Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 79.2% 498 / 0 / 629
Functions: -% 0 / 1 / 1
Branches: 69.7% 297 / 0 / 426

OMCompiler/Compiler/BackEnd/CommonSubExpression.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package CommonSubExpression
37 " file: CommonSubExpression.mo
38 package: CommonSubExpression
39 description: This package contains functions for the optimization modules
40 wrapFunctionCalls, commonSubExpressionReplacement and cseBinary."
41
42
43 public
44 import BackendDAE;
45 import DAE;
46
47 protected
48 import Array;
49 import AvlSetInt;
50 import BackendDAEUtil;
51 import BackendDump;
52 import BackendEquation;
53 import BackendVarTransform;
54 import BackendVariable;
55 import BaseHashTable;
56 import ComponentReference;
57 import ComponentReferenceBasics;
58 import DAEUtil;
59 import ExpandableArray;
60 import Expression;
61 protected import ExpressionBasics;
62 import ExpressionDump;
63 import ExpressionSolve;
64 import ExpressionSimplify;
65 import GCExt;
66 import Global;
67 import HashSet;
68 import HashTableExpToExp;
69 import HashTableExpToIndex;
70 import HpcOmTaskGraph;
71 import List;
72 import ResolveLoops;
73 import StringUtil;
74 import Types;
75 import TypesDump;
76 import UnorderedSet;
77
78 uniontype CSE_Equation
79 record CSE_EQUATION
80 DAE.Exp cse "lhs";
81 DAE.Exp call "rhs";
82 list<Integer> dependencies;
83 end CSE_EQUATION;
84 end CSE_Equation;
85
86 constant CSE_Equation dummy_equation = CSE_EQUATION(DAE.RCONST(0.0), DAE.RCONST(0.0), {});
87 constant Boolean debug = false;
88 constant String BORDER = "###############################################################";
89 constant String UNDERLINE = "========================================";
90
91 protected function printCSEEquation
92 input CSE_Equation cseEquation;
93 output String str;
94 protected
95 Boolean first = true;
96 algorithm
97 58 str := ExpressionBasics.printExpStr(cseEquation.cse) + " - " + ExpressionBasics.printExpStr(cseEquation.call) + " - {";
98
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 for i in cseEquation.dependencies loop
100 ✗ if first then
101 ✗ str := str + intString(i);
102 first := false;
103 else
104 ✗ str := str + ", " + intString(i);
105 end if;
106 end for;
107
108 58 str := str + "}";
109 end printCSEEquation;
110
111 public function wrapFunctionCalls "
112 This function traverses the equation systems and looks for function calls to store in $cse variables.
113 This avoids unnecessary function evaluations.
114 Main function: is called by postOpt and SymbolicJacobian
115 authors: Jan Hagemann, Lennart Ochel and Patrick Täuber (FH Bielefeld, Germany)"
116 input BackendDAE.BackendDAE inDAE;
117 output BackendDAE.BackendDAE outDAE;
118 protected
119 Integer size;
120 HashTableExpToIndex.HashTable HT "call -> index";
121 ExpandableArray<CSE_Equation> exarray "id -> (cse, call, dependencies)";
122
123 Integer cseIndex = System.tmpTickIndex(Global.backendDAE_cseIndex);
124 Integer index;
125
126 BackendDAE.Shared shared;
127 AvlTreePathFunction.Tree functionTree;
128 BackendDAE.EquationArray orderedEqs, orderedEqs_new;
129 BackendDAE.Variables orderedVars, globalKnownVars;
130 list<BackendDAE.EqSystem> eqSystems = {};
131 String daeTypeStr = BackendDump.printBackendDAEType2String(inDAE.shared.backendDAEType);
132 Boolean isSimulationDAE = stringEq(daeTypeStr, "simulation");
133 // A Jacobian's own globalKnownVars never reach SimCode, so a call there stays an equation.
134 Boolean allowGlobalKnown = not stringEq(daeTypeStr, "jacobian");
135
136 HashSet.HashSet globalKnownVarHT;
137
138 algorithm
139 2808 size := BackendDAEUtil.maxSizeOfEqSystems(inDAE.eqs) + 42; //create data structures independent from the size of the EqSystem
140 2808 exarray := ExpandableArray.new(size, dummy_equation);
141
142 2808 size := Util.nextPrime(realInt(2.4*size));
143 2808 HT := HashTableExpToIndex.emptyHashTableSized(size);
144
145 2808 shared := inDAE.shared;
146 2808 BackendDAE.SHARED(globalKnownVars=globalKnownVars,functionTree=functionTree) := shared;
147
148 // Create Hashtable and store globally known variables in it
149 2808 globalKnownVarHT := HashSet.emptyHashSetSized(Util.nextPrime(realInt(2.4*(globalKnownVars.numberOfVars + 42))));
150
2/2
✓ Branch 0 taken 1066 times.
✓ Branch 1 taken 1742 times.
2808 if isSimulationDAE then
151 1066 globalKnownVarHT := BackendVariable.traverseBackendDAEVars(globalKnownVars, VarToGlobalKnownVarHT, globalKnownVarHT);
152 end if;
153
154
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2808 times.
2808 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
155 ✗ print("Start optimization module wrapFunctionCalls for " + daeTypeStr + " DAE\n" + BORDER + BORDER + "\n\n\n");
156 ✗ print("Phase 0: Set up data structure\n" + BORDER + "\n");
157 ✗ BackendDump.dumpVariables(globalKnownVars, "globalKnownVars before WFC");
158 ✗ print("globalKnownVarHT before algorithm\n" + UNDERLINE + "\n");
159 ✗ BaseHashSet.dumpHashSet(globalKnownVarHT);
160 end if;
161
162 // Start the WFC algorithm for all equation systems
163
2/2
✓ Branch 0 taken 3302 times.
✓ Branch 1 taken 2808 times.
6110 for syst in inDAE.eqs loop
164
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3302 times.
3302 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
165 ✗ print("\n\nHandle system (belongs to " + daeTypeStr + " DAE):\n" + BORDER + "\n");
166 ✗ BackendDump.dumpVariables(syst.orderedVars, "Variables");
167 ✗ BackendDump.dumpEquationArray(syst.orderedEqs, "Equations");
168 ✗ print("\nPhase 1: Analysis\n" + BORDER + "\n");
169 end if;
170
171 3302 HT := BaseHashTable.clear(HT);
172 3302 exarray := ExpandableArray.clear(exarray);
173 index := 0;
174
175 3302 orderedEqs := syst.orderedEqs;
176 3302 orderedVars := syst.orderedVars;
177
178 // Phase 1: Analysis
179 3302 (HT, exarray, cseIndex, index, _) := BackendEquation.traverseEquationArray(orderedEqs, wrapFunctionCalls_analysis, (HT, exarray, cseIndex, index, functionTree));
180
181
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3302 times.
3302 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
182 ✗ print("Hastable after analysis\n" + UNDERLINE + "\n");
183 ✗ BaseHashTable.dumpHashTable(HT);
184 ✗ print(ExpandableArray.toString(exarray, "\nExpandable Array after analysis", printCSEEquation));
185 end if;
186
187
2/2
✓ Branch 0 taken 769 times.
✓ Branch 1 taken 2533 times.
3302 if index > 0 then
188 // Phase 2: Dependencies
189 769 exarray := determineDependencies(exarray, HT);
190
191
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 769 times.
769 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
192 ✗ print("\n\nPhase 2: Dependencies\n" + BORDER + "\n\n");
193 ✗ print("Hashtable after dependencies\n" + UNDERLINE + "\n");
194 ✗ BaseHashTable.dumpHashTable(HT);
195 ✗ print(ExpandableArray.toString(exarray, "\nExpandable Array after dependencies", printCSEEquation));
196 ✗ print("\n\nPhase3: Substitution\n" + BORDER + "\n");
197 end if;
198
199 // Phase 3: Substitution
200 769 orderedEqs_new := BackendEquation.emptyEqnsSized(ExpandableArray.getNumberOfElements(orderedEqs) + ExpandableArray.getNumberOfElements(exarray));
201 769 (HT, exarray, orderedEqs_new) := BackendEquation.traverseEquationArray(orderedEqs, wrapFunctionCalls_substitution, (HT, exarray, orderedEqs_new));
202
203
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 769 times.
769 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
204 ✗ print("Hashtable after substitution\n" + UNDERLINE + "\n");
205 ✗ BaseHashTable.dumpHashTable(HT);
206 ✗ print(ExpandableArray.toString(exarray, "\nExpandable Array after substitution", printCSEEquation));
207 ✗ print("\n\nPhase 4: Create CSE-Equations\n" + BORDER + "\n\n");
208 end if;
209
210 // Phase 4: Create CSE equations
211 769 (orderedEqs_new, orderedVars, globalKnownVars) := createCseEquations(exarray, orderedEqs_new, orderedVars, globalKnownVars, globalKnownVarHT, allowGlobalKnown);
212
213 769 syst.orderedEqs := orderedEqs_new;
214 syst.orderedVars := orderedVars;
215
216 // Check for unbalanced system
217
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 769 times.
769 if not intEq(BackendEquation.equationArraySize(orderedEqs_new), orderedVars.numberOfVars) then
218 ✗ Error.addCompilerWarning("After manipulating the system with postOptModule wrapFunctionCalls the system is unbalanced. This indicates that the original system is singular. You can use -d=dumpCSE and -d=dumpCSE_verbose for more information.");
219 end if;
220
221 // Reset Matching
222 769 syst.m := NONE();
223 syst.mT := NONE();
224 syst.matching := BackendDAE.NO_MATCHING();
225
226
3/4
✓ Branch 1 taken 742 times.
✓ Branch 2 taken 27 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 742 times.
769 if Flags.isSet(Flags.DUMP_CSE) or Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
227 27 print("\n\n\n" + BORDER + "\nFinal Results\n" + BORDER + "\n");
228 27 BackendDump.dumpVariables(syst.orderedVars, "########### Updated Variable List (" + BackendDump.printBackendDAEType2String(shared.backendDAEType) + ")");
229 27 BackendDump.dumpEquationArray(syst.orderedEqs, "########### Updated Equation List (" + BackendDump.printBackendDAEType2String(shared.backendDAEType) + ")");
230 27 BackendDump.dumpVariables(globalKnownVars, "########### Updated globalKnownVars (" + BackendDump.printBackendDAEType2String(shared.backendDAEType) + ")");
231 27 print(ExpandableArray.toString(exarray, "\n########### CSE Replacements", printCSEEquation));
232 end if;
233
234
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 769 times.
769 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
235 ✗ print("\n\n" + BORDER);
236 ✗ BackendDump.dumpEqSystem(syst, "Final EqSystem");
237 end if;
238 else
239
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2533 times.
2533 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
240 ✗ print("\n" + BORDER + "\nNo function calls found. Exiting the algorithm...\n\n\n");
241 end if;
242 end if;
243
244 eqSystems := syst::eqSystems;
245 end for;
246
247 2808 shared.globalKnownVars := globalKnownVars;
248
249 2808 System.tmpTickSetIndex(cseIndex, Global.backendDAE_cseIndex);
250 2808 eqSystems := MetaModelica.Dangerous.listReverseInPlace(eqSystems);
251 2808 outDAE := BackendDAE.DAE(eqSystems, shared);
252 end wrapFunctionCalls;
253
254 protected function VarToGlobalKnownVarHT
255 " Adds all globalKnownVars with bindExp to globalKnownVarHT except inputs and nonfixed parameters"
256 input BackendDAE.Var inVar;
257 input HashSet.HashSet inGlobalKnownVarHT;
258 output BackendDAE.Var outVar = inVar;
259 output HashSet.HashSet outGlobalKnownVarHT = inGlobalKnownVarHT;
260 algorithm
261 // To-Do: Move inputs to localKnownVars
262
9/10
✓ Branch 1 taken 295 times.
✓ Branch 2 taken 183078 times.
✓ Branch 4 taken 132660 times.
✓ Branch 5 taken 50418 times.
✓ Branch 7 taken 1680 times.
✓ Branch 8 taken 130980 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 181398 times.
✓ Branch 11 taken 181310 times.
✓ Branch 12 taken 88 times.
183373 if not BackendVariable.isInput(inVar) and not (BackendVariable.isParam(inVar) and not BackendVariable.varFixed(inVar)) and isSome(inVar.bindExp) then
263 181310 outGlobalKnownVarHT := BaseHashSet.add(BackendVariable.varCref(inVar), inGlobalKnownVarHT);
264 end if;
265 end VarToGlobalKnownVarHT;
266
267 protected function findCallsInGlobalKnownVars
268 "This function traverses the globalKnownVars and looks for function calls. The calls are stored in the HT/expArray"
269 input BackendDAE.Var inVar;
270 input tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer, Integer, AvlTreePathFunction.Tree> inTuple;
271 output BackendDAE.Var outVar = inVar;
272 output tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer, Integer, AvlTreePathFunction.Tree> outTuple = inTuple;
273 protected
274 DAE.Exp exp;
275 BackendDAE.Equation eq;
276 algorithm
277 // To-Do: Move inputs to localKnownVars
278 ✗ if not BackendVariable.isInput(inVar) and not (BackendVariable.isParam(inVar) and not BackendVariable.varFixed(inVar)) and isSome(inVar.bindExp) then
279 ✗ SOME(exp):= inVar.bindExp;
280 ✗ if isCall(exp) then
281 ✗ eq := BackendEquation.generateEquation(DAE.CREF(inVar.varName, inVar.varType), exp);
282 ✗ (_, outTuple) := wrapFunctionCalls_analysis(eq, inTuple);
283 end if;
284 end if;
285 end findCallsInGlobalKnownVars;
286
287 protected function wrapFunctionCalls_substitution
288 "Third phase of the WFC algorithm: The found function calls in the equation system which are stored in the HT are replaced by its cse-variables."
289 input BackendDAE.Equation inEq;
290 input tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, BackendDAE.EquationArray> inTuple;
291 output BackendDAE.Equation outEq = inEq;
292 output tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, BackendDAE.EquationArray> outTuple;
293 protected
294 HashTableExpToIndex.HashTable HT;
295 ExpandableArray<CSE_Equation> exarray;
296 BackendDAE.EquationArray orderedEqs_new;
297 BackendDAE.Equation eq;
298 algorithm
299
3/3
✓ Branch 0 taken 439 times.
✓ Branch 1 taken 42633 times.
✓ Branch 2 taken 379 times.
43451 (HT, exarray, orderedEqs_new) := inTuple;
300
301 () := match inEq
302 case BackendDAE.COMPLEX_EQUATION() algorithm
303
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 439 times.
439 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
304 ✗ BackendDump.dumpEquationList({inEq}, "wrapFunctionCalls_substitution (COMPLEX_EQUATION)");
305 end if;
306
307 439 (eq, (HT, exarray, orderedEqs_new)) := BackendEquation.traverseExpsOfEquation(inEq, wrapFunctionCalls_substitution2, (HT, exarray, orderedEqs_new));
308
309
2/2
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 281 times.
439 if not isEquationRedundant(eq) then
310 158 orderedEqs_new := BackendEquation.add(eq, orderedEqs_new);
311
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
158 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
312 ✗ BackendDump.dumpEquationList({eq}, "isEquationRedundant? no");
313 end if;
314 else
315
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 281 times.
281 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
316 ✗ BackendDump.dumpEquationList({eq}, "isEquationRedundant? yes");
317 end if;
318 end if;
319 then ();
320
321 case BackendDAE.EQUATION() algorithm
322
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42633 times.
42633 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
323 ✗ BackendDump.dumpEquationList({inEq}, "wrapFunctionCalls_substitution (EQUATION)");
324 end if;
325
326 42633 (eq, (HT, exarray, orderedEqs_new)) := BackendEquation.traverseExpsOfEquation(inEq, wrapFunctionCalls_substitution2, (HT, exarray, orderedEqs_new));
327
328
2/2
✓ Branch 1 taken 39858 times.
✓ Branch 2 taken 2775 times.
42633 if not isEquationRedundant(eq) then
329 39858 orderedEqs_new := BackendEquation.add(eq, orderedEqs_new);
330 end if;
331 then ();
332
333 // all other cases are not handled (e.g. algorithms)
334 else algorithm
335 379 orderedEqs_new := BackendEquation.add(inEq, orderedEqs_new);
336 then ();
337 end match;
338
339 43451 outTuple := (HT, exarray, orderedEqs_new);
340 end wrapFunctionCalls_substitution;
341
342 protected function wrapFunctionCalls_substitution2
343 input DAE.Exp inExp;
344 input tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, BackendDAE.EquationArray> inTuple;
345 output DAE.Exp outExp;
346 output tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, BackendDAE.EquationArray> outTuple;
347 algorithm
348 86144 (outExp, outTuple) := Expression.traverseExpBottomUp(inExp, wrapFunctionCalls_substitution3, inTuple);
349 end wrapFunctionCalls_substitution2;
350
351 protected function wrapFunctionCalls_substitution3
352 input DAE.Exp inExp;
353 input tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, BackendDAE.EquationArray> inTuple;
354 output DAE.Exp outExp;
355 output tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, BackendDAE.EquationArray> outTuple;
356 protected
357 HashTableExpToIndex.HashTable HT;
358 ExpandableArray<CSE_Equation> exarray;
359 BackendDAE.EquationArray orderedEqs_new;
360 Integer id, ix;
361 DAE.Exp cse, call, tmp;
362 list<DAE.Exp> PR;
363 list<Integer> dependencies;
364 algorithm
365 691184 (HT, exarray, orderedEqs_new) := inTuple;
366
367
4/4
✓ Branch 1 taken 25062 times.
✓ Branch 2 taken 666122 times.
✓ Branch 4 taken 13712 times.
✓ Branch 5 taken 11350 times.
691184 if Expression.isCall(inExp) and BaseHashTable.hasKey(inExp, HT) then
368 13712 id := BaseHashTable.get(inExp, HT);
369 13712 CSE_EQUATION(cse=cse, call=call, dependencies=dependencies) := ExpandableArray.get(id, exarray);
370 13712 (HT, exarray) := substituteDependencies(dependencies, HT, exarray, call, cse);
371 13712 ExpandableArray.update(id, CSE_EQUATION(cse, call, {}), exarray);
372 13712 outExp := cse;
373 elseif Expression.isTSUB(inExp) then
374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 DAE.TSUB(exp=tmp, ix=ix) := inExp;
375
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 if Expression.isTuple(tmp) then
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 DAE.TUPLE(PR) := tmp;
377 10 outExp := listGet(PR, ix);
378 else
379 outExp := inExp;
380 end if;
381 else
382 outExp := inExp;
383 end if;
384
385 691184 outTuple := (HT, exarray, orderedEqs_new);
386 end wrapFunctionCalls_substitution3;
387
388 protected function substituteDependencies
389 input list<Integer> inDependencies;
390 input output HashTableExpToIndex.HashTable ht;
391 input output ExpandableArray<CSE_Equation> exarray;
392 input DAE.Exp inCall;
393 input DAE.Exp inCSE;
394 protected
395 DAE.Exp cse, call;
396 list<Integer> dependencies;
397
398 DAE.Exp cse2, call2;
399 list<Integer> dependencies2;
400
401 Integer id2;
402 algorithm
403
2/2
✓ Branch 0 taken 699 times.
✓ Branch 1 taken 13712 times.
14411 for id in inDependencies loop
404 699 CSE_EQUATION(cse=cse, call=call, dependencies=dependencies) := ExpandableArray.get(id, exarray);
405 699 call := substituteExp(call, inCall, inCSE);
406
407 //ExpandableArray.toString(exarray, "substituteDependencies", printCSEEquation);
408 //print("Exp: " + ExpressionBasics.printExpStr(call) + "\n");
409
410
2/2
✓ Branch 1 taken 698 times.
✓ Branch 2 taken 1 time.
699 if not BaseHashTable.hasKey(call, ht) then
411 698 ht := BaseHashTable.add((call, id), ht);
412 698 ExpandableArray.update(id, CSE_EQUATION(cse, call, dependencies), exarray);
413 else
414 1 id2 := BaseHashTable.get(call, ht);
415 1 CSE_EQUATION(cse=cse2, call=call2, dependencies=dependencies2) := ExpandableArray.get(id2, exarray);
416 1 cse2 := mergeCSETuples(cse, cse2);
417 1 ExpandableArray.update(id2, CSE_EQUATION(cse2, call, UnorderedSet.unique_list(listAppend(dependencies,dependencies2), Util.id, intEq)), exarray);
418 1 ExpandableArray.update(id, CSE_EQUATION(cse, cse2, {}), exarray);
419
420
421 //print("substituteDependencies: not handled yet\n");
422 //print("id: " + intString(id) + "\n");
423 //print("inCall: " + ExpressionBasics.printExpStr(inCall) + "\n");
424 //print("inCSE: " + ExpressionBasics.printExpStr(inCSE) + "\n");
425 //BaseHashTable.dumpHashTable(ht);
426 //ExpandableArray.toString(exarray, "substituteDependencies", printCSEEquation);
427 end if;
428 end for;
429 end substituteDependencies;
430
431 protected function substituteExp
432 input DAE.Exp inExp;
433 input DAE.Exp inKey;
434 input DAE.Exp inValue;
435 output DAE.Exp outExp;
436 algorithm
437 699 outExp := Expression.traverseExpTopDown(inExp, substituteExp2, (inKey, inValue));
438 end substituteExp;
439
440 protected function substituteExp2
441 input DAE.Exp inExp;
442 input tuple<DAE.Exp, DAE.Exp> inTuple;
443 output DAE.Exp outExp;
444 output Boolean cont;
445 output tuple<DAE.Exp, DAE.Exp> outTuple = inTuple;
446 protected
447 DAE.Exp key, value, tmp;
448 list<DAE.Exp> expList;
449 Integer ix;
450 algorithm
451 8666 (key, value) := inTuple;
452
453
2/2
✓ Branch 1 taken 7858 times.
✓ Branch 2 taken 808 times.
8666 if ExpressionBasics.expEqual(inExp, key) then
454 outExp := value;
455 cont := false;
456 elseif Expression.isTSUB(inExp) then
457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 DAE.TSUB(exp=tmp, ix=ix) := inExp;
458
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if ExpressionBasics.expEqual(tmp, key) then
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 DAE.TUPLE(expList) := value;
460 1 outExp := listGet(expList, ix);
461 cont := false;
462 else
463 outExp := inExp;
464 cont := true;
465 end if;
466 else
467 outExp := inExp;
468 cont := true;
469 end if;
470 end substituteExp2;
471
472 protected function createCseEquations
473 " Fourth phase of the WFC algorithm:
474 Creates CSE equations from the expandable array and stores them in the correct data structure:
475 1) cse var (i.e. function call) with $cse-prefix is dependending on variables
476 -> store eqn in orderedEqs and var in orderedVars
477 2) cse var (i.e. function call) without $cse-prefix is dependending on variables
478 -> store eqn in orderedEqs
479 3) cse var (i.e. function call) with $cse-prefix is only dependending on globally known variables
480 -> store var in globalKnownVars (bindExp=call)
481 4) cse var (i.e. function call) without $cse-prefix is only dependending on globally known variables
482 -> store var in globalKnownVars (bindExp=call) and delete var from orderedVars
483 author: ptaeuber"
484 input ExpandableArray<CSE_Equation> exarray "id -> (cse, call, dependencies)";
485 input output BackendDAE.EquationArray orderedEqs "equations of the system";
486 input output BackendDAE.Variables orderedVars;
487 input output BackendDAE.Variables globalKnownVars;
488 input output HashSet.HashSet globalKnownVarHT;
489 input Boolean allowGlobalKnown;
490 protected
491 DAE.Exp cse, call;
492 BackendDAE.Equation eq;
493 DAE.ComponentRef cr;
494 BackendDAE.Var var;
495 list<BackendDAE.Var> varList, delVars;
496 Boolean isGlobalKnown, eqRedundant, add;
497 algorithm
498
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 769 times.
769 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
499 ✗ print("globalKnownVars:\n" + UNDERLINE + "\n");
500 ✗ BaseHashSet.dumpHashSet(globalKnownVarHT);
501 ✗ print("\nTraverse expandable array\n" + UNDERLINE + "\n");
502 end if;
503
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 769 times.
6556 for i in ExpandableArray.getNumberOfElements(exarray):-1:1 loop
504 add := true;
505 5787 CSE_EQUATION(cse=cse, call=call) := ExpandableArray.get(i, exarray);
506
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5787 times.
5787 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
507 ✗ print("\n--> cse-equation: " + ExpressionBasics.printExpStr(cse) + " = " + ExpressionBasics.printExpStr(call) + "\n");
508 end if;
509
510 5787 eq := BackendEquation.generateEquation(cse, call);
511 5787 (globalKnownVarHT, globalKnownVars, orderedVars, eqRedundant, isGlobalKnown) := isEquationRedundant_flatten(eq, globalKnownVarHT, globalKnownVars, orderedVars, allowGlobalKnown);
512
513 if debug then print("\ndebug 1 - eq redundant?\n"); end if;
514
2/2
✓ Branch 0 taken 5786 times.
✓ Branch 1 taken 1 time.
5787 if not eqRedundant then
515 if debug then print("\ndebug 2 - no, not redundant. let's loop\n"); end if;
516 5786 varList := createVarsForExp(cse);
517 // If cse is a constant number add the equation
518
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 5778 times.
5786 if listEmpty(varList) then
519 8 orderedEqs := BackendEquation.add(eq, orderedEqs);
520 else
521
2/2
✓ Branch 0 taken 14152 times.
✓ Branch 1 taken 5778 times.
19930 for var in varList loop
522 if debug then print("\ndebug 3 - handle var: " + BackendDump.varString(var) + " Is it a globalKnownVar?\n"); end if;
523 14152 cr := BackendVariable.varCref(var);
524 // Variable is not in globalKnownVars HT
525
2/2
✓ Branch 0 taken 12809 times.
✓ Branch 1 taken 1343 times.
14152 if not isGlobalKnown then
526 if debug then print("\ndebug 4 - The variable is not a globalKnownVar. Should an equation be added?\n"); end if;
527
2/2
✓ Branch 0 taken 5543 times.
✓ Branch 1 taken 7266 times.
12809 if add then
528 if debug then print("\ndebug 5 - yes, definitely!\n"); end if;
529 5543 orderedEqs := BackendEquation.add(eq, orderedEqs);
530 add := false;
531 end if;
532 if debug then print("\ndebug 6 - Is this cref a CSE cref?: " + ExpressionBasics.printExpStr(Expression.crefExp(cr)) + "\n"); end if;
533
2/2
✓ Branch 1 taken 8428 times.
✓ Branch 2 taken 4381 times.
12809 if isCSECref(cr) then
534 if debug then print("\ndebug 7 - yes it is a CSE cref. Add to orderedVars!\n"); end if;
535 8428 orderedVars := BackendVariable.addVar(var, orderedVars);
536 end if;
537 if debug then print("\ndebug 8\n"); end if;
538
539 // Variable is in globalKnownVars HT: Add it to globalKnownVars and not to ordered vars and do not create a cse-equation
540 else
541 if debug then print("\ndebug 9 - The variable is a globalKnownVar.\n"); end if;
542
543
2/2
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 918 times.
1343 if not isCSECref(cr) then
544 if debug then print("\ndebug 10 - The globalKnownVar is no CSE cref, so copy attributes and delete it from orderedVars if it is in that list.\n"); end if;
545 425 (delVars, orderedVars) := BackendVariable.deleteVarIfExistsAndReturn(cr, orderedVars);
546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 425 times.
425 if listEmpty(delVars) then
547 ✗ (delVars, _) := BackendVariable.getVar(cr, globalKnownVars);
548 end if;
549 425 var := listGet(delVars, 1);
550 end if;
551
552 // Save the rhs (call) as bind expression and set fixed=true
553 1343 var := BackendVariable.setBindExp(var, SOME(call));
554 1343 var := BackendVariable.makeParam(var);
555 1343 var := BackendVariable.setVarFinal(var, true) "make final so var is not changeable after compilation";
556
557 // If it is a tuple or a record (or record within tuple)
558
4/4
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 1202 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 140 times.
1343 if intGt(listLength(varList), 1) or Expression.isTuple(cse) then
559 if debug then print("\ndebug 11 - It is a tuple! Add it to tplExp\n"); end if;
560 1203 var.tplExp := SOME(cse);
561 end if;
562
563 if debug then print("\ndebug 12 - Add the variable to globalKnownVars\n"); end if;
564 // Add var to globalKnownVars
565 1343 globalKnownVars := BackendVariable.addVar(var, globalKnownVars);
566
567 end if;
568 end for;
569 end if;
570 end if;
571 end for;
572 if debug then print("\ndebug 13\n"); end if;
573 end createCseEquations;
574
575 protected function determineDependencies
576 "Second phase of the WFC algorithm: Finds the dependencies between nested function calls and stores them in the expandable array."
577 input output ExpandableArray<CSE_Equation> exarray "id -> (cse, call, dependencies)";
578 input HashTableExpToIndex.HashTable HT "call -> index";
579 protected
580 list<DAE.Exp> callArguments;
581 algorithm
582
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 769 times.
769 for i in 1:ExpandableArray.getNumberOfElements(exarray) loop
583
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5787 times.
5787 CSE_EQUATION(call=DAE.CALL(expLst=callArguments)) := ExpandableArray.get(i, exarray);
584 5787 (_, (_, exarray, _)) := Expression.traverseExpList(callArguments, determineDependencies2, (HT, exarray, i));
585 end for;
586 end determineDependencies;
587
588 protected function determineDependencies2
589 input DAE.Exp inExp;
590 input tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer> inTuple;
591 output DAE.Exp outExp = inExp;
592 output tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer> outTuple;
593 protected
594 Integer id, index;
595 list<Integer> dependencies;
596 HashTableExpToIndex.HashTable HT;
597 ExpandableArray<CSE_Equation> exarray;
598 DAE.Exp cse, call;
599 algorithm
600
2/2
✓ Branch 1 taken 1570 times.
✓ Branch 2 taken 63416 times.
64986 if Expression.isCall(inExp) then
601 1570 (HT, exarray, index) := inTuple;
602
603
2/2
✓ Branch 1 taken 809 times.
✓ Branch 2 taken 761 times.
1570 if BaseHashTable.hasKey(inExp, HT) then
604 809 id := BaseHashTable.get(inExp, HT);
605 809 CSE_EQUATION(cse=cse, call=call, dependencies=dependencies) := ExpandableArray.get(id, exarray);
606
2/2
✓ Branch 1 taken 699 times.
✓ Branch 2 taken 110 times.
809 if not listMember(index, dependencies) then
607 dependencies := index::dependencies;
608 699 ExpandableArray.update(id, CSE_EQUATION(cse, call, dependencies), exarray);
609 end if;
610 end if;
611
612 1570 outTuple := (HT, exarray, index);
613 else
614 outTuple := inTuple;
615 end if;
616 end determineDependencies2;
617
618 protected function allArgsInGlobalKnownVars
619 "Returns true if all call arguments are globally known"
620 input list<DAE.Exp> callArgs;
621 input HashSet.HashSet globalKnownVarHT;
622 output Boolean allCrefsAreGlobal = true;
623 protected
624 list<DAE.ComponentRef> crefList;
625 algorithm
626 5292 (_,crefList) := Expression.traverseExpList(callArgs, Expression.traversingComponentRefFinder, {});
627
2/2
✓ Branch 0 taken 9541 times.
✓ Branch 1 taken 2079 times.
11620 for cr in crefList loop
628
2/2
✓ Branch 0 taken 6328 times.
✓ Branch 1 taken 3213 times.
9541 if allCrefsAreGlobal then
629 6328 allCrefsAreGlobal := BaseHashSet.has(cr, globalKnownVarHT);
630 else
631 3213 return;
632 end if;
633 end for;
634 end allArgsInGlobalKnownVars;
635
636 protected function addConstantCseVarsToGlobalKnownVarHT
637 "Adds the cse variable to the globalKnownVarHT. For tuples the crefs are stored separately.
638 author: ptaeuber"
639 input DAE.Exp cse_crExp;
640 input output HashSet.HashSet globalKnownVarHT;
641 algorithm
642 () := match cse_crExp
643 local
644 list<DAE.Exp> expLst;
645 DAE.ComponentRef cr;
646 list<DAE.ComponentRef> crefs;
647
648 case DAE.TUPLE(PR = expLst)
649 algorithm
650 ✗ for exp in expLst loop
651 ✗ if Expression.isNotWild(exp) then
652 ✗ globalKnownVarHT := addConstantCseVarsToGlobalKnownVarHT(exp, globalKnownVarHT);
653 end if;
654 end for;
655 then ();
656
657 case DAE.CALL(expLst = expLst)
658 algorithm
659 ✗ for exp in expLst loop
660 ✗ if Expression.isNotWild(exp) then
661 ✗ globalKnownVarHT := addConstantCseVarsToGlobalKnownVarHT(exp, globalKnownVarHT);
662 end if;
663 end for;
664 then();
665
666 case DAE.RECORD(exps = expLst)
667 algorithm
668
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for exp in expLst loop
669
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if Expression.isNotWild(exp) then
670 1 globalKnownVarHT := addConstantCseVarsToGlobalKnownVarHT(exp, globalKnownVarHT);
671 end if;
672 end for;
673 then();
674
675 case DAE.CREF(componentRef=cr, ty = DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_)))
676 algorithm
677 105 globalKnownVarHT := BaseHashSet.add(cr, globalKnownVarHT);
678 105 crefs := ComponentReference.expandCref(cr, true /*the way it is now we won't get records here. but if we do somehow expand them*/);
679
680
2/2
✓ Branch 0 taken 1269 times.
✓ Branch 1 taken 105 times.
1374 for cr_ in crefs loop
681 1269 globalKnownVarHT := BaseHashSet.add(cr_, globalKnownVarHT);
682 end for;
683 then ();
684
685 case DAE.CREF(componentRef=cr) guard(Expression.isArrayType(Expression.typeof(cse_crExp)))
686 algorithm
687 14 globalKnownVarHT := BaseHashSet.add(cr, globalKnownVarHT);
688 14 crefs := ComponentReference.expandCref(cr, true);
689
690
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 14 times.
52 for cr_ in crefs loop
691 38 globalKnownVarHT := BaseHashSet.add(cr_, globalKnownVarHT);
692 end for;
693 then ();
694
695 case DAE.CREF(componentRef=cr)
696 algorithm
697 144 globalKnownVarHT := BaseHashSet.add(cr, globalKnownVarHT);
698 then ();
699
700 else algorithm
701 ✗ Error.addInternalError("addConstantCseVarsToGlobalKnownVarHT failed. Reached else case that should not be reachable while handling CSE expression:\n" + ExpressionDump.dumpExpStr(cse_crExp, 0), sourceInfo());
702 ✗ fail();
703 then();
704 end match;
705 end addConstantCseVarsToGlobalKnownVarHT;
706
707 protected function wrapFunctionCalls_analysis
708 "First phase of the WFC algorithm: The equation system is traversed and all occuring function calls are stored in the HT and the expandable array."
709 input BackendDAE.Equation inEq;
710 input tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer, Integer, AvlTreePathFunction.Tree> inTuple;
711 output BackendDAE.Equation outEq = inEq;
712 output tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer, Integer, AvlTreePathFunction.Tree> outTuple;
713 protected
714 AvlTreePathFunction.Tree functionTree;
715 HashTableExpToIndex.HashTable HT;
716 ExpandableArray<CSE_Equation> exarray;
717
718 Integer cseIndex, exIndex, index, ix;
719 DAE.Exp lhs, rhs;
720 DAE.Exp cref, call;
721 DAE.Exp exp;
722 DAE.Type ty;
723 list<DAE.Type> types;
724 CSE_Equation cseEquation;
725 algorithm
726
3/3
✓ Branch 0 taken 447 times.
✓ Branch 1 taken 68405 times.
✓ Branch 2 taken 1040 times.
69892 (HT, exarray, cseIndex, index, functionTree) := inTuple;
727
728 () := match inEq
729 case BackendDAE.COMPLEX_EQUATION(left=lhs, right=rhs) algorithm
730
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 447 times.
447 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
731 ✗ BackendDump.dumpEquationList({inEq}, "wrapFunctionCalls_analysis (COMPLEX_EQUATION)");
732 end if;
733
734 // TUPLE = CALL
735 // ************
736
2/2
✓ Branch 1 taken 246 times.
✓ Branch 2 taken 201 times.
447 if isCallAndTuple(lhs, rhs) then
737 246 (cref, call) := getTheRightPattern(lhs, rhs);
738
739 // Tuple is already in HT
740
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 241 times.
246 if BaseHashTable.hasKey(call, HT) then
741 5 exIndex := BaseHashTable.get(call, HT);
742 5 cseEquation := ExpandableArray.get(exIndex, exarray);
743 5 cseEquation.cse := mergeCSETuples(cseEquation.cse, cref);
744 5 exarray := ExpandableArray.update(exIndex, cseEquation, exarray);
745
746 // Tuple is not already in HT
747 elseif not isSkipCase(call, functionTree) then
748 234 index := index + 1;
749 234 HT := BaseHashTable.add((call, index), HT);
750 234 exarray := ExpandableArray.set(index, CSE_EQUATION(cref, call, {}), exarray);
751 end if;
752
753 // RECORD = CALL
754 // *************
755 elseif isCallAndRecord(lhs, rhs) then
756 48 (cref, call) := getTheRightPattern(lhs, rhs);
757
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 48 times.
48 if BaseHashTable.hasKey(call, HT) then
758 ✗ exIndex := BaseHashTable.get(call, HT);
759 ✗ cseEquation := ExpandableArray.get(exIndex, exarray);
760 ✗ cseEquation.cse := cref;
761 ✗ exarray := ExpandableArray.update(exIndex, cseEquation, exarray);
762
763 elseif not isSkipCase(call, functionTree) then
764 46 index := index + 1;
765 46 HT := BaseHashTable.add((call, index), HT);
766 46 exarray := ExpandableArray.set(index, CSE_EQUATION(cref, call, {}), exarray);
767 end if;
768 end if;
769
770 447 (_, (HT, exarray, cseIndex, index, functionTree)) := BackendEquation.traverseExpsOfEquation(inEq, wrapFunctionCalls_analysis2, (HT, exarray, cseIndex, index, functionTree));
771 then ();
772
773 case BackendDAE.EQUATION(exp=lhs, scalar=rhs) algorithm
774
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68405 times.
68405 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
775 ✗ BackendDump.dumpEquationList({inEq}, "wrapFunctionCalls_analysis (EQUATION)");
776 end if;
777
778 // CREF = CALL or CONST = CALL
779 // ***************************
780
4/4
✓ Branch 1 taken 63449 times.
✓ Branch 2 taken 4956 times.
✓ Branch 4 taken 119 times.
✓ Branch 5 taken 63330 times.
68405 if isCallAndCref(lhs, rhs) or isConstAndCall(lhs, rhs) then
781 5075 (cref, call) := getTheRightPattern(lhs, rhs);
782
783
2/2
✓ Branch 1 taken 127 times.
✓ Branch 2 taken 4948 times.
5075 if BaseHashTable.hasKey(call, HT) then
784 127 exIndex := BaseHashTable.get(call, HT);
785 127 cseEquation := ExpandableArray.get(exIndex, exarray);
786 127 cseEquation.cse := cref;
787 127 exarray := ExpandableArray.update(exIndex, cseEquation, exarray);
788
789 elseif not isSkipCase(call, functionTree) then
790 2726 index := index + 1;
791 2726 HT := BaseHashTable.add((call, index), HT);
792 2726 exarray := ExpandableArray.set(index, CSE_EQUATION(cref, call, {}), exarray);
793 end if;
794
795 // CREF = TSUB
796 // ***********
797 elseif isTsubAndCref(lhs, rhs) then
798
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
3 (cref, DAE.TSUB(call as DAE.CALL(attr=DAE.CALL_ATTR(ty=DAE.T_TUPLE(types=types))),ix,_)) := getTheRightPattern(lhs, rhs);
799
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if BaseHashTable.hasKey(call, HT) then
800 ✗ exIndex := BaseHashTable.get(call, HT);
801 ✗ cseEquation := ExpandableArray.get(exIndex, exarray);
802 ✗ cref := createCrefForTsub(listLength(types), ix, cref);
803 ✗ cseEquation.cse := mergeCSETuples(cseEquation.cse, cref);
804 ✗ exarray := ExpandableArray.update(exIndex, cseEquation, exarray);
805
806 elseif not isSkipCase(call, functionTree) then
807 2 index := index + 1;
808 2 HT := BaseHashTable.add((call, index), HT);
809 2 cref := createCrefForTsub(listLength(types), ix, cref);
810 2 exarray := ExpandableArray.set(index, CSE_EQUATION(cref, call, {}), exarray);
811 end if;
812 end if;
813
814 68405 (_, (HT, exarray, cseIndex, index, functionTree)) := BackendEquation.traverseExpsOfEquation(inEq, wrapFunctionCalls_analysis2, (HT, exarray, cseIndex, index, functionTree));
815 then ();
816
817 // all other cases are not handled (e.g. algorithms)
818 else ();
819 end match;
820
821
822 69892 outTuple := (HT, exarray, cseIndex, index, functionTree);
823 end wrapFunctionCalls_analysis;
824
825 protected function createCrefForTsub "(4, 2, x) -> TUPLE(_,x,_,_)"
826 input Integer length;
827 input Integer ix;
828 input DAE.Exp cref;
829 output DAE.Exp outCref;
830 protected
831 list<DAE.Exp> expList = {};
832 algorithm
833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 for i in 1:ix-1 loop
834 expList := DAE.CREF(DAE.WILD(),DAE.T_UNKNOWN_DEFAULT)::expList;
835 end for;
836 expList := cref::expList;
837
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
13 for i in ix+1:length loop
838 expList := DAE.CREF(DAE.WILD(),DAE.T_UNKNOWN_DEFAULT)::expList;
839 end for;
840 6 outCref := DAE.TUPLE(listReverse(expList));
841 end createCrefForTsub;
842
843 protected function wrapFunctionCalls_analysis2
844 input DAE.Exp inExp;
845 input tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer, Integer, AvlTreePathFunction.Tree> inTuple;
846 output DAE.Exp outExp = inExp;
847 output tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer, Integer, AvlTreePathFunction.Tree> outTuple;
848 algorithm
849 137704 (_, outTuple) := Expression.traverseExpTopDown(inExp, wrapFunctionCalls_analysis3, inTuple);
850 end wrapFunctionCalls_analysis2;
851
852
853 protected function wrapFunctionCalls_analysis3
854 input DAE.Exp inExp;
855 input tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer, Integer, AvlTreePathFunction.Tree> inTuple;
856 output DAE.Exp outExp = inExp;
857 output Boolean cont;
858 output tuple<HashTableExpToIndex.HashTable, ExpandableArray<CSE_Equation>, Integer, Integer, AvlTreePathFunction.Tree> outTuple;
859 protected
860 AvlTreePathFunction.Tree functionTree;
861 HashTableExpToIndex.HashTable HT;
862 ExpandableArray<CSE_Equation> exarray;
863 Integer cseIndex, index;
864 DAE.Exp tsub;
865 algorithm
866 937819 (HT, exarray, cseIndex, index, functionTree) := inTuple;
867
868 cont := match inExp
869 local
870 DAE.Exp cse_var, cse_var2, call, e, e2;
871 DAE.Type ty;
872 list<DAE.Type> types;
873 Integer ix, id;
874 list<DAE.Exp> expList={};
875 CSE_Equation cseEquation;
876
877 case DAE.IFEXP()
878 algorithm
879 4493 (_, outTuple) := Expression.traverseExpTopDown(inExp.expCond, wrapFunctionCalls_analysis3, inTuple);
880 cont := false;
881 4493 return;
882 then fail();
883
884 // TODO: split up skip cases
885 case _
886 guard isSkipCase(inExp, functionTree)
887 then false;
888
889 case tsub as DAE.TSUB(exp=call as DAE.CALL(attr=DAE.CALL_ATTR(ty=DAE.T_TUPLE(types=types))), ix=ix, ty=ty) algorithm
890
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 5 times.
9 if not BaseHashTable.hasKey(call, HT) then
891 4 index := index + 1;
892 4 HT := BaseHashTable.add((call, index), HT);
893 4 (cse_var, cseIndex) := createReturnExp(ty, cseIndex, inComplex=false);
894 4 cse_var2 := createCrefForTsub(listLength(types), ix, cse_var);
895 4 exarray := ExpandableArray.set(index, CSE_EQUATION(cse_var2, call, {}), exarray);
896
897 else
898 5 id := BaseHashTable.get(call, HT);
899 5 cseEquation := ExpandableArray.get(id, exarray);
900
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 if Expression.isTuple(cseEquation.cse) then
901
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 DAE.TUPLE(expList) := cseEquation.cse;
902 5 e := listGet(expList, ix);
903
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
5 if isWildCref(e) then
904 2 (cse_var, cseIndex) := createReturnExp(ty, cseIndex, inComplex=false);
905 2 expList := List.set(expList, ix, cse_var);
906 4 cseEquation.cse := DAE.TUPLE(expList);
907 2 exarray := ExpandableArray.update(id, cseEquation, exarray);
908 end if;
909 else
910 ✗ Error.addMessage(Error.GENERIC_ELAB_EXPRESSION, {ExpressionDump.dumpExpStr(inExp, 0) + " This should never happen, Error in wrapFunctionCalls_analysis3. Trying to recover."});
911 end if;
912 end if;
913 then true;
914
915 /*
916 check arguments of noEvent for functions but ignore noEvent itself.
917 ticket #5771
918 */
919 case DAE.CALL(Absyn.IDENT("noEvent"),{DAE.RELATION(e,_,e2,_,_)}) algorithm
920 1936 (_, outTuple) := Expression.traverseExpTopDown(e, wrapFunctionCalls_analysis3, inTuple);
921 1936 (_, outTuple) := Expression.traverseExpTopDown(e2, wrapFunctionCalls_analysis3, outTuple);
922 cont := false;
923 1936 return;
924 then true;
925
926 case DAE.CALL(attr=DAE.CALL_ATTR(ty=ty)) algorithm
927
2/2
✓ Branch 1 taken 2775 times.
✓ Branch 2 taken 8287 times.
11062 if not BaseHashTable.hasKey(inExp, HT) then
928 2775 index := index + 1;
929 2775 HT := BaseHashTable.add((inExp, index), HT);
930 2775 (cse_var, cseIndex) := createReturnExp(ty, cseIndex, inComplex=false);
931 2775 exarray := ExpandableArray.set(index, CSE_EQUATION(cse_var, inExp, {}), exarray);
932 end if;
933 then true;
934
935 else true;
936 end match;
937
938 931390 outTuple := (HT, exarray, cseIndex, index, functionTree);
939 end wrapFunctionCalls_analysis3;
940
941 protected function getTheRightPattern
942 input DAE.Exp inExp1;
943 input DAE.Exp inExp2;
944 output DAE.Exp outExp1;
945 output DAE.Exp outExp2;
946 algorithm
947 (outExp1, outExp2) := match(inExp1, inExp2)
948 case (DAE.RCONST(), DAE.CALL()) then (inExp1, inExp2);
949 case (DAE.CALL(), DAE.RCONST()) then (inExp2, inExp1);
950 case (DAE.TUPLE(), DAE.CALL()) then (inExp1, inExp2);
951 case (DAE.CALL(), DAE.TUPLE()) then (inExp2, inExp1);
952 case (DAE.CREF(), DAE.CALL()) then (inExp1, inExp2);
953 case (DAE.CALL(), DAE.CREF()) then (inExp2, inExp1);
954 case (DAE.CREF(), DAE.TSUB()) then (inExp1, inExp2);
955 case (DAE.TSUB(), DAE.CREF()) then (inExp2, inExp1);
956 else fail();
957 end match;
958 end getTheRightPattern;
959
960 protected function isEquationRedundant
961 input BackendDAE.Equation inEq;
962 output Boolean outB "true if 'x=x', else false";
963 algorithm
964 outB := match inEq
965 local
966 DAE.Exp exp1, exp2;
967 list<DAE.Exp> lhs, rhs;
968
969 case BackendDAE.EQUATION(exp=exp1, scalar=exp2)
970 42633 then ExpressionBasics.expEqual(exp1, exp2);
971
972 case BackendDAE.EQUATION(exp=DAE.TUPLE(lhs), scalar=DAE.TUPLE(rhs)) guard (listLength(lhs) == listLength(rhs)) algorithm
973 ✗ print("This should never appear\n");
974 ✗ then isEquationRedundant2(lhs, rhs);
975
976 case BackendDAE.COMPLEX_EQUATION(left=DAE.TUPLE(lhs), right=DAE.TUPLE(rhs)) guard (listLength(lhs) == listLength(rhs))
977 241 then isEquationRedundant2(lhs, rhs);
978
979 case BackendDAE.COMPLEX_EQUATION(left = exp1 as DAE.CREF(ty = DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_))), right = exp2 as DAE.CREF(ty = DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_))))
980 46 then ExpressionBasics.expEqual(exp1, exp2);
981
982 else false;
983 end match;
984 end isEquationRedundant;
985
986 protected function isEquationRedundant2
987 input list<DAE.Exp> lhs;
988 input list<DAE.Exp> rhs;
989 output Boolean result = true;
990 protected
991 DAE.Exp l, r;
992 list<DAE.Exp> ll, rr;
993 algorithm
994
2/2
✓ Branch 0 taken 235 times.
✓ Branch 1 taken 1417 times.
1652 if listEmpty(lhs) then
995 235 return;
996 end if;
997
998 1417 l::ll := lhs;
999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1417 times.
1417 r::rr := rhs;
1000
1001
3/4
✓ Branch 1 taken 1407 times.
✓ Branch 2 taken 10 times.
✓ Branch 4 taken 1407 times.
✗ Branch 5 not taken.
1417 if not isWildCref(l) and not isWildCref(r) then
1002 //print(ExpressionBasics.printExpStr(l) + " ?= " + ExpressionBasics.printExpStr(r) + "\n");
1003
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1401 times.
1407 if not ExpressionBasics.expEqual(l, r) then
1004 result := false;
1005 6 return;
1006 end if;
1007 end if;
1008
1009 1411 result := isEquationRedundant2(ll, rr);
1010 end isEquationRedundant2;
1011
1012 protected function isEquationRedundant_flatten
1013 "Same as isEquationRedundant but flattens equations of form 'tuple = tuple'
1014 (e.g. (a,_,b) = (_,c,d) => b=d), if right tuple elements are in globalKnownVarHT add left tuple elements to globalKnownVars"
1015 input BackendDAE.Equation inEq;
1016 input output HashSet.HashSet globalKnownVarHT;
1017 input output BackendDAE.Variables globalKnownVars;
1018 input output BackendDAE.Variables orderedVars;
1019 input Boolean allowGlobalKnown;
1020 output Boolean outB "true if 'x=x', else false";
1021 output Boolean isGlobalKnown = false;
1022 algorithm
1023 outB := match inEq
1024 local
1025 DAE.Exp exp1, exp2;
1026 list<DAE.Exp> lhs, rhs;
1027 list<BackendDAE.Var> varList;
1028 Boolean isRedundant;
1029
1030 // a = b
1031 case BackendDAE.EQUATION(exp=exp1, scalar=exp2)
1032 algorithm
1033 4944 isRedundant := ExpressionBasics.expEqual(exp1, exp2);
1034
1/2
✓ Branch 0 taken 4944 times.
✗ Branch 1 not taken.
4944 if not isRedundant then
1035
4/4
✓ Branch 0 taken 4516 times.
✓ Branch 1 taken 428 times.
✓ Branch 3 taken 140 times.
✓ Branch 4 taken 4376 times.
4944 isGlobalKnown := allowGlobalKnown and allArgsInGlobalKnownVars({exp2}, globalKnownVarHT);
1036 if isGlobalKnown then
1037 140 globalKnownVarHT := addConstantCseVarsToGlobalKnownVarHT(exp1, globalKnownVarHT);
1038 end if;
1039 end if;
1040 then isRedundant;
1041
1042 // (a,b) = (c,d)
1043 case BackendDAE.COMPLEX_EQUATION(left=DAE.TUPLE(lhs), right=DAE.TUPLE(rhs)) guard (listLength(lhs) == listLength(rhs))
1044 algorithm
1045 1 (globalKnownVarHT, globalKnownVars, orderedVars, isRedundant) := isEquationRedundant_flatten2(lhs, rhs, globalKnownVarHT, globalKnownVars, orderedVars);
1046 1 then isRedundant;
1047
1048 // (a,b) = c
1049 case BackendDAE.COMPLEX_EQUATION(_, exp1 as DAE.TUPLE(lhs), exp2, _, _)
1050 algorithm
1051 239 isRedundant := ExpressionBasics.expEqual(exp1, exp2);
1052
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 if not isRedundant then
1053
4/4
✓ Branch 0 taken 236 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 232 times.
239 isGlobalKnown := allowGlobalKnown and allArgsInGlobalKnownVars({exp2}, globalKnownVarHT);
1054 if isGlobalKnown then
1055
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 for expMem in lhs loop
1056 // create variable with bind exp
1057 14 varList := createVarsForExp(expMem, {});
1058
2/2
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 14 times.
46 for var in varList loop
1059 // Add var to globalKnownVars
1060 32 var := BackendVariable.setBindExp(var, SOME(exp2));
1061 32 globalKnownVars := BackendVariable.addVar(var, globalKnownVars);
1062 // Add cref(s) to globalKnownVarHT
1063 32 globalKnownVarHT := addConstantCseVarsToGlobalKnownVarHT(expMem, globalKnownVarHT);
1064 end for;
1065 end for;
1066 end if;
1067 end if;
1068 then isRedundant;
1069
1070 case BackendDAE.COMPLEX_EQUATION(left=exp1, right=exp2)
1071 algorithm
1072 602 isRedundant := ExpressionBasics.expEqual(exp1, exp2);
1073
1/2
✓ Branch 0 taken 602 times.
✗ Branch 1 not taken.
602 if not isRedundant then
1074
4/4
✓ Branch 0 taken 540 times.
✓ Branch 1 taken 62 times.
✓ Branch 3 taken 91 times.
✓ Branch 4 taken 449 times.
602 isGlobalKnown := allowGlobalKnown and allArgsInGlobalKnownVars({exp2}, globalKnownVarHT);
1075 if isGlobalKnown then
1076 91 globalKnownVarHT := addConstantCseVarsToGlobalKnownVarHT(exp1, globalKnownVarHT);
1077 end if;
1078 end if;
1079 then isRedundant;
1080
1081 else false;
1082 end match;
1083 end isEquationRedundant_flatten;
1084
1085 protected function isEquationRedundant_flatten2
1086 input list<DAE.Exp> lhs;
1087 input list<DAE.Exp> rhs;
1088 input output HashSet.HashSet globalKnownVarHT;
1089 input output BackendDAE.Variables globalKnownVars;
1090 input output BackendDAE.Variables orderedVars;
1091 output Boolean result = true;
1092 protected
1093 DAE.Exp l, r;
1094 list<DAE.Exp> ll, rr;
1095 BackendDAE.Var var;
1096 algorithm
1097
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
4 if listEmpty(lhs) then
1098 1 return;
1099 end if;
1100
1101 3 l::ll := lhs;
1102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 r::rr := rhs;
1103
1104
3/4
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
3 if not isWildCref(l) and not isWildCref(r) then
1105 //print(ExpressionBasics.printExpStr(l) + " ?= " + ExpressionBasics.printExpStr(r) + "\n");
1106
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if not ExpressionBasics.expEqual(l, r) then
1107 // Left variable in globalKnownVarHT?
1108 ✗ if BaseHashSet.has(Expression.expCref(r), globalKnownVarHT) then
1109 // create variable with bind exp
1110 ✗ {var} := createVarsForExp(l, {});
1111 ✗ var := BackendVariable.setBindExp(var, SOME(r));
1112
1113 // Add var to globalKnownVars
1114 ✗ globalKnownVars := BackendVariable.addVar(var, globalKnownVars);
1115
1116 // Add cref(s) to globalKnownVarHT
1117 ✗ globalKnownVarHT := addConstantCseVarsToGlobalKnownVarHT(l, globalKnownVarHT);
1118
1119 // Delete var from ordered vars if no cse-cref
1120 ✗ if not isCSECref(var.varName) then
1121 ✗ (_, orderedVars) := BackendVariable.deleteVarIfExistsAndReturn(var.varName, orderedVars);
1122 end if;
1123 else
1124 result := false;
1125 ✗ return;
1126 end if;
1127 end if;
1128 end if;
1129
1130 3 (globalKnownVarHT, globalKnownVars, orderedVars, result) := isEquationRedundant_flatten2(ll, rr, globalKnownVarHT, globalKnownVars, orderedVars);
1131 end isEquationRedundant_flatten2;
1132
1133 protected function isCall
1134 input DAE.Exp inExp;
1135 output Boolean outBoolean;
1136 algorithm
1137 outBoolean := match inExp
1138 case DAE.CALL() then true;
1139 else false;
1140 end match;
1141 end isCall;
1142
1143 protected function isCallAndCref
1144 input DAE.Exp inExp;
1145 input DAE.Exp inExp2;
1146 output Boolean outBoolean;
1147 algorithm
1148 outBoolean := match(inExp, inExp2)
1149 case (DAE.CREF(),DAE.CALL()) then true;
1150 case (DAE.CALL(),DAE.CREF()) then true;
1151 else false;
1152 end match;
1153 end isCallAndCref;
1154
1155 protected function isTsubAndCref
1156 input DAE.Exp inExp;
1157 input DAE.Exp inExp2;
1158 output Boolean outBoolean;
1159 algorithm
1160 outBoolean := match(inExp, inExp2)
1161 case (DAE.CREF(), DAE.TSUB()) then true;
1162 case (DAE.TSUB(), DAE.CREF()) then true;
1163 else false;
1164 end match;
1165 end isTsubAndCref;
1166
1167 protected function isConstAndCall
1168 input DAE.Exp inExp;
1169 input DAE.Exp inExp2;
1170 output Boolean outBoolean;
1171 algorithm
1172 outBoolean := match(inExp, inExp2)
1173 case (DAE.RCONST(), DAE.CALL()) then true;
1174 case (DAE.CALL(), DAE.RCONST()) then true;
1175 else false;
1176 end match;
1177 end isConstAndCall;
1178
1179 protected function isCallAndTuple
1180 input DAE.Exp inExp;
1181 input DAE.Exp inExp2;
1182 output Boolean outBoolean;
1183 algorithm
1184 outBoolean := match(inExp, inExp2)
1185 case (DAE.TUPLE(),DAE.CALL()) then true;
1186 case (DAE.CALL(),DAE.TUPLE()) then true;
1187 else false;
1188 end match;
1189 end isCallAndTuple;
1190
1191 protected function isCallAndRecord
1192 input DAE.Exp inExp;
1193 input DAE.Exp inExp2;
1194 output Boolean outBoolean;
1195 algorithm
1196 outBoolean := match(inExp, inExp2)
1197 case (DAE.CREF(ty = DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_))), DAE.CALL()) then true;
1198 case (DAE.CALL(), DAE.CREF(ty = DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_)))) then true;
1199 else false;
1200 end match;
1201 end isCallAndRecord;
1202
1203 protected function mergeCSETuples
1204 input DAE.Exp inCref1;
1205 input DAE.Exp inCref2;
1206 output DAE.Exp outCref;
1207 protected
1208 list<DAE.Exp> expLst1, expLst2, expLst3;
1209 DAE.Exp e;
1210 algorithm
1211 // TUPLE = TUPLE
1212
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 if Expression.isTuple(inCref1) and Expression.isTuple(inCref2) then
1213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 DAE.TUPLE(expLst1) := inCref1;
1214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 DAE.TUPLE(expLst2) := inCref2;
1215 6 expLst1 := mergeCSETuples2(expLst1, expLst2);
1216 6 outCref := DAE.TUPLE(expLst1);
1217 // CREF = TUPLE kann es diese fälle jetzt noch geben???
1218 elseif not Expression.isTuple(inCref1) and Expression.isTuple(inCref2) then
1219 ✗ print("mergeCSETuples: This should never appear! (1)\n");
1220 ✗ DAE.TUPLE(expLst2) := inCref2;
1221 ✗ e::expLst3 := expLst2;
1222 ✗ if isWildCref(e) then
1223 expLst2 := inCref1::expLst3;
1224 end if;
1225 ✗ outCref := DAE.TUPLE(expLst2);
1226 // TUPLE = CREF kann es diese fälle jetzt noch geben???
1227 elseif Expression.isTuple(inCref1) and not Expression.isTuple(inCref2) then
1228 ✗ print("mergeCSETuples: This should never appear! (2)\n");
1229 ✗ DAE.TUPLE(expLst1) := inCref1;
1230 ✗ e::expLst3 := expLst1;
1231 ✗ if isWildCref(e) then
1232 expLst1 := inCref2::expLst3;
1233 end if;
1234 ✗ outCref := DAE.TUPLE(expLst1);
1235 // CREF = CREF
1236 else
1237 outCref := inCref1;
1238 end if;
1239 end mergeCSETuples;
1240
1241 protected function mergeCSETuples2"(_,b,_,_) x (a,_,c,_) -> (a,b,c,_) || (_,b) x (a,d) -> (a,b)"
1242 input list<DAE.Exp> inExpLst1;
1243 input list<DAE.Exp> inExpLst2;
1244 output list<DAE.Exp> outExpLst = {};
1245 algorithm
1246 outExpLst := match(inExpLst1, inExpLst2)
1247 local
1248 list<DAE.Exp> expLst1, expLst2;
1249 DAE.Exp e1, e2;
1250
1251 case ({}, {})
1252 then outExpLst;
1253
1254 case (e1::expLst1, e2::expLst2) algorithm
1255 14 outExpLst := mergeCSETuples2(expLst1, expLst2);
1256
4/4
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 1 time.
14 if not isWildCref(e1) and not isWildCref(e2) then
1257
3/4
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 9 times.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
10 if isCSEExp(e1) and not isCSEExp(e2) then
1258 1 outExpLst := e2::outExpLst;
1259 else
1260 outExpLst := e1::outExpLst;
1261 end if;
1262 elseif isWildCref(e1) and not isWildCref(e2) then
1263 2 outExpLst := e2::outExpLst;
1264 elseif not isWildCref(e1) and isWildCref(e2) then
1265 1 outExpLst := e1::outExpLst;
1266 elseif isWildCref(e1) and isWildCref(e2) then
1267 outExpLst := e1::outExpLst;
1268 end if;
1269 then outExpLst;
1270 end match;
1271 end mergeCSETuples2;
1272
1273 protected function isWildCref
1274 input DAE.Exp inExp;
1275 output Boolean outB;
1276 algorithm
1277 outB := match inExp
1278 case DAE.CREF(componentRef=DAE.WILD()) then true;
1279 else false;
1280 end match;
1281 end isWildCref;
1282
1283 protected function isSkipCase "outline all skip cases
1284 This contains amongst others
1285 * MLS 3.3 rev1, section 3.7.1
1286 Numeric Functions and Conversion Functions
1287 * MLS 3.3 rev1, section 3.7.1.1
1288 Event Triggering Mathematical Functions
1289 * MLS 3.3 rev1, section 3.7.2
1290 Derivative and Special Purpose Operators with Function Syntax
1291 * MLS 3.3 rev1, section 3.7.3
1292 Event-Related Operators with Function Syntax"
1293 input DAE.Exp inCall;
1294 input AvlTreePathFunction.Tree functionTree;
1295 output Boolean outB;
1296 algorithm
1297 outB := match inCall
1298 local
1299 Absyn.Path path;
1300 case DAE.ASUB() then true;
1301 case DAE.CALL(path=Absyn.IDENT("$_round")) then true;
1302 case DAE.CALL(path=Absyn.IDENT("$getPart")) then true;
1303 case DAE.CALL(path=Absyn.IDENT("abs")) then true;
1304 case DAE.CALL(path=Absyn.IDENT("actualStream")) then true;
1305 case DAE.CALL(path=Absyn.IDENT("backSample")) then true;
1306 case DAE.CALL(path=Absyn.IDENT("cardinality")) then true;
1307 case DAE.CALL(path=Absyn.IDENT("ceil")) then true;
1308 case DAE.CALL(path=Absyn.IDENT("change")) then true;
1309 case DAE.CALL(path=Absyn.IDENT("Clock")) then true;
1310 case DAE.CALL(path=Absyn.IDENT("delay")) then true;
1311 case DAE.CALL(path=Absyn.IDENT("der")) then true;
1312 case DAE.CALL(path=Absyn.IDENT("div")) then true;
1313 case DAE.CALL(path=Absyn.IDENT("edge")) then true;
1314 case DAE.CALL(path=Absyn.IDENT("firstTick")) then true;
1315 case DAE.CALL(path=Absyn.IDENT("floor")) then true;
1316 case DAE.CALL(path=Absyn.IDENT("getInstanceName")) then true;
1317 case DAE.CALL(path=Absyn.IDENT("hold")) then true;
1318 case DAE.CALL(path=Absyn.IDENT("homotopy")) then true;
1319 case DAE.CALL(path=Absyn.IDENT("initial")) then true;
1320 case DAE.CALL(path=Absyn.IDENT("inStream")) then true;
1321 case DAE.CALL(path=Absyn.IDENT("integer")) then true;
1322 case DAE.CALL(path=Absyn.IDENT("Integer")) then true;
1323 case DAE.CALL(path=Absyn.IDENT("interval")) then true;
1324 case DAE.CALL(path=Absyn.IDENT("mod")) then true;
1325 case DAE.CALL(path=Absyn.IDENT("noClock")) then true;
1326 //case DAE.CALL(path=Absyn.IDENT("noEvent")) then true;
1327 case DAE.CALL(path=Absyn.IDENT("pre")) then true;
1328 case DAE.CALL(path=Absyn.IDENT("previous")) then true;
1329 case DAE.CALL(path=Absyn.IDENT("reinit")) then true;
1330 case DAE.CALL(path=Absyn.IDENT("rem")) then true;
1331 case DAE.CALL(path=Absyn.IDENT("sample")) then true;
1332 case DAE.CALL(path=Absyn.IDENT("semiLinear")) then true;
1333 case DAE.CALL(path=Absyn.IDENT("shiftSample")) then true;
1334 case DAE.CALL(path=Absyn.IDENT("sign")) then true;
1335 case DAE.CALL(path=Absyn.IDENT("smooth")) then true;
1336 case DAE.CALL(path=Absyn.IDENT("spatialDistribution")) then true;
1337 case DAE.CALL(path=Absyn.IDENT("sqrt")) then true;
1338 case DAE.CALL(path=Absyn.IDENT("String")) then true;
1339 case DAE.CALL(path=Absyn.IDENT("subSample")) then true;
1340 case DAE.CALL(path=Absyn.IDENT("sum")) then true;
1341 case DAE.CALL(path=Absyn.IDENT("superSample")) then true;
1342 case DAE.CALL(path=Absyn.IDENT("terminal")) then true;
1343 case DAE.CALL() guard(Expression.isImpureCall(inCall) or isCallRecordConstructor(inCall, functionTree)) then true;
1344 ✗ case DAE.CALL() guard(Flags.getConfigBool(Flags.WFC_ADVANCED)) then isSkipCase_advanced(inCall);
1345 else false;
1346 end match;
1347 end isSkipCase;
1348
1349 protected function isSkipCase_advanced
1350 "This contains
1351 * MLS 3.3 rev1, section 3.7.1.2
1352 Built-in Mathematical Functions and External Built-in Functions "
1353 input DAE.Exp inCall;
1354 output Boolean outB;
1355 algorithm
1356 outB := match inCall
1357 local
1358 Absyn.Path path;
1359 case DAE.CALL(path=Absyn.IDENT("acos")) then true;
1360 case DAE.CALL(path=Absyn.IDENT("asin")) then true;
1361 case DAE.CALL(path=Absyn.IDENT("atan")) then true;
1362 case DAE.CALL(path=Absyn.IDENT("atan2")) then true;
1363 case DAE.CALL(path=Absyn.IDENT("cos")) then true;
1364 case DAE.CALL(path=Absyn.IDENT("cosh")) then true;
1365 case DAE.CALL(path=Absyn.IDENT("exp")) then true;
1366 case DAE.CALL(path=Absyn.IDENT("log")) then true;
1367 case DAE.CALL(path=Absyn.IDENT("log10")) then true;
1368 case DAE.CALL(path=Absyn.IDENT("sin")) then true;
1369 case DAE.CALL(path=Absyn.IDENT("sinh")) then true;
1370 case DAE.CALL(path=Absyn.IDENT("tan")) then true;
1371 case DAE.CALL(path=Absyn.IDENT("tanh")) then true;
1372 else false;
1373 end match;
1374 end isSkipCase_advanced;
1375
1376 protected function isCallRecordConstructor
1377 //DAEUtil.funcIsRecord(DAEUtil.getNamedFunction(path, functionTree))
1378 input DAE.Exp inExp;
1379 input AvlTreePathFunction.Tree funcsIn;
1380 output Boolean outIsCall;
1381 algorithm
1382 outIsCall := matchcontinue inExp
1383 local
1384 Absyn.Path path;
1385 DAE.Function func;
1386
1387 case DAE.CALL(path=path) algorithm
1388
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 10936 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10936 times.
16020 SOME(func) := AvlTreePathFunction.get(funcsIn,path);
1389 10936 then listEmpty(DAEUtil.getFunctionElements(func));
1390 else false;
1391 end matchcontinue;
1392 end isCallRecordConstructor;
1393
1394 protected function createReturnExp
1395 input DAE.Type inType;
1396 input Integer inIndex;
1397 input String inPrefix = "$cse";
1398 input Boolean inComplex = true;
1399 output DAE.Exp outExp;
1400 output Integer outIndex;
1401 algorithm
1402 (outExp, outIndex) := match inType
1403 local
1404 Integer i;
1405 String str;
1406 DAE.Exp value;
1407 DAE.ComponentRef cr;
1408 DAE.Type ty;
1409 list<DAE.Type> typeLst;
1410 list<DAE.Exp> expLst;
1411
1412 case DAE.T_REAL() algorithm
1413 2250 str := inPrefix + intString(inIndex);
1414 2250 cr := DAE.CREF_IDENT(str, DAE.T_REAL_DEFAULT, {});
1415 2250 value := DAE.CREF(cr, DAE.T_REAL_DEFAULT);
1416 2250 then (value, inIndex + 1);
1417
1418 case DAE.T_INTEGER() algorithm
1419 16 str := inPrefix + intString(inIndex);
1420 16 cr := DAE.CREF_IDENT(str, DAE.T_INTEGER_DEFAULT, {});
1421 16 value := DAE.CREF(cr, DAE.T_INTEGER_DEFAULT);
1422 16 then (value, inIndex + 1);
1423
1424 case DAE.T_STRING() algorithm
1425 ✗ str := inPrefix + intString(inIndex);
1426 ✗ cr := DAE.CREF_IDENT(str, DAE.T_STRING_DEFAULT, {});
1427 ✗ value := DAE.CREF(cr, DAE.T_STRING_DEFAULT);
1428 ✗ then (value, inIndex + 1);
1429
1430 case DAE.T_BOOL() algorithm
1431 1 str := inPrefix + intString(inIndex);
1432 1 cr := DAE.CREF_IDENT(str, DAE.T_BOOL_DEFAULT, {});
1433 1 value := DAE.CREF(cr, DAE.T_BOOL_DEFAULT);
1434 1 then (value, inIndex + 1);
1435
1436 case DAE.T_ENUMERATION() algorithm
1437 ✗ str := inPrefix + intString(inIndex);
1438 ✗ cr := DAE.CREF_IDENT(str, inType, {});
1439 ✗ value := DAE.CREF(cr, inType);
1440 ✗ then (value, inIndex + 1);
1441
1442 case DAE.T_CLOCK() algorithm
1443 ✗ str := inPrefix + intString(inIndex);
1444 ✗ cr := DAE.CREF_IDENT(str, DAE.T_CLOCK_DEFAULT, {});
1445 ✗ value := DAE.CREF(cr, DAE.T_CLOCK_DEFAULT);
1446 ✗ then (value, inIndex + 1);
1447
1448 case DAE.T_TUPLE(types=typeLst) algorithm
1449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if inComplex then
1450 ✗ (expLst, i) := List.mapFold(typeLst, function createReturnExp(inPrefix=inPrefix, inComplex=inComplex), inIndex);
1451 ✗ value := DAE.TUPLE(expLst);
1452 else
1453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 ty::_ := typeLst;
1454 2 (value, i) := createReturnExp(ty, inIndex, inPrefix, false);
1455 end if;
1456 2 then (value, i);
1457
1458 // Expanding
1459 case DAE.T_ARRAY() algorithm
1460 1 str := inPrefix + intString(inIndex);
1461 1 cr := DAE.CREF_IDENT(str, inType, {});
1462 // crefs = ComponentReference.expandCref(cr, false);
1463 // expLst = List.map(crefs, Expression.crefExp);
1464 // value = DAE.ARRAY(inType, true, expLst);
1465 1 value := DAE.CREF(cr, inType);
1466 1 then (value, inIndex + 1);
1467
1468 // record types
1469 case DAE.T_COMPLEX( complexClassType=ClassInf.RECORD(_)) algorithm
1470 556 str := inPrefix + intString(inIndex);
1471 556 cr := DAE.CREF_IDENT(str, inType, {}); //inType?
1472 // crefs = ComponentReference.expandCref(cr, true);
1473 // expLst = List.map(crefs, Expression.crefExp);
1474 // varNames = List.map(varLst, Expression.varName);
1475 // value = DAE.RECORD(path, expLst, varNames, inType);
1476 // print(" DAE.T_COMPLEX \n");
1477 556 value := DAE.CREF(cr, inType);
1478 556 then (value, inIndex + 1);
1479
1480 else algorithm
1481 ✗ Error.addInternalError(" - createReturnExp failed for " + TypesDump.printTypeStr(inType) + "\n", sourceInfo());
1482 ✗ then fail();
1483 end match;
1484 end createReturnExp;
1485
1486 protected function createVarsForExp_onlyCSECrefs
1487 "Same as createVarsForExp but only creates a variable if the crefs in inExp are $cse-crefs"
1488 input DAE.Exp inExp;
1489 input list<BackendDAE.Var> inAccumVarLst;
1490 output list<BackendDAE.Var> outVarLst;
1491 algorithm
1492 outVarLst := match inExp
1493 local
1494 DAE.ComponentRef cr, cr_;
1495 list<DAE.ComponentRef> crefs;
1496 list<DAE.Exp> expLst;
1497 BackendDAE.Var var;
1498 DAE.Type ty;
1499 DAE.InstDims arrayDim;
1500 /*
1501 case DAE.CREF(componentRef=cr) guard(not Expression.isArrayType(Expression.typeof(inExp))
1502 and not Expression.isRecordType(Expression.typeof(inExp))) equation
1503 // use the correct type when creating var. The cref might have subs.
1504 var = BackendVariable.createCSEVar(cr, Expression.typeof(inExp));
1505 then var::inAccumVarLst;
1506 */
1507 case DAE.CREF(componentRef=DAE.WILD()) then inAccumVarLst;
1508
1509 case DAE.CREF(componentRef=cr, ty = DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_))) guard isCSECref(cr) algorithm
1510 // use the correct type when creating var. The cref might have subs.
1511 ✗ crefs := ComponentReference.expandCref(cr, true /*the way it is now we won't get records here. but if we do somehow expand them*/);
1512
1513 /* Create SimVars from the list of expanded crefs.*/
1514 /* Mark the first element as an arrayCref i.e. we have 'SOME(arraycref)' since this is how the C template
1515 detects first elements of arrays to generate VARNAME_indexed(..) macros for accessing the array
1516 with variable indexes.*/
1517 outVarLst := inAccumVarLst;
1518 ✗ for cr_ in crefs loop
1519 ✗ arrayDim := ComponentReferenceBasics.crefDims(cr_);
1520 ✗ outVarLst := BackendVariable.createCSEArrayVar(cr_, ComponentReference.crefTypeFull(cr_), arrayDim)::outVarLst;
1521 end for;
1522 then outVarLst;
1523
1524 case DAE.CREF(componentRef=cr) guard(isCSECref(cr) and Expression.isArrayType(Expression.typeof(inExp))) algorithm
1525 // use the correct type when creating var. The cref might have subs.
1526 ✗ crefs := ComponentReference.expandCref(cr, true);
1527
1528 outVarLst := inAccumVarLst;
1529 ✗ ty := DAEUtil.expTypeElementType(Expression.typeof(inExp));
1530 ✗ for cr_ in crefs loop
1531 ✗ arrayDim := ComponentReferenceBasics.crefDims(cr_);
1532 //expLst := DAE.CREF(cr_, ComponentReference.crefType(cr_))::expLst;
1533 ✗ outVarLst := BackendVariable.createCSEArrayVar(cr_, ty, arrayDim)::outVarLst;
1534 end for;
1535 //expLst = list(DAE.CREF(cr_, ComponentReference.crefType(cr_)) for cr_ in crefs);
1536 then outVarLst;
1537
1538 case DAE.CREF(componentRef=cr) guard isCSECref(cr) algorithm
1539 // use the correct type when creating var. The cref might have subs.
1540 2 var := BackendVariable.createCSEVar(cr, Expression.typeof(inExp));
1541 then var::inAccumVarLst;
1542
1543 case DAE.TUPLE(expLst) algorithm
1544 ✗ outVarLst := List.fold(expLst, createVarsForExp_onlyCSECrefs, inAccumVarLst);
1545 then outVarLst;
1546
1547 case DAE.ARRAY(array=expLst) algorithm
1548 //print("This should never appear\n");
1549 ✗ outVarLst := List.fold(expLst, createVarsForExp_onlyCSECrefs, inAccumVarLst);
1550 then outVarLst;
1551
1552 case DAE.RECORD(exps=expLst) algorithm
1553 ✗ print("This should never appear\n");
1554 ✗ outVarLst := List.fold(expLst, createVarsForExp_onlyCSECrefs, inAccumVarLst);
1555 then outVarLst;
1556
1557 // add no variable in all other cases
1558 else inAccumVarLst;
1559 end match;
1560 end createVarsForExp_onlyCSECrefs;
1561
1562 protected function createVarsForExp
1563 "Creates a variable list for crefs in inExp, e.g. inExp = (a, b, _, d) -> outVarLst = {a,b,d}"
1564 input DAE.Exp inExp;
1565 input list<BackendDAE.Var> inAccumVarLst = {};
1566 output list<BackendDAE.Var> outVarLst;
1567 algorithm
1568 outVarLst := match inExp
1569 local
1570 DAE.ComponentRef cr, cr_;
1571 list<DAE.ComponentRef> crefs;
1572 list<DAE.Exp> expLst;
1573 BackendDAE.Var var;
1574 DAE.Type ty;
1575 DAE.InstDims arrayDim;
1576 /*
1577 case DAE.CREF(componentRef=cr) guard(not Expression.isArrayType(Expression.typeof(inExp))
1578 and not Expression.isRecordType(Expression.typeof(inExp))) equation
1579 // use the correct type when creating var. The cref might have subs.
1580 var = BackendVariable.createCSEVar(cr, Expression.typeof(inExp));
1581 then var::inAccumVarLst;
1582 */
1583 case DAE.CREF(componentRef=DAE.WILD()) then inAccumVarLst;
1584
1585 case DAE.CREF(componentRef=cr, ty = DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_))) algorithm
1586 // use the correct type when creating var. The cref might have subs.
1587 632 crefs := ComponentReference.expandCref(cr, true /*the way it is now we won't get records here. but if we do somehow expand them*/);
1588
1589 /* Create SimVars from the list of expanded crefs.*/
1590 /* Mark the first element as an arrayCref i.e. we have 'SOME(arraycref)' since this is how the C template
1591 detects first elements of arrays to generate VARNAME_indexed(..) macros for accessing the array
1592 with variable indexes.*/
1593 outVarLst := inAccumVarLst;
1594
2/2
✓ Branch 0 taken 7796 times.
✓ Branch 1 taken 632 times.
8428 for cr_ in crefs loop
1595 7796 arrayDim := ComponentReferenceBasics.crefDims(cr_);
1596 7796 outVarLst := BackendVariable.createCSEArrayVar(cr_, ComponentReference.crefTypeFull(cr_), arrayDim)::outVarLst;
1597 end for;
1598 then outVarLst;
1599
1600 case DAE.CREF(componentRef=cr) guard(Expression.isArrayType(Expression.typeof(inExp))) algorithm
1601 // use the correct type when creating var. The cref might have subs.
1602 18 crefs := ComponentReference.expandCref(cr, true);
1603
1604 outVarLst := inAccumVarLst;
1605 18 ty := DAEUtil.expTypeElementType(Expression.typeof(inExp));
1606
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 18 times.
67 for cr_ in crefs loop
1607 49 arrayDim := ComponentReferenceBasics.crefDims(cr_);
1608 //expLst := DAE.CREF(cr_, ComponentReference.crefType(cr_))::expLst;
1609 49 outVarLst := BackendVariable.createCSEArrayVar(cr_, ty, arrayDim)::outVarLst;
1610 end for;
1611 //expLst = list(DAE.CREF(cr_, ComponentReference.crefType(cr_)) for cr_ in crefs);
1612 then outVarLst;
1613
1614 case DAE.CREF(componentRef=cr) algorithm
1615 // use the correct type when creating var. The cref might have subs.
1616 6339 var := BackendVariable.createCSEVar(cr, Expression.typeof(inExp));
1617 then var::inAccumVarLst;
1618
1619 case DAE.TUPLE(expLst) algorithm
1620 239 outVarLst := List.fold(expLst, createVarsForExp, inAccumVarLst);
1621 then outVarLst;
1622
1623 case DAE.ARRAY(array=expLst) algorithm
1624 //print("This should never appear\n");
1625 ✗ outVarLst := List.fold(expLst, createVarsForExp, inAccumVarLst);
1626 then outVarLst;
1627
1628 case DAE.RECORD(exps=expLst) algorithm
1629 7 outVarLst := List.fold(expLst, createVarsForExp, inAccumVarLst);
1630 then outVarLst;
1631
1632 case DAE.CALL(expLst=expLst) algorithm
1633 ✗ outVarLst := List.fold(expLst, createVarsForExp, inAccumVarLst);
1634 then outVarLst;
1635
1636 // add no variable in all other cases
1637 else inAccumVarLst;
1638 end match;
1639 end createVarsForExp;
1640
1641 public function isCSECref
1642 "Returns true if the cref is prefixed with '$cse'"
1643 input DAE.ComponentRef cr;
1644 output Boolean b;
1645 algorithm
1646 b := match cr
1647 local
1648 String s;
1649 9125 case DAE.CREF_IDENT(ident=s) then StringUtil.startsWith(s, "$cse");
1650 116387 case DAE.CREF_QUAL(ident=s) then StringUtil.startsWith(s, "$cse");
1651 else false;
1652 end match;
1653 end isCSECref;
1654
1655 public function isCSEExp
1656 "Returns true if the exp is prefixed with '$cse'"
1657 input DAE.Exp inExp;
1658 output Boolean b;
1659 algorithm
1660 b := match inExp
1661 10 case DAE.CREF() then isCSECref(inExp.componentRef);
1662 else false;
1663 end match;
1664 end isCSEExp;
1665
1666 public function cseBinary "authors: Jan Hagemann and Lennart Ochel (FH Bielefeld, Germany)
1667 This module eliminates common subexpressions in an acausal environment.
1668 NOTE: This is currently just an experimental prototype to demonstrate interesting effects."
1669 input BackendDAE.BackendDAE inDAE;
1670 output BackendDAE.BackendDAE outDAE;
1671 algorithm
1672 2 outDAE := BackendDAEUtil.mapEqSystemAndFold(inDAE, CSE1, 1);
1673 end cseBinary;
1674
1675 protected function CSE1
1676 input BackendDAE.EqSystem inSystem;
1677 input BackendDAE.Shared inShared;
1678 input Integer inIndex;
1679 output BackendDAE.EqSystem outSystem;
1680 output BackendDAE.Shared outShared = inShared;
1681 output Integer outIndex;
1682 algorithm
1683 (outSystem, outIndex) := matchcontinue inSystem
1684 local
1685 BackendDAE.Variables orderedVars;
1686 BackendDAE.EquationArray orderedEqs;
1687 BackendDAE.EqSystem syst;
1688 list<BackendDAE.Var> varList;
1689 list<BackendDAE.Equation> eqList;
1690 HashTableExpToExp.HashTable HT;
1691 HashTableExpToIndex.HashTable HT2, HT3;
1692 Integer index = inIndex;
1693
1694 case syst as BackendDAE.EQSYSTEM(orderedVars=orderedVars, orderedEqs=orderedEqs) algorithm
1695 //if Flags.isSet(Flags.DUMP_CSE) then
1696 // BackendDump.dumpVariables(orderedVars, "########### Updated Variable List ###########");
1697 // BackendDump.dumpEquationArray(orderedEqs, "########### Updated Equation List ###########");
1698 //end if;
1699 2 HT := HashTableExpToExp.emptyHashTableSized(49999); //2053 4013 25343 536870879
1700 2 HT2 := HashTableExpToIndex.emptyHashTableSized(49999);
1701 2 HT3 := HashTableExpToIndex.emptyHashTableSized(49999);
1702
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
1703 ✗ print("collect statistics\n========================================\n");
1704 end if;
1705 2 (HT, HT2, index) := BackendEquation.traverseEquationArray(orderedEqs, createStatistics, (HT, HT2, index));
1706 //BaseHashTable.dumpHashTable(HT);
1707 //BaseHashTable.dumpHashTable(HT2);
1708
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
1709 ✗ print("\nstart substitution\n========================================\n");
1710 end if;
1711 2 (orderedEqs, (HT, HT2, _, eqList, varList)) := BackendEquation.traverseEquationArray_WithUpdate (orderedEqs, substituteCSE, (HT, HT2, HT3, {}, {}));
1712
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
1713 ✗ print("\n");
1714 end if;
1715 2 syst.orderedEqs := BackendEquation.addList(eqList, orderedEqs);
1716 2 syst.orderedVars := BackendVariable.addVars(varList, orderedVars);
1717
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if Flags.isSet(Flags.DUMP_CSE) then
1718 2 BackendDump.dumpVariables(syst.orderedVars, "########### Updated Variable List ###########");
1719 2 BackendDump.dumpEquationArray(syst.orderedEqs, "########### Updated Equation List ###########");
1720 end if;
1721 2 then (BackendDAEUtil.clearEqSyst(syst), index);
1722
1723 else (inSystem, inIndex);
1724 end matchcontinue;
1725 end CSE1;
1726
1727 protected function substituteCSE
1728 input BackendDAE.Equation inEq;
1729 input tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, HashTableExpToIndex.HashTable, list<BackendDAE.Equation>, list<BackendDAE.Var>> inTuple;
1730 output BackendDAE.Equation outEq;
1731 output tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, HashTableExpToIndex.HashTable, list<BackendDAE.Equation>, list<BackendDAE.Var>> outTuple;
1732 algorithm
1733 (outEq, outTuple) := match inEq
1734 local
1735 BackendDAE.Equation eq;
1736 tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, HashTableExpToIndex.HashTable, list<BackendDAE.Equation>, list<BackendDAE.Var>> tpl;
1737
1738 case BackendDAE.ALGORITHM() then (inEq, inTuple);
1739 case BackendDAE.WHEN_EQUATION() then (inEq, inTuple); // not necessary
1740 //case BackendDAE.COMPLEX_EQUATION() then (inEq, inTuple);
1741 //case BackendDAE.ARRAY_EQUATION() then (inEq, inTuple);
1742 case BackendDAE.IF_EQUATION() then (inEq, inTuple);
1743
1744 else algorithm
1745
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
1746 ✗ print("traverse " + BackendDump.equationString(inEq) + "\n");
1747 end if;
1748 21 (eq, (tpl, _)) := BackendEquation.traverseExpsOfEquation(inEq, substituteCSE1, (inTuple, BackendEquation.equationSource(inEq)));
1749 then (eq, tpl);
1750 end match;
1751 end substituteCSE;
1752
1753 protected function substituteCSE1
1754 input DAE.Exp inExp;
1755 input tuple<tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, HashTableExpToIndex.HashTable, list<BackendDAE.Equation>, list<BackendDAE.Var>>, DAE.ElementSource> inTuple;
1756 output DAE.Exp outExp;
1757 output tuple<tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, HashTableExpToIndex.HashTable, list<BackendDAE.Equation>, list<BackendDAE.Var>>, DAE.ElementSource> outTuple;
1758 algorithm
1759 42 (outExp, outTuple) := Expression.traverseExpTopDown(inExp, substituteCSE_main, inTuple);
1760 end substituteCSE1;
1761
1762 protected function substituteCSE_main
1763 input DAE.Exp inExp;
1764 input tuple<tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, HashTableExpToIndex.HashTable, list<BackendDAE.Equation>, list<BackendDAE.Var>>, DAE.ElementSource> inTuple;
1765 output DAE.Exp outExp;
1766 output Boolean cont;
1767 output tuple<tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, HashTableExpToIndex.HashTable, list<BackendDAE.Equation>, list<BackendDAE.Var>>, DAE.ElementSource> outTuple;
1768 algorithm
1769 (outExp, cont, outTuple) := matchcontinue(inExp, inTuple)
1770 local
1771 DAE.Exp value;
1772 HashTableExpToExp.HashTable HT;
1773 HashTableExpToIndex.HashTable HT2;
1774 HashTableExpToIndex.HashTable HT3;
1775 list<BackendDAE.Equation> eqLst;
1776 list<BackendDAE.Var> varLst;
1777 Integer counter;
1778 BackendDAE.Equation eq;
1779 DAE.ElementSource source;
1780
1781 case (DAE.BINARY(), ((HT, HT2, HT3, eqLst, varLst), source)) algorithm
1782 47 value := BaseHashTable.get(inExp, HT);
1783 47 counter := BaseHashTable.get(value, HT2);
1784
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6 times.
47 true := intGt(counter, 1);
1785
1786
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
1787 ✗ print(" - substitute cse binary: " + ExpressionBasics.printExpStr(inExp) + " (counter: " + intString(counter) + ", id: " + ExpressionBasics.printExpStr(value) + ")\n");
1788 end if;
1789
1790
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if not BaseHashTable.hasKey(value, HT3) then
1791 2 HT3 := BaseHashTable.add((value, 1), HT3);
1792 2 varLst := createVarsForExp_onlyCSECrefs(value, varLst);
1793 2 eq := BackendEquation.generateEquation(value, inExp, source /* TODO: Add CSE? */, BackendDAE.EQ_ATTR_DEFAULT_BINDING);
1794 eqLst := eq::eqLst;
1795 end if;
1796 6 then (value, true, ((HT, HT2, HT3, eqLst, varLst), source));
1797
1798 else (inExp, true, inTuple);
1799 end matchcontinue;
1800 end substituteCSE_main;
1801
1802 protected function createStatistics
1803 input BackendDAE.Equation inEq;
1804 input tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, Integer> inTuple;
1805 output BackendDAE.Equation outEq;
1806 output tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, Integer> outTuple;
1807 algorithm
1808 (outEq, outTuple) := match inEq
1809 local
1810 BackendDAE.Equation eq;
1811 tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, Integer> tpl;
1812
1813 ✗ case BackendDAE.ALGORITHM() then (inEq, inTuple);
1814 ✗ case BackendDAE.WHEN_EQUATION() then (inEq, inTuple); // not necessary
1815 //case BackendDAE.COMPLEX_EQUATION() then (inEq, inTuple);
1816 //case BackendDAE.ARRAY_EQUATION() then (inEq, inTuple);
1817 ✗ case BackendDAE.IF_EQUATION() then (inEq, inTuple);
1818
1819 else algorithm
1820
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
21 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
1821 ✗ print("traverse " + BackendDump.equationString(inEq) + "\n");
1822 end if;
1823 21 (eq, tpl) := BackendEquation.traverseExpsOfEquation(inEq, createStatistics1, inTuple);
1824 then (eq, tpl);
1825 end match;
1826 end createStatistics;
1827
1828 protected function createStatistics1
1829 input DAE.Exp inExp;
1830 input tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, Integer> inTuple;
1831 output DAE.Exp outExp;
1832 output tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, Integer> outTuple;
1833 algorithm
1834 42 (outExp, outTuple) := Expression.traverseExpTopDown(inExp, createStatistics_main, inTuple);
1835 end createStatistics1;
1836
1837 protected function createStatistics_main
1838 input DAE.Exp inExp;
1839 input tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, Integer> inTuple;
1840 output DAE.Exp outExp;
1841 output Boolean cont;
1842 output tuple<HashTableExpToExp.HashTable, HashTableExpToIndex.HashTable, Integer> outTuple;
1843 algorithm
1844 (outExp, cont, outTuple) := matchcontinue(inExp, inTuple)
1845 local
1846 DAE.Exp exp1, exp2, value;
1847 DAE.Operator op;
1848 Absyn.Path path;
1849 HashTableExpToExp.HashTable HT;
1850 HashTableExpToIndex.HashTable HT2;
1851 Integer i, counter;
1852
1853 case (DAE.BINARY(exp1, op, exp2), (HT, HT2, i)) algorithm
1854 if checkOp(op) then
1855
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 43 times.
47 if BaseHashTable.hasKey(inExp, HT) then
1856 4 value := BaseHashTable.get(inExp, HT);
1857 4 counter := BaseHashTable.get(value, HT2) + 1;
1858 4 BaseHashTable.update((value, counter), HT2);
1859
1860
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if isCommutative(op) then
1861 4 value := BaseHashTable.get(DAE.BINARY(exp2, op, exp1), HT);
1862 4 BaseHashTable.update((value, counter), HT2);
1863 end if;
1864 else
1865 43 (value, i) := createReturnExp(Expression.typeof(inExp), i, "$cseb");
1866 counter := 1;
1867 43 HT := BaseHashTable.add((inExp, value), HT);
1868 43 HT2 := BaseHashTable.add((value, counter), HT2);
1869
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 4 times.
43 if isCommutative(op) then
1870 39 HT := BaseHashTable.add((DAE.BINARY(exp2, op, exp1), value), HT);
1871 end if;
1872 end if;
1873
1874
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 47 times.
47 if Flags.isSet(Flags.DUMP_CSE_VERBOSE) then
1875 ✗ print(" - cse binary expression: " + ExpressionBasics.printExpStr(inExp) + " (counter: " + intString(counter) + ", id: " + ExpressionBasics.printExpStr(value) + ")\n");
1876 end if;
1877 end if;
1878 47 then (inExp, true, (HT, HT2, i));
1879
1880 // skip some kinds of expressions
1881 case (DAE.IFEXP(), _)
1882 then (inExp, false, inTuple);
1883 case (DAE.CALL(path=Absyn.IDENT("der")), _)
1884 then (inExp, false, inTuple);
1885 case (DAE.CALL(path=Absyn.IDENT("smooth")), _)
1886 then (inExp, false, inTuple);
1887 case (DAE.CALL(path=Absyn.IDENT("noEvent")), _)
1888 then (inExp, false, inTuple);
1889 case (DAE.CALL(path=Absyn.IDENT("semiLinear")), _)
1890 then (inExp, false, inTuple);
1891 case (DAE.CALL(path=Absyn.IDENT("homotopy")), _)
1892 then (inExp, false, inTuple);
1893
1894 else (inExp, true, inTuple);
1895 end matchcontinue;
1896 end createStatistics_main;
1897
1898 protected function isCommutative
1899 input DAE.Operator inOp;
1900 output Boolean outCommutative;
1901 algorithm
1902 outCommutative := match inOp
1903 case DAE.MUL() then true;
1904 case DAE.ADD() then true;
1905 else false;
1906 end match;
1907 end isCommutative;
1908
1909 protected function checkOp
1910 input DAE.Operator inOp;
1911 output Boolean outB;
1912 algorithm
1913 outB := match inOp
1914 case DAE.ADD() then true;
1915 case DAE.SUB() then true;
1916 case DAE.MUL() then true;
1917 case DAE.DIV() then true;
1918 case DAE.POW() then true;
1919 case DAE.UMINUS() then true;
1920 else false;
1921 end match;
1922 end checkOp;
1923
1924 // =============================================================================
1925 // Common Sub Expressions
1926 //
1927 // =============================================================================
1928
1929 protected
1930 uniontype CommonSubExp
1931 record ASSIGNMENT_CSE
1932 //a = exp1;
1933 //b = exp1;
1934 //--> a = b;
1935 list<Integer> eqIdcs;
1936 list<Integer> sharedVars;
1937 list<Integer> aliasVars;
1938 end ASSIGNMENT_CSE;
1939
1940 record SHORTCUT_CSE
1941 //a = exp1;
1942 //a = exp2;
1943 //--> exp1 = exp2;
1944 list<Integer> eqIdcs;
1945 Integer sharedVar;
1946 end SHORTCUT_CSE;
1947 end CommonSubExp;
1948
1949 public function commonSubExpressionReplacement"detects common sub expressions and introduces alias variables for them.
1950 REMARK: this is just a basic prototype. feel free to extend.
1951 author:Waurich TUD 2014-11"
1952 input BackendDAE.BackendDAE daeIn;
1953 output BackendDAE.BackendDAE daeOut;
1954 algorithm
1955 //print("SYSTEM IN\n");
1956 //BackendDump.printBackendDAE(daeIn);
1957 1067 daeOut := BackendDAEUtil.mapEqSystem(daeIn, commonSubExpression);
1958 //print("SYSTEM OUT\n");
1959 //BackendDump.printBackendDAE(daeOut);
1960 end commonSubExpressionReplacement;
1961
1962 protected function commonSubExpression
1963 input BackendDAE.EqSystem sysIn;
1964 input BackendDAE.Shared sharedIn;
1965 output BackendDAE.EqSystem sysOut;
1966 output BackendDAE.Shared sharedOut;
1967 algorithm
1968 (sysOut, sharedOut) := matchcontinue(sysIn, sharedIn)
1969 local
1970 AvlTreePathFunction.Tree functionTree;
1971 BackendDAE.Variables vars;
1972 BackendDAE.EquationArray eqs;
1973 BackendDAE.EqSystem syst;
1974 BackendDAE.AdjacencyMatrix m, mT;
1975 list<CommonSubExp> cseLst;
1976
1977 Boolean isInitial;
1978
1979 case(BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs), BackendDAE.SHARED(functionTree=functionTree))
1980 algorithm
1981 1568 isInitial := BackendDAEUtil.isInitializationDAE(sharedIn);
1982 1568 (_, m, mT) := BackendDAEUtil.getAdjacencyMatrix(sysIn, BackendDAE.ABSOLUTE(), SOME(functionTree), isInitial);
1983 //print("start this eqSystem\n");
1984 //BackendDump.dumpEqSystem(sysIn, "eqSystem input");
1985 //BackendDump.dumpAdjacencyMatrix(m);
1986 //BackendDump.dumpAdjacencyMatrixT(mT);
1987 1568 cseLst := commonSubExpressionFind(m, mT, vars, eqs, isInitial);
1988 //if not listEmpty(cseLst) then print("update "+stringDelimitList(List.map(cseLst, printCSE), "\n")+"\n");end if;
1989 1568 syst := commonSubExpressionUpdate(cseLst, m, mT, sysIn);
1990 1361 GCExt.free(m);
1991 1361 GCExt.free(mT);
1992 1361 syst.orderedEqs := eqs;
1993 //print("done this eqSystem\n");
1994 //BackendDump.dumpEqSystem(syst, "eqSystem");
1995 then (syst, sharedIn);
1996 else (sysIn, sharedIn);
1997 end matchcontinue;
1998 end commonSubExpression;
1999
2000 protected function commonSubExpressionFind
2001 input BackendDAE.AdjacencyMatrix mIn;
2002 input BackendDAE.AdjacencyMatrix mTIn;
2003 input BackendDAE.Variables varsIn;
2004 input BackendDAE.EquationArray eqsIn;
2005 input Boolean isInitial;
2006 output list<CommonSubExp> cseOut;
2007 protected
2008 list<Integer> eqIdcs, varIdcs,lengthLst, range;
2009 list<list<Integer>> partitions;
2010 BackendDAE.Variables vars;
2011 BackendDAE.EquationArray eqs;
2012 BackendDAE.EqSystem eqSys;
2013 BackendDAE.AdjacencyMatrix m, mT;
2014 list<BackendDAE.Equation> eqLst;
2015 list<BackendDAE.Var> varLst;
2016 list<CommonSubExp> cseLst2, cseLst3, shortenPathsCSE;
2017 AvlSetInt.Tree varIdcsSet;
2018 array<Integer> eqMap, varMap;
2019 algorithm
2020 try
2021 1568 range := List.intRange(arrayLength(mIn));
2022 1568 lengthLst := List.mapArray(mIn, listLength);
2023
2024 // check for CSE of length 1 (all eqs with 2 variables)
2025 //print("CHECK FOR CSE 2\n");
2026 1568 (_, eqIdcs) := List.filter1OnTrueSync(lengthLst, intEq, 2, range);
2027 1568 (eqLst, eqIdcs) := List.filterOnTrueSync(BackendEquation.getList(eqIdcs, eqsIn),BackendEquation.isNotAlgorithm,eqIdcs); // no algorithms
2028 1568 eqs := BackendEquation.listEquation(eqLst);
2029 1568 varIdcs := UnorderedSet.unique_list(List.flatten(List.map1(eqIdcs, Array.getIndexFirst, mIn)), Util.id, intEq);
2030 1568 varLst := List.map1(varIdcs, BackendVariable.getVarAtIndexFirst, varsIn);
2031 //(varLst,varIdcs) := List.filterOnTrueSync(varLst,BackendVariable.isVarNonDiscrete,varIdcs);// no discrete vars
2032 1568 vars := BackendVariable.listVar1(varLst);
2033 1568 eqSys := BackendDAEUtil.createEqSystem(vars, eqs);
2034 1568 (_, m, mT) := BackendDAEUtil.getAdjacencyMatrix(eqSys, BackendDAE.ABSOLUTE(), NONE(), isInitial);
2035 //BackendDump.dumpEqSystem(eqSys, "reduced system for CSE 2");
2036 //BackendDump.dumpAdjacencyMatrix(m);
2037 //BackendDump.dumpAdjacencyMatrix(mT);
2038 //varAtts := List.threadMap(List.fill(false, listLength(varIdcs)), List.fill("", listLength(varIdcs)), Util.makeTuple);
2039 //eqAtts := List.threadMap(List.fill(false, listLength(eqIdcs)), List.fill("", listLength(eqIdcs)), Util.makeTuple);
2040 //BackendDump.dumpBipartiteGraphStrongComponent2(vars, eqs, m, varAtts, eqAtts, "CSE2_"+intString(arrayLength(mIn)));
2041 1568 partitions := ResolveLoops.partitionBipartiteGraph(m, mT);
2042 1568 partitions := List.filterOnFalse(partitions,listEmpty);
2043 //print("the partitions for system : \n"+stringDelimitList(List.map(partitions, HpcOmTaskGraph.intLstString), "\n")+"\n");
2044 1568 eqMap := listArray(eqIdcs);
2045 1568 varMap := listArray(varIdcs);
2046 1568 cseLst2 := List.fold(partitions, function getCSE2(m=m, mT=mT, vars=vars, eqs=eqs, eqMap=eqMap, varMap=varMap), {});
2047
2048 1568 shortenPathsCSE := shortenPaths(partitions, m, mT, vars, eqs, eqMap, varMap, {}, isInitial);
2049
2050 // check for CSE of length 2
2051 //print("CHECK FOR CSE 3\n");
2052 1568 (_, eqIdcs) := List.filter1OnTrueSync(lengthLst, intEq, 3, range);
2053 1568 (eqLst, eqIdcs) := List.filterOnTrueSync(BackendEquation.getList(eqIdcs, eqsIn),BackendEquation.isNotAlgorithm,eqIdcs); // no algorithms
2054 1568 eqs := BackendEquation.listEquation(eqLst);
2055 varIdcsSet := AvlSetInt.EMPTY();
2056
2/2
✓ Branch 0 taken 16571 times.
✓ Branch 1 taken 1568 times.
18139 for eq in eqIdcs loop
2057 16571 varIdcsSet := AvlSetInt.addList(varIdcsSet, arrayGet(mIn, eq));
2058 end for;
2059 1568 varIdcs := AvlSetInt.listKeysReverse(varIdcsSet);
2060 1568 varLst := List.map1(varIdcs, BackendVariable.getVarAtIndexFirst, varsIn);
2061 1568 vars := BackendVariable.listVar1(varLst);
2062 1568 eqSys := BackendDAEUtil.createEqSystem(vars, eqs);
2063 1568 (_, m, mT) := BackendDAEUtil.getAdjacencyMatrix(eqSys, BackendDAE.ABSOLUTE(), NONE(), isInitial);
2064 //BackendDump.dumpEqSystem(eqSys, "reduced system for CSE 3");
2065 //BackendDump.dumpAdjacencyMatrix(m);
2066 //BackendDump.dumpAdjacencyMatrix(mT);
2067 //varAtts := List.threadMap(List.fill(false, listLength(varIdcs)), List.fill("", listLength(varIdcs)), Util.makeTuple);
2068 //eqAtts := List.threadMap(List.fill(false, listLength(eqIdcs)), List.fill("", listLength(eqIdcs)), Util.makeTuple);
2069 //BackendDump.dumpBipartiteGraphStrongComponent2(vars, eqs, m, varAtts, eqAtts, "CSE3_"+intString(arrayLength(mIn)));
2070 1568 partitions := ResolveLoops.partitionBipartiteGraph(m, mT);
2071 //print("the partitions for system : \n"+stringDelimitList(List.map(partitions, HpcOmTaskGraph.intLstString), "\n")+"\n");
2072 1568 cseLst3 := List.fold(partitions, function getCSE3(m=m, mT=mT, vars=vars, eqs=eqs, eqMap=listArray(eqIdcs), varMap=listArray(varIdcs)), {});
2073 1568 cseOut := listAppend(cseLst2, listAppend(cseLst3,shortenPathsCSE));
2074 //print("the cses : \n"+stringDelimitList(List.map(cseOut, printCSE), "\n")+"\n");
2075 else
2076 cseOut := {};
2077 end try;
2078 end commonSubExpressionFind;
2079
2080
2081 protected function shortenPaths"looks for a path in the bipartite graph where each variable and equation has only 2 adjacent node.
2082 Then check if variables which are shared by 2 equations can be combined somehow to rearrange edges and create a shortcut of this path.
2083 author:Waurich TUD 2016-05"
2084 input list<list<Integer>> allPartitions;
2085 input BackendDAE.AdjacencyMatrix mIn;
2086 input BackendDAE.AdjacencyMatrix mTIn;
2087 input BackendDAE.Variables allVars;
2088 input BackendDAE.EquationArray allEqs;
2089 input array<Integer> eqMap;
2090 input array<Integer> varMap;
2091 input list<CommonSubExp> cseIn;
2092 input Boolean isInitial;
2093 output list<CommonSubExp> cseOut;
2094 protected
2095 BackendDAE.AdjacencyMatrix mT;
2096 BackendDAE.Variables pathVars;
2097 Integer numVars, varIdx, absV;
2098 array<Integer> pathVarIdxMap, partArr;
2099 list<Integer> adjEqs, pathVarIdcs, row, touched;
2100 list<CommonSubExp> cses;
2101 algorithm
2102 try
2103 // getall vars with only 2 adjacent equations
2104 1568 numVars := BackendVariable.varsSize(allVars);
2105 1568 (_, pathVarIdcs) := List.filter1OnTrueSync(List.mapArray(mTIn, listLength), intEq, 2, List.intRange(numVars));
2106 1568 pathVars := BackendVariable.listVar1(List.map1(pathVarIdcs, BackendVariable.getVarAtIndexFirst, allVars));
2107 1568 pathVarIdxMap := listArray(List.map1(pathVarIdcs,Array.getIndexFirst,varMap));
2108 cses := cseIn;
2109
2/2
✓ Branch 1 taken 578 times.
✓ Branch 2 taken 990 times.
1568 if BackendVariable.varsSize(pathVars) > 0 then
2110 578 mT := arrayCreate(BackendVariable.varsSize(pathVars), {});
2111
2/2
✓ Branch 0 taken 2866 times.
✓ Branch 1 taken 332 times.
3198 for partition in allPartitions loop
2112 // The transposed adjacency matrix of the partition's equations, filled
2113 // like BackendDAEUtil.adjacencyMatrixDispatch but only for the
2114 // variables they touch.
2115 2866 partArr := listArray(partition);
2116 touched := {};
2117
1/2
✓ Branch 0 taken 2866 times.
✗ Branch 1 not taken.
12418 for eqIdx in 1:arrayLength(partArr) loop
2118 9552 (row, _) := BackendDAEUtil.adjacencyRow(BackendEquation.get(allEqs, partArr[eqIdx]), pathVars, BackendDAE.SOLVABLE(), NONE(), {}, isInitial);
2119
2/2
✓ Branch 1 taken 13564 times.
✓ Branch 2 taken 9552 times.
23116 for v in BackendDAEUtil.uniqueRow(row) loop
2120 13564 absV := intAbs(v);
2121 13564 adjEqs := arrayGet(mT, absV);
2122
2/2
✓ Branch 0 taken 5150 times.
✓ Branch 1 taken 8414 times.
13564 if listEmpty(adjEqs) then
2123 touched := absV :: touched;
2124 end if;
2125
2/2
✓ Branch 0 taken 7090 times.
✓ Branch 1 taken 6474 times.
27128 arrayUpdate(mT, absV, (if v < 0 then -eqIdx else eqIdx) :: adjEqs);
2126 end for;
2127 end for;
2128
2129
2/2
✓ Branch 1 taken 4865 times.
✓ Branch 2 taken 2620 times.
7485 for idx in List.sort(touched, intGt) loop
2130 4865 adjEqs := arrayGet(mT, idx);
2131
2/2
✓ Branch 1 taken 1481 times.
✓ Branch 2 taken 3384 times.
4865 if listLength(adjEqs) == 2 then
2132
4/4
✓ Branch 0 taken 2786 times.
✓ Branch 1 taken 1235 times.
✓ Branch 2 taken 2786 times.
✓ Branch 3 taken 1235 times.
4021 adjEqs := list(arrayGet(eqMap, partArr[eq]) for eq in adjEqs);
2133 1235 varIdx := arrayGet(pathVarIdxMap, idx);
2134 1235 cses := SHORTCUT_CSE(adjEqs, varIdx) :: cses;
2135 end if;
2136 4619 arrayUpdate(mT, idx, {});
2137 end for;
2138 end for;
2139 //print("the SHORTPATH cses : \n"+stringDelimitList(List.map(cses, printCSE), "\n")+"\n");
2140 end if;
2141 cseOut := cses;
2142 else
2143 cseOut := cseIn;
2144 end try;
2145 end shortenPaths;
2146
2147 protected function getCSE2"traverses the partitions and checks for CSE2 i.e a=b+const. ; c = b+const. --> a=c
2148 author:Waurich TUD 2014-11"
2149 input list<Integer> partition;
2150 input BackendDAE.AdjacencyMatrix m;
2151 input BackendDAE.AdjacencyMatrix mT;
2152 input BackendDAE.Variables vars; // for partition
2153 input BackendDAE.EquationArray eqs; // for partition
2154 input array<Integer> eqMap;
2155 input array<Integer> varMap;
2156 input list<CommonSubExp> cseIn;
2157 output list<CommonSubExp> cseOut;
2158 algorithm
2159 cseOut := matchcontinue partition
2160 local
2161 Integer sharedVarIdx, eqIdx1, eqIdx2, varIdx1, varIdx2;
2162 list<Integer> varIdcs1, varIdcs2, sharedVarIdcs, eqIdcs;
2163 BackendDAE.Equation eq1, eq2;
2164 BackendDAE.Var var1, var2;
2165 DAE.Exp varExp1, varExp2, lhs, rhs1, rhs2;
2166 case {eqIdx1, eqIdx2}
2167 algorithm
2168 //print("partition "+stringDelimitList(List.map(partition, intString), ", ")+"\n");
2169 // the partition consists of 2 equations
2170 1809 varIdcs1 := arrayGet(m, eqIdx1);
2171 1809 varIdcs2 := arrayGet(m, eqIdx2);
2172 1809 (sharedVarIdcs, varIdcs1, varIdcs2) := List.intersection1OnTrue(varIdcs1, varIdcs2, intEq);
2173 //print("sharedVarIdcs "+stringDelimitList(List.map(sharedVarIdcs, intString), ", ")+"\n");
2174
3/4
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 1728 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1728 times.
1809 {varIdx1} := varIdcs1;
2175
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1728 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1722 times.
1728 {varIdx2} := varIdcs2;
2176
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1722 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1722 times.
1722 {sharedVarIdx} := sharedVarIdcs;
2177
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1722 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1722 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1722 times.
1722 {eq1, eq2} := BackendEquation.getList(partition, eqs);
2178 1722 BackendVariable.getVarAt(vars, sharedVarIdx);
2179 1722 var1 := BackendVariable.getVarAt(vars, varIdx1);
2180 1722 var2 := BackendVariable.getVarAt(vars, varIdx2);
2181
2182 // compare the actual equations
2183 1722 varExp1 := BackendVariable.varExp(var1);
2184 1722 varExp2 := BackendVariable.varExp(var2);
2185
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 1688 times.
1722 BackendDAE.EQUATION(exp=lhs, scalar=rhs1) := eq1;
2186 1688 (rhs1, _) := ExpressionSolve.solve(lhs, rhs1, varExp1);
2187
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1595 times.
1609 BackendDAE.EQUATION(exp=lhs, scalar=rhs2) := eq2;
2188 1595 (rhs2, _) := ExpressionSolve.solve(lhs, rhs2, varExp2);
2189
2/2
✓ Branch 1 taken 729 times.
✓ Branch 2 taken 270 times.
999 true := ExpressionBasics.expEqual(rhs1, rhs2);
2190 //print("rhs1 " +ExpressionBasics.printExpStr(rhs1)+"\n");
2191 //print("rhs2 " +ExpressionBasics.printExpStr(rhs2)+"\n");
2192 //print("is equal\n");
2193 // build CSE
2194 270 sharedVarIdcs := List.map1(sharedVarIdcs, Array.getIndexFirst, varMap);
2195 270 varIdcs2 := listAppend(varIdcs1, varIdcs2);
2196 270 varIdcs2 := List.map1(varIdcs2, Array.getIndexFirst, varMap);
2197 270 eqIdcs := List.map1(partition, Array.getIndexFirst, eqMap);
2198 270 then ASSIGNMENT_CSE(eqIdcs, sharedVarIdcs, varIdcs2)::cseIn;
2199 else cseIn;
2200 end matchcontinue;
2201 end getCSE2;
2202
2203 protected function getCSE3"traverses the partitions and checks for CSE3 i.e a=b+c+const. ; d = b+c+const. --> a=d
2204 author:Waurich TUD 2014-11"
2205 input list<Integer> partition;
2206 input BackendDAE.AdjacencyMatrix m;
2207 input BackendDAE.AdjacencyMatrix mT;
2208 input BackendDAE.Variables vars; // for partition
2209 input BackendDAE.EquationArray eqs; // for partition
2210 input array<Integer> eqMap;
2211 input array<Integer> varMap;
2212 input list<CommonSubExp> cseIn;
2213 output list<CommonSubExp> cseOut;
2214 algorithm
2215 cseOut := matchcontinue cseIn
2216 local
2217 Integer eqIdx1, eqIdx2, varIdx1, varIdx2;
2218 list<Integer> varIdcs1, varIdcs2, sharedVarIdcs, eqIdcs;
2219 list<Integer> loop1;
2220 list<list<Integer>> loops;
2221 BackendDAE.Equation eq1, eq2;
2222 BackendDAE.Var var1, var2;
2223 DAE.Exp varExp1, varExp2, lhs, rhs1, rhs2;
2224 list<CommonSubExp> cseLst;
2225 case _
2226 algorithm
2227 //print("partition "+stringDelimitList(List.map(partition, intString), ", ")+"\n");
2228 // partition has only one loop
2229 4198 (loops, _, _) := ResolveLoops.resolveLoops_findLoops({partition}, m, mT, findExactlyOneLoop=false);
2230 cseLst := cseIn;
2231
2/2
✓ Branch 0 taken 7355 times.
✓ Branch 1 taken 2337 times.
9692 for loop1 in loops loop
2232 //print("loop1 "+stringDelimitList(List.map(loop1, intString), ", ")+"\n");
2233
4/6
✓ Branch 0 taken 1568 times.
✓ Branch 1 taken 5787 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5787 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5787 times.
7355 {eqIdx1, eqIdx2} := loop1;
2234 5787 varIdcs1 := arrayGet(m, eqIdx1);
2235 5787 varIdcs2 := arrayGet(m, eqIdx2);
2236 5787 (sharedVarIdcs, varIdcs1, varIdcs2) := List.intersection1OnTrue(varIdcs1, varIdcs2, intEq);
2237 //print("sharedVarIdcs "+stringDelimitList(List.map(sharedVarIdcs, intString), ", ")+"\n");
2238 //print("varIdcs1 "+stringDelimitList(List.map(varIdcs1, intString), ", ")+"\n");
2239 //print("varIdcs2 "+stringDelimitList(List.map(varIdcs2, intString), ", ")+"\n");
2240
4/4
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 5768 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 5723 times.
5787 {varIdx1} := varIdcs1;
2241
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5723 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 5722 times.
5723 {varIdx2} := varIdcs2;
2242
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 5722 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5722 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5722 times.
5722 {eq1, eq2} := BackendEquation.getList(loop1, eqs);
2243 5722 var1 := BackendVariable.getVarAt(vars, varIdx1);
2244 5722 var2 := BackendVariable.getVarAt(vars, varIdx2);
2245
2246 // compare the actual equations
2247 5722 varExp1 := BackendVariable.varExp(var1);
2248 5722 varExp2 := BackendVariable.varExp(var2);
2249
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5697 times.
5722 BackendDAE.EQUATION(exp=lhs, scalar=rhs1) := eq1;
2250 5697 (rhs1, _) := ExpressionSolve.solve(lhs, rhs1, varExp1);
2251
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5642 times.
5646 BackendDAE.EQUATION(exp=lhs, scalar=rhs2) := eq2;
2252 5642 (rhs2, _) := ExpressionSolve.solve(lhs, rhs2, varExp2);
2253
2/2
✓ Branch 1 taken 950 times.
✓ Branch 2 taken 4544 times.
5494 if ExpressionBasics.expEqual(rhs1, rhs2) then
2254 //print("rhs1 " +ExpressionBasics.printExpStr(rhs1)+"\n");
2255 //print("rhs2 " +ExpressionBasics.printExpStr(rhs2)+"\n");
2256 //print("is equal\n");
2257 // build CSE
2258
4/4
✓ Branch 0 taken 1900 times.
✓ Branch 1 taken 950 times.
✓ Branch 2 taken 1900 times.
✓ Branch 3 taken 950 times.
2850 sharedVarIdcs := list(arrayGet(varMap, i) for i in sharedVarIdcs);
2259 950 varIdcs2 := listAppend(varIdcs1, varIdcs2);
2260
4/4
✓ Branch 0 taken 1900 times.
✓ Branch 1 taken 950 times.
✓ Branch 2 taken 1900 times.
✓ Branch 3 taken 950 times.
2850 varIdcs2 := list(arrayGet(varMap, i) for i in varIdcs2);
2261
4/4
✓ Branch 0 taken 1900 times.
✓ Branch 1 taken 950 times.
✓ Branch 2 taken 1900 times.
✓ Branch 3 taken 950 times.
2850 eqIdcs := list(arrayGet(eqMap,i) for i in loop1);
2262 950 cseLst := ASSIGNMENT_CSE(eqIdcs, sharedVarIdcs, varIdcs2)::cseLst;
2263 end if;
2264 end for;
2265 then cseLst;
2266 else cseIn;
2267 end matchcontinue;
2268 end getCSE3;
2269
2270
2271 protected function commonSubExpressionUpdate"updates the eqSystem.
2272 remark: the vars are not explicitly declared as alias and an equation is not removed since there are cases where alias-replacements are invalid like :
2273 x[1]=x[2];
2274 for i in 1:2 loop x[i] =i*time; end for;
2275 Thats why one original equation is replaced by an alias equation.
2276 author:Waurich TUD 2014-11"
2277 input list<CommonSubExp> tplsIn;
2278 input BackendDAE.AdjacencyMatrix m;
2279 input BackendDAE.AdjacencyMatrix mT;
2280 input BackendDAE.EqSystem sysIn;
2281 output BackendDAE.EqSystem sysOut;
2282 algorithm
2283 sysOut := match (tplsIn, sysIn)
2284 local
2285 Integer sharedVar, eqIdx1, eqIdx2, varIdx1, varIdx2, varIdx_remain, varIdxAlias, eqIdxDel, n;
2286 list<Integer> eqIdcs, eqs1, eqs2, aliasVars;
2287 list<CommonSubExp> rest;
2288 BackendDAE.Var var1, var2, var_remain, var_alias;
2289 BackendVarTransform.VariableReplacements repl;
2290 BackendDAE.Variables vars;
2291 BackendDAE.Var var;
2292 BackendDAE.Equation eq1,eq2, eqNew;
2293 BackendDAE.EquationArray eqs;
2294 BackendDAE.EqSystem syst;
2295 DAE.Exp varExp_remain, varExp_alias, lhs1,rhs1,lhs2,rhs2,varExp,exp;
2296 DAE.ComponentRef cref;
2297 list<BackendDAE.Equation> eqLst;
2298 case({}, syst as BackendDAE.EQSYSTEM())
2299 algorithm
2300 1361 then (BackendDAEUtil.clearEqSyst(syst));
2301
2302 case (ASSIGNMENT_CSE(eqIdcs={eqIdx1, eqIdx2}, aliasVars={varIdx1, varIdx2})::rest, syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs))
2303 algorithm
2304 // update the equations
2305 1213 repl := BackendVarTransform.emptyReplacements();
2306 1213 eqs1 := arrayGet(mT, varIdx1);
2307 1213 eqs2 := arrayGet(mT, varIdx2);
2308 //print("eqs1 "+stringDelimitList(List.map(eqs1, intString), ", ")+"\n");
2309 //print("eqs2 "+stringDelimitList(List.map(eqs2, intString), ", ")+"\n");
2310
2311 1213 var1 := BackendVariable.getVarAt(vars, varIdx1);
2312 1213 var2 := BackendVariable.getVarAt(vars, varIdx2);
2313
2314 //choose alias variable
2315
2/2
✓ Branch 1 taken 1203 times.
✓ Branch 2 taken 10 times.
1213 if BackendVariable.isStateVar(var1) then varIdxAlias := varIdx2; varIdx_remain := varIdx1;
2316 elseif BackendVariable.isStateVar(var2) then varIdx_remain := varIdx2; varIdxAlias := varIdx1;
2317 else
2318
2/2
✓ Branch 2 taken 246 times.
✓ Branch 3 taken 950 times.
1196 if intLe(listLength(eqs2), listLength(eqs1)) then varIdxAlias := varIdx2; varIdx_remain := varIdx1; else varIdxAlias := varIdx1; varIdx_remain := varIdx2; end if;
2319 end if;
2320
2321
2/2
✓ Branch 2 taken 252 times.
✓ Branch 3 taken 961 times.
1213 if intLe(listLength(eqs2), listLength(eqs1)) then eqIdxDel := eqIdx2; else eqIdxDel := eqIdx1; end if;
2322
2323 1213 var_remain := BackendVariable.getVarAt(vars, varIdx_remain);
2324 1213 var_alias := BackendVariable.getVarAt(vars, varIdxAlias);
2325 1213 cref := BackendVariable.varCref(var_alias);
2326 1213 varExp_remain := BackendVariable.varExp(var_remain);
2327 1213 varExp_alias := BackendVariable.varExp(var_alias);
2328 1213 repl := BackendVarTransform.addReplacement(repl, cref, varExp_remain, NONE());
2329 //BackendVarTransform.dumpReplacements(repl);
2330
2331 //replace in equations
2332 1213 eqIdcs := arrayGet(mT, varIdxAlias);
2333 1213 eqLst := BackendEquation.getList(eqIdcs, eqs);
2334 //(eqLst, _) = BackendVarTransform.replaceEquations(eqLst, repl, NONE());
2335 1213 eqs := List.threadFold(eqIdcs, eqLst, BackendEquation.setAtIndexFirst, eqs);
2336
2337 //replace original equation
2338 1213 BackendEquation.setAtIndex(eqs,eqIdxDel,BackendDAE.EQUATION(varExp_remain,varExp_alias,DAE.emptyElementSource,BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC));
2339 1213 then commonSubExpressionUpdate(rest, m, mT, syst);
2340
2341 case (SHORTCUT_CSE(eqIdcs={eqIdx1, eqIdx2}, sharedVar=sharedVar)::rest, syst as BackendDAE.EQSYSTEM(orderedVars=vars, orderedEqs=eqs))
2342 algorithm
2343
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 563 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 563 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 563 times.
563 {eq1, eq2} := BackendEquation.getList({eqIdx1, eqIdx2}, eqs);
2344 563 var := BackendVariable.getVarAt(vars, sharedVar);
2345 563 varExp := BackendVariable.varExp(var);
2346
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 531 times.
563 BackendDAE.EQUATION(exp=lhs1, scalar=rhs1) := eq1;
2347
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 520 times.
531 BackendDAE.EQUATION(exp=lhs2, scalar=rhs2) := eq2;
2348
2349 // since ExpressionSolve is able to solve for vars in if-expressions, stop here
2350
2/2
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 497 times.
520 true := hasAlgebraicOperationsOnly(lhs1);
2351
2/2
✓ Branch 1 taken 50 times.
✓ Branch 2 taken 447 times.
497 true := hasAlgebraicOperationsOnly(rhs1);
2352
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 440 times.
447 true := hasAlgebraicOperationsOnly(lhs2);
2353
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 406 times.
440 true := hasAlgebraicOperationsOnly(rhs2);
2354
2355 406 (rhs1, _) := ExpressionSolve.solve(lhs1, rhs1, varExp);
2356 361 (lhs1, _) := ExpressionSolve.solve(lhs2, rhs2, varExp);
2357
2358 357 (_,lhs1,rhs1) := cancelExpressions(lhs1,rhs1);
2359 357 n := listLength(Expression.getAllCrefs(Expression.expSub(lhs1,rhs1)));
2360 //print("n1 "+intString(n1)+"\n");
2361 //print("n2 "+intString(n2)+"\n");
2362
2363
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 323 times.
356 if n <= 2 then
2364 //print("FROM "+BackendDump.equationString(eq1)+"\n");
2365 //print("AND "+BackendDump.equationString(eq2)+"\n");
2366 33 eqNew := BackendDAE.EQUATION(lhs1,rhs1,DAE.emptyElementSource,BackendDAE.EQ_ATTR_DEFAULT_DYNAMIC);
2367 //print("MADE A NEW EQUATION "+BackendDump.equationString(eqNew)+"\n\n");
2368 //replace original equation
2369 33 BackendEquation.setAtIndex(eqs,eqIdx1,eqNew);
2370 end if;
2371
2372 356 then commonSubExpressionUpdate(rest, m, mT, syst);
2373 case (_::rest, _)
2374 ✗ then commonSubExpressionUpdate(rest, m, mT, sysIn);
2375 end match;
2376 end commonSubExpressionUpdate;
2377
2378
2379 protected function hasAlgebraicOperationsOnly"checks if the expression contains algebraic operations only. (no realtions, ifs, etc.)
2380 author:Waurich TUD 05-2016"
2381 input DAE.Exp exp;
2382 output Boolean isAlgOut;
2383 algorithm
2384 isAlgOut := match exp
2385 local
2386 Boolean b;
2387 DAE.Exp e1,e2;
2388 case DAE.RCONST()
2389 then true;
2390 case DAE.CREF()
2391 then true;
2392 case DAE.BINARY(e1,_,e2)
2393 algorithm
2394 1090 b := hasAlgebraicOperationsOnly(e1);
2395
4/4
✓ Branch 0 taken 1067 times.
✓ Branch 1 taken 23 times.
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 1019 times.
1090 b := b and hasAlgebraicOperationsOnly(e2);
2396 then b;
2397 case DAE.UNARY(_,e1)
2398 algorithm
2399 138 b := hasAlgebraicOperationsOnly(e1);
2400 then b;
2401 else
2402 then false;
2403 end match;
2404 end hasAlgebraicOperationsOnly;
2405
2406
2407 protected function cancelExpressions"checks if factors on each side of an equation can be cancelled
2408 author: Waurich TUD 2016-05"
2409 input DAE.Exp e1In;//lhs
2410 input DAE.Exp e2In;//rhs
2411 output Boolean canceled = false;
2412 output DAE.Exp e1Out = e1In;
2413 output DAE.Exp e2Out = e2In;
2414 protected
2415 list<DAE.Exp> topLevelFactors1, topLevelFactors2;
2416 algorithm
2417 357 topLevelFactors1 := getTopLevelFactors(e1In,{});
2418 //print("topLevelFactors1 "+ExpressionDump.printExpListStr(topLevelFactors1)+"\n");
2419 357 topLevelFactors2 := getTopLevelFactors(e2In,{});
2420 //print("topLevelFactors2 "+ExpressionDump.printExpListStr(topLevelFactors2)+"\n");
2421
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 273 times.
357 if not listEmpty(topLevelFactors1) and not listEmpty(topLevelFactors1) then
2422 273 topLevelFactors1 := List.intersectionOnTrue(topLevelFactors1,topLevelFactors2,ExpressionBasics.expEqual);
2423
1/2
✓ Branch 1 taken 273 times.
✗ Branch 2 not taken.
273 if listLength(topLevelFactors1) == 1 then
2424 ✗ e1Out := Expression.expDiv(e1In,listHead(topLevelFactors1));
2425 ✗ e1Out := ExpressionSimplify.simplify(e1Out);
2426 ✗ e2Out := Expression.expDiv(e2In,listHead(topLevelFactors2));
2427 ✗ e2Out := ExpressionSimplify.simplify(e2Out);
2428 //print("e1Out "+ExpressionDump.printExpListStr({e1Out})+"\n");
2429 //print("e2Out "+ExpressionDump.printExpListStr({e2Out})+"\n");
2430 canceled := true;
2431 end if;
2432 end if;
2433 end cancelExpressions;
2434
2435 protected function getTopLevelFactors"Gets factors(crefs only) of the exp"
2436 input DAE.Exp exp;
2437 input list<DAE.Exp> lstIn;
2438 output list<DAE.Exp> lstOut;
2439 algorithm
2440 lstOut := match exp
2441 local
2442 DAE.Exp e1,e2;
2443 list<DAE.Exp> eLst;
2444 case DAE.BINARY(e1,DAE.MUL(_),e2)
2445 algorithm
2446 509 eLst := getTopLevelFactors(e1,lstIn);
2447 509 eLst := getTopLevelFactors(e2,eLst);
2448 then eLst;
2449 case DAE.UNARY(_ ,e1 as DAE.CREF())
2450 algorithm
2451 then e1::lstIn;
2452 case e1 as DAE.CREF()
2453 algorithm
2454 then e1::lstIn;
2455 else
2456 then lstIn;
2457 end match;
2458 end getTopLevelFactors;
2459
2460 protected function printCSE"prints a CSE tuple string.
2461 author:Waurich TUD 2014-11"
2462 input CommonSubExp cse;
2463 output String s;
2464 algorithm
2465 s := match cse
2466 local
2467 Integer sharedVar;
2468 list<Integer> eqIdcs;
2469 list<Integer> sharedVars;
2470 list<Integer> aliasVars;
2471 case ASSIGNMENT_CSE(eqIdcs=eqIdcs, sharedVars=sharedVars, aliasVars=aliasVars)
2472 ✗ then "ASSIGN_CSE: eqs{"+stringDelimitList(List.map(eqIdcs, intString), ", ")+"}"+" sharedVars{"+stringDelimitList(List.map(sharedVars, intString), ", ")+"}"+" aliasVars{"+stringDelimitList(List.map(aliasVars, intString), ", ")+"}";
2473 case SHORTCUT_CSE(eqIdcs, sharedVar)
2474 ✗ then "SHORTCUT_CSE: eqs{"+stringDelimitList(List.map(eqIdcs, intString), ", ")+"}"+" sharedVar{"+intString(sharedVar)+"}";
2475 end match;
2476 end printCSE;
2477 annotation(__OpenModelica_Interface="backend");
2478
2479 end CommonSubExpression;
2480