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 |