Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 141 / 0 / 141
Functions: -% 0 / 1 / 1
Branches: 90.1% 128 / 0 / 142

OMCompiler/Compiler/NFFrontEnd/NFSimplifyModel.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 NFSimplifyModel
37
38 import FlatModel = NFFlatModel;
39 import Equation = NFEquation;
40 import Statement = NFStatement;
41 import Expression = NFExpression;
42 import Type = NFType;
43 import ComponentRef = NFComponentRef;
44 import NFFlatten.FunctionTree;
45 import Class = NFClass;
46 import NFInstNode.InstNode;
47 import NFInstNode;
48 import NFFunction.Function;
49 import Sections = NFSections;
50 import Binding = NFBinding;
51 import Variable = NFVariable;
52 import Algorithm = NFAlgorithm;
53 import Dimension = NFDimension;
54 import Subscript = NFSubscript;
55
56 protected
57 import Ceval = NFCeval;
58 import DAE;
59 import ExecStat.execStat;
60 import MetaModelica.Dangerous.*;
61 import NFPrefixes.Variability;
62 import SimplifyExp = NFSimplifyExp;
63
64 public
65 function simplify
66 input output FlatModel flatModel;
67 algorithm
68
4/4
✓ Branch 0 taken 240727 times.
✓ Branch 1 taken 1576 times.
✓ Branch 2 taken 240727 times.
✓ Branch 3 taken 1576 times.
242303 flatModel.variables := list(simplifyVariable(v) for v in flatModel.variables);
69 flatModel.equations := simplifyEquations(flatModel.equations);
70 flatModel.initialEquations := simplifyEquations(flatModel.initialEquations);
71 flatModel.algorithms := simplifyAlgorithms(flatModel.algorithms);
72 flatModel.initialAlgorithms := simplifyAlgorithms(flatModel.initialAlgorithms);
73
74 1574 execStat(getInstanceName());
75 end simplify;
76
77 function simplifyVariable
78 input output Variable var;
79 algorithm
80
8/8
✓ Branch 1 taken 472029 times.
✓ Branch 2 taken 241172 times.
✓ Branch 3 taken 472029 times.
✓ Branch 4 taken 241172 times.
✓ Branch 6 taken 445 times.
✓ Branch 7 taken 241172 times.
✓ Branch 8 taken 445 times.
✓ Branch 9 taken 241172 times.
713646 var.binding := simplifyBinding(var.binding);
81 var.typeAttributes := list(simplifyTypeAttribute(a) for a in var.typeAttributes);
82 var.children := list(simplifyVariable(v) for v in var.children);
83 end simplifyVariable;
84
85 function simplifyBinding
86 input output Binding binding;
87 protected
88 Expression exp, sexp;
89 algorithm
90
2/2
✓ Branch 1 taken 109997 times.
✓ Branch 2 taken 603204 times.
713201 if Binding.isBound(binding) then
91 603204 exp := Binding.getTypedExp(binding);
92 603204 sexp := SimplifyExp.simplify(exp);
93 603204 sexp := removeEmptyFunctionArguments(sexp);
94
95
2/2
✓ Branch 0 taken 478857 times.
✓ Branch 1 taken 124347 times.
603204 if not referenceEq(exp, sexp) then
96 124347 binding := Binding.setTypedExp(sexp, binding);
97 end if;
98 end if;
99 end simplifyBinding;
100
101 function simplifyTypeAttribute
102 input output tuple<String, Binding> attribute;
103 protected
104 String name;
105 Binding binding, sbinding;
106 algorithm
107 472029 (name, binding) := attribute;
108 472029 sbinding := simplifyBinding(binding);
109
110
2/2
✓ Branch 0 taken 386776 times.
✓ Branch 1 taken 85253 times.
472029 if not referenceEq(binding, sbinding) then
111 85253 attribute := (name, sbinding);
112 end if;
113 end simplifyTypeAttribute;
114
115 function simplifyDimension
116 input Dimension dim;
117 output Dimension outDim;
118 algorithm
119 outDim := match dim
120 local
121 Expression e;
122
123 case Dimension.EXP()
124 algorithm
125 224 e := SimplifyExp.simplify(dim.exp);
126
1/2
✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
224 then
127 if referenceEq(e, dim.exp) then dim else Dimension.fromExp(e, dim.var);
128
129 else dim;
130 end match;
131 end simplifyDimension;
132
133 function simplifyEquations
134 input list<Equation> eql;
135 output list<Equation> outEql = {};
136 algorithm
137
2/2
✓ Branch 0 taken 142841 times.
✓ Branch 1 taken 4477 times.
147318 for eq in eql loop
138 142841 outEql := simplifyEquation(eq, outEql);
139 end for;
140
141 4477 outEql := listReverseInPlace(outEql);
142 end simplifyEquations;
143
144 function simplifyEquation
145 input Equation eq;
146 input output list<Equation> equations;
147 algorithm
148 equations := match eq
149 local
150 Expression e;
151 list<Equation> body;
152 Dimension dim;
153
154 138341 case Equation.EQUALITY() then simplifyEqualityEquation(eq, equations);
155
156 case Equation.FOR(range = SOME(e))
157 algorithm
158 349 dim := Type.nthDimension(Expression.typeOf(e), 1);
159
160
6/6
✓ Branch 1 taken 345 times.
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 56 times.
✓ Branch 5 taken 289 times.
✓ Branch 7 taken 53 times.
✓ Branch 8 taken 3 times.
349 if Dimension.isZero(dim) then
161 // Discard the for-loop if the iteration range is empty.
162 elseif Dimension.isOne(dim) and Flags.getConfigBool(Flags.NEW_BACKEND) then
163 // Unroll the loop if the iteration range is size 1.
164 // TODO: This breaks some of the -d=-nfScalarize tests because they rely on the broken way
165 // the old backend handles for-loops, so only enable it for the new backend for now.
166 53 e := Expression.applySubscript(Subscript.INDEX(Expression.INTEGER(1)), e);
167 53 e := SimplifyExp.simplify(e);
168 53 body := Equation.replaceIteratorList(eq.body, eq.iterator, e);
169 53 body := simplifyEquations(body);
170 53 equations := List.append_reverse(body, equations);
171 else
172 // Otherwise just simplify the range and body of the loop.
173 584 eq.range := Util.applyOption(eq.range, function SimplifyExp.simplify(includeScope = false));
174 292 eq.body := simplifyEquations(eq.body);
175 equations := eq :: equations;
176 end if;
177 then
178 equations;
179
180 case Equation.IF()
181 1429 then simplifyIfEqBranches(eq.branches, eq.scope, eq.source, equations);
182
183 case Equation.WHEN()
184 algorithm
185
4/4
✓ Branch 0 taken 361 times.
✓ Branch 1 taken 320 times.
✓ Branch 2 taken 361 times.
✓ Branch 3 taken 320 times.
681 eq.branches := list(
186 match b
187 case Equation.Branch.BRANCH()
188 algorithm
189 361 b.condition := SimplifyExp.simplify(b.condition);
190 361 b.body := simplifyEquations(b.body);
191 then
192 b;
193 end match
194 for b in eq.branches);
195 then
196 eq :: equations;
197
198 case Equation.ASSERT()
199 algorithm
200 4539 eq.condition := SimplifyExp.simplify(eq.condition);
201
2/2
✓ Branch 1 taken 2011 times.
✓ Branch 2 taken 2528 times.
4539 then
202 if Expression.isTrue(eq.condition) then equations else eq :: equations;
203
204 case Equation.REINIT()
205 algorithm
206 28 eq.reinitExp := SimplifyExp.simplify(eq.reinitExp);
207 then
208 eq :: equations;
209
210 case Equation.NORETCALL()
211 algorithm
212 66 e := SimplifyExp.simplify(eq.exp);
213
214
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 if Expression.isCall(e) then
215 66 eq.exp := removeEmptyFunctionArguments(e);
216 equations := eq :: equations;
217 end if;
218 then
219 equations;
220
221 else eq :: equations;
222 end match;
223 end simplifyEquation;
224
225 function simplifyEqualityEquation
226 input Equation eq;
227 input output list<Equation> equations;
228 protected
229 Expression lhs, rhs;
230 Type ty;
231 DAE.ElementSource src;
232 NFInstNode.ScopeRef scope;
233 Equation.ScalarizeMode scalarize_mode;
234 algorithm
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138341 times.
138341 Equation.EQUALITY(lhs = lhs, rhs = rhs, ty = ty, scope = scope, source = src, scalarizeMode = scalarize_mode) := eq;
236 138341 ty := Type.mapDims(ty, simplifyDimension);
237
238
2/2
✓ Branch 1 taken 2346 times.
✓ Branch 2 taken 135995 times.
138341 if Type.isEmptyArray(ty) then
239 2346 return;
240 end if;
241
242 135995 lhs := SimplifyExp.simplify(lhs);
243 135995 lhs := removeEmptyTupleElements(lhs);
244 135995 rhs := SimplifyExp.simplify(rhs);
245 135995 rhs := removeEmptyFunctionArguments(rhs);
246
247 equations := match (lhs, rhs)
248 case (Expression.TUPLE(), Expression.TUPLE())
249 4 then simplifyTupleElement(lhs.elements, rhs.elements, ty, src,
250 function Equation.makeEquality(scope = InstNode.fromCell(scope), scalarizeMode = scalarize_mode), equations);
251
252 135991 else Equation.EQUALITY(lhs, rhs, ty, scope, src, scalarize_mode) :: equations;
253 end match;
254 end simplifyEqualityEquation;
255
256 function simplifyAlgorithms
257 input list<Algorithm> algs;
258 output list<Algorithm> outAlgs = {};
259 algorithm
260
2/2
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 3148 times.
3345 for alg in algs loop
261 197 alg := simplifyAlgorithm(alg);
262
263
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 1 time.
197 if not listEmpty(alg.statements) then
264 outAlgs := alg :: outAlgs;
265 end if;
266 end for;
267
268 3148 outAlgs := listReverseInPlace(outAlgs);
269 end simplifyAlgorithms;
270
271 function simplifyAlgorithm
272 input output Algorithm alg;
273 algorithm
274 1377 alg.statements := simplifyStatements(alg.statements);
275 end simplifyAlgorithm;
276
277 function simplifyStatements
278 input list<Statement> stmts;
279 output list<Statement> outStmts = {};
280 algorithm
281
2/2
✓ Branch 0 taken 110866 times.
✓ Branch 1 taken 23153 times.
134019 for s in stmts loop
282 110866 outStmts := simplifyStatement(s, outStmts);
283 end for;
284
285 23153 outStmts := listReverseInPlace(outStmts);
286 end simplifyStatements;
287
288 function simplifyStatement
289 input Statement stmt;
290 input output list<Statement> statements;
291 algorithm
292 statements := match stmt
293 local
294 Expression e;
295 Dimension dim;
296 list<Statement> body;
297
298 101577 case Statement.ASSIGNMENT() then simplifyAssignment(stmt, statements);
299
300 // if there are no body equations, remove the for-loop
301 case Statement.FOR(body = {}) then statements;
302
303 case Statement.FOR(range = SOME(e))
304 algorithm
305 512 dim := Type.nthDimension(Expression.typeOf(e), 1);
306
307 //if Dimension.isOne(dim) then
308 // // Unroll the loop if the iteration range consists of only one value.
309 // e := Expression.applySubscript(Subscript.INDEX(Expression.INTEGER(1)), e);
310 // body := Statement.replaceIteratorList(stmt.body, stmt.iterator, e);
311 // body := simplifyStatements(body);
312 // statements := listAppend(listReverse(body), statements);
313 //elseif not Dimension.isZero(dim) then
314
2/2
✓ Branch 1 taken 504 times.
✓ Branch 2 taken 8 times.
512 if not Dimension.isZero(dim) then
315 // Otherwise just simplify if the iteration range is not empty.
316 1008 stmt.range := SOME(SimplifyExp.simplify(e));
317 504 stmt.body := simplifyStatements(stmt.body);
318 statements := stmt :: statements;
319 end if;
320 then
321 statements;
322
323 case Statement.IF()
324 4914 then simplifyIfStmtBranches(stmt.branches, stmt.source, Statement.makeIf, simplifyStatements, statements);
325
326 case Statement.WHEN()
327 algorithm
328 109 stmt.branches := simplifyWhenBranches(stmt.branches);
329
2/2
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 1 time.
109 then
330 if listEmpty(stmt.branches) then statements else stmt :: statements;
331
332 case Statement.ASSERT()
333 algorithm
334 3407 stmt.condition := SimplifyExp.simplify(stmt.condition);
335 3407 stmt.message := SimplifyExp.simplify(stmt.message);
336 3407 stmt.level := SimplifyExp.simplify(stmt.level);
337 then
338 stmt :: statements;
339
340 case Statement.TERMINATE()
341 algorithm
342 1 stmt.message := SimplifyExp.simplify(stmt.message);
343 then
344 stmt :: statements;
345
346 case Statement.WHILE()
347 algorithm
348 206 stmt.condition := SimplifyExp.simplify(stmt.condition);
349 206 stmt.body := simplifyStatements(stmt.body);
350 then
351 stmt :: statements;
352
353 case Statement.NORETCALL()
354 algorithm
355 117 e := SimplifyExp.simplify(stmt.exp);
356
357
1/2
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
117 if Expression.isCall(e) then
358 117 stmt.exp := removeEmptyFunctionArguments(e);
359 statements := stmt :: statements;
360 end if;
361 then
362 statements;
363
364 else stmt :: statements;
365 end match;
366 end simplifyStatement;
367
368 function simplifyWhenBranches
369 input output list<tuple<Expression, list<Statement>>> branches;
370 algorithm
371 branches := match branches
372 local
373 Expression condition;
374 list<Statement> body;
375 list<tuple<Expression, list<Statement>>> tail;
376 case (condition, body) :: tail algorithm
377 145 condition := SimplifyExp.simplify(condition);
378 145 body := simplifyStatements(body);
379 // if the condition is a constant boolean -> skip this unreachable branch
380
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 144 times.
145 then if Expression.isBoolean(condition) then simplifyWhenBranches(tail) else (condition, body) :: simplifyWhenBranches(tail);
381 else branches;
382 end match;
383 end simplifyWhenBranches;
384
385 function simplifyAssignment
386 input Statement stmt;
387 input output list<Statement> statements;
388 protected
389 Expression lhs, rhs;
390 Type ty;
391 DAE.ElementSource src;
392 algorithm
393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 101577 times.
101577 Statement.ASSIGNMENT(lhs = lhs, rhs = rhs, ty = ty, source = src) := stmt;
394 101577 ty := Type.mapDims(ty, simplifyDimension);
395
396
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 101569 times.
101577 if Type.isEmptyArray(ty) then
397 8 return;
398 end if;
399
400 101569 lhs := SimplifyExp.simplify(lhs);
401 101569 lhs := removeEmptyTupleElements(lhs);
402 101569 rhs := SimplifyExp.simplify(rhs);
403 101569 rhs := removeEmptyFunctionArguments(rhs);
404
405 statements := match (lhs, rhs)
406 case (Expression.TUPLE(), Expression.TUPLE())
407 1 then simplifyTupleElement(lhs.elements, rhs.elements, ty, src, Statement.makeAssignment, statements);
408
409 101568 else Statement.ASSIGNMENT(lhs, rhs, ty, src) :: statements;
410 end match;
411 end simplifyAssignment;
412
413 function simplifyTupleElement<ElementT>
414 "Helper function to simplifyEqualityEquation/simplifyAssignment.
415 Handles Expression.TUPLE() := Expression.TUPLE() assignments by splitting
416 them into a separate assignment statement for each pair of tuple elements."
417 input list<Expression> lhsTuple;
418 input list<Expression> rhsTuple;
419 input Type ty;
420 input DAE.ElementSource src;
421 input MakeElement makeFn;
422 input output list<ElementT> statements;
423
424 partial function MakeElement
425 input Expression lhs;
426 input Expression rhs;
427 input Type ty;
428 input DAE.ElementSource src;
429 output ElementT element;
430 end MakeElement;
431 protected
432 Expression rhs;
433 list<Expression> rest_rhs = rhsTuple;
434 Type ety;
435 list<Type> rest_ty;
436 algorithm
437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 Type.TUPLE(types = rest_ty) := ty;
438
439
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 5 times.
16 for lhs in lhsTuple loop
440
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 rhs :: rest_rhs := rest_rhs;
441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 ety :: rest_ty := rest_ty;
442
443
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1 time.
11 if not Expression.isWildCref(lhs) then
444
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 time.
10 statements := makeFn(lhs, rhs, ety, src) :: statements;
445 end if;
446 end for;
447 end simplifyTupleElement;
448
449 function removeEmptyTupleElements
450 "Replaces tuple elements that has one or more zero dimension with _."
451 input output Expression exp;
452 algorithm
453 () := match exp
454 local
455 list<Type> tyl;
456
457 case Expression.TUPLE(ty = Type.TUPLE(types = tyl))
458 algorithm
459
9/10
✓ Branch 0 taken 1854 times.
✓ Branch 1 taken 827 times.
✓ Branch 2 taken 1854 times.
✓ Branch 3 taken 827 times.
✓ Branch 4 taken 1854 times.
✓ Branch 5 taken 827 times.
✓ Branch 7 taken 25 times.
✓ Branch 8 taken 1829 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 827 times.
3508 exp.elements := list(
460 if Type.isEmptyArray(t) then Expression.CREF(t, ComponentRef.WILD()) else e
461 threaded for e in exp.elements, t in tyl);
462 then
463 ();
464
465 else ();
466 end match;
467 end removeEmptyTupleElements;
468
469 function removeEmptyFunctionArguments
470 input Expression exp;
471 input Boolean isArg = false;
472 output Expression outExp;
473 protected
474 Boolean is_arg;
475 algorithm
476
2/2
✓ Branch 0 taken 235835 times.
✓ Branch 1 taken 2694074 times.
2929909 if isArg then
477 () := match exp
478 case Expression.CREF() guard Type.isEmptyArray(exp.ty)
479 algorithm
480 161 outExp := Expression.fillType(exp.ty, Expression.INTEGER(0));
481 161 return;
482 then
483 ();
484
485 else ();
486 end match;
487 end if;
488
489
4/4
✓ Branch 0 taken 2694074 times.
✓ Branch 1 taken 235674 times.
✓ Branch 3 taken 49804 times.
✓ Branch 4 taken 2644270 times.
2929748 is_arg := isArg or Expression.isCall(exp);
490 2929748 outExp := Expression.mapShallow(exp, function removeEmptyFunctionArguments(isArg = is_arg));
491 end removeEmptyFunctionArguments;
492
493 function simplifyIfEqBranches
494 input list<Equation.Branch> branches;
495 input NFInstNode.ScopeRef scope;
496 input DAE.ElementSource src;
497 input output list<Equation> elements;
498 protected
499 Expression cond;
500 list<Equation> body;
501 Variability var;
502 list<Equation.Branch> accum = {};
503 algorithm
504
2/2
✓ Branch 0 taken 2065 times.
✓ Branch 1 taken 186 times.
2251 for branch in branches loop
505 accum := match branch
506 case Equation.Branch.BRANCH(cond, var, body)
507 algorithm
508 2060 cond := SimplifyExp.simplify(cond);
509
510 // A branch with condition true will always be selected when encountered.
511
2/2
✓ Branch 1 taken 1241 times.
✓ Branch 2 taken 819 times.
2060 if Expression.isTrue(cond) then
512
2/2
✓ Branch 0 taken 1077 times.
✓ Branch 1 taken 164 times.
1241 if listEmpty(accum) then
513 // If it's the first branch, remove the if and keep only the branch body.
514
2/2
✓ Branch 0 taken 2236 times.
✓ Branch 1 taken 1077 times.
3313 for eq in body loop
515 2236 elements := simplifyEquation(eq, elements);
516 end for;
517 1077 return;
518 else
519 // Otherwise just discard the rest of the branches.
520 164 accum := Equation.makeBranch(cond, simplifyEquations(body)) :: accum;
521 164 accum := List.trim(accum, Equation.Branch.isEmpty);
522 164 elements := Equation.makeIf(listReverseInPlace(accum), InstNode.fromCell(scope), src) :: elements;
523 164 return;
524 end if;
525 elseif not Expression.isFalse(cond) then
526 // Keep branches that are neither literal true or false.
527 459 accum := Equation.makeBranch(cond, simplifyEquations(body)) :: accum;
528 end if;
529 then
530 accum;
531
532 case Equation.INVALID_BRANCH(branch =
533 Equation.Branch.BRANCH(condition = cond, conditionVar = var))
534 algorithm
535
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5 if var <= Variability.STRUCTURAL_PARAMETER then
536 4 cond := Ceval.evalExp(cond);
537 end if;
538
539 // An invalid branch that can't be removed will trigger the errors
540 // stored in it.
541
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
5 if not Expression.isFalse(cond) then
542 2 Equation.Branch.triggerErrors(branch);
543 end if;
544 then
545 accum;
546
547 else branch :: accum;
548 end match;
549 end for;
550
551 186 accum := List.trim(accum, Equation.Branch.isEmpty);
552
553
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 19 times.
186 if not listEmpty(accum) then
554 19 elements := Equation.makeIf(listReverseInPlace(accum), InstNode.fromCell(scope), src) :: elements;
555 end if;
556 end simplifyIfEqBranches;
557
558 function simplifyIfStmtBranches<ElemT>
559 input list<tuple<Expression, list<ElemT>>> branches;
560 input DAE.ElementSource src;
561 input MakeFunc makeFunc;
562 input SimplifyFunc simplifyFunc;
563 input output list<ElemT> elements;
564
565 partial function MakeFunc
566 input list<tuple<Expression, list<ElemT>>> branches;
567 input DAE.ElementSource src;
568 output ElemT element;
569 end MakeFunc;
570
571 partial function SimplifyFunc
572 input output list<ElemT> elements;
573 end SimplifyFunc;
574 protected
575 Expression cond;
576 list<ElemT> body;
577 list<tuple<Expression, list<ElemT>>> accum = {};
578 algorithm
579
2/2
✓ Branch 0 taken 10700 times.
✓ Branch 1 taken 1200 times.
11900 for branch in branches loop
580 10700 (cond, body) := branch;
581 10700 cond := SimplifyExp.simplify(cond);
582
583 // A branch with condition true will always be selected when encountered.
584
2/2
✓ Branch 1 taken 3714 times.
✓ Branch 2 taken 6986 times.
10700 if Expression.isTrue(cond) then
585
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 3691 times.
3714 if listEmpty(accum) then
586 // If it's the first branch, remove the if and keep only the branch body.
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 elements := listAppend(listReverse(simplifyFunc(body)), elements);
588 23 return;
589 else
590 // Otherwise just discard the rest of the branches.
591
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3691 times.
3691 accum := (cond, simplifyFunc(body)) :: accum;
592 3691 break;
593 end if;
594 elseif not Expression.isFalse(cond) then
595 // Keep branches that are neither literal true or false.
596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6962 times.
6962 accum := (cond, simplifyFunc(body)) :: accum;
597 end if;
598 end for;
599
600
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4883 times.
4891 if not listEmpty(accum) then
601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4883 times.
4883 elements := makeFunc(listReverseInPlace(accum), src) :: elements;
602 end if;
603 end simplifyIfStmtBranches;
604
605 function simplifyFunction
606 input Function func;
607 protected
608 Class cls;
609 Algorithm fn_body;
610 Sections sections;
611 algorithm
612
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12185 times.
12185 if not Function.isSimplified(func) then
613 12185 Function.markSimplified(func);
614 12185 Function.mapExp(func, function SimplifyExp.simplify(includeScope = false), mapBody = false);
615
616 12185 cls := InstNode.getClass(InstNode.fromHandle(func.node));
617 () := match cls
618 case Class.INSTANCED_CLASS(sections = sections)
619 algorithm
620 () := match sections
621 case Sections.SECTIONS(algorithms = {fn_body})
622 algorithm
623 10245 fn_body.statements := simplifyStatements(fn_body.statements);
624 10245 sections.algorithms := {fn_body};
625 10245 cls.sections := sections;
626 10245 InstNode.updateClass(cls, InstNode.fromHandle(func.node));
627 then
628 ();
629
630 else ();
631 end match;
632 then
633 ();
634
635 else ();
636 end match;
637
638
2/2
✓ Branch 0 taken 800 times.
✓ Branch 1 taken 12185 times.
12985 for fn_der in func.derivatives loop
639
2/2
✓ Branch 2 taken 800 times.
✓ Branch 3 taken 800 times.
1600 for der_fn in Function.getCachedFuncs(InstNode.borrow(fn_der.derivativeFn)) loop
640 800 simplifyFunction(der_fn);
641 end for;
642 end for;
643 end if;
644 end simplifyFunction;
645
646 function combineBinaries
647 "author: kabdelhak 09-2020
648 Combines binaries for better handling in the backend.
649 NOTE: does not do any other simplification
650 e.g. BINARY(BINARY(2, /, y^2), *, BINARY(3, *, x))
651 --> MULTARY({2, 3, x}, {y^2}, *)"
652 input output FlatModel flatModel;
653 algorithm
654
20/20
✓ Branch 0 taken 6432 times.
✓ Branch 1 taken 203 times.
✓ Branch 2 taken 6432 times.
✓ Branch 3 taken 203 times.
✓ Branch 5 taken 4064 times.
✓ Branch 6 taken 203 times.
✓ Branch 7 taken 4064 times.
✓ Branch 8 taken 203 times.
✓ Branch 10 taken 84 times.
✓ Branch 11 taken 203 times.
✓ Branch 12 taken 84 times.
✓ Branch 13 taken 203 times.
✓ Branch 15 taken 11 times.
✓ Branch 16 taken 203 times.
✓ Branch 17 taken 11 times.
✓ Branch 18 taken 203 times.
✓ Branch 20 taken 6 times.
✓ Branch 21 taken 203 times.
✓ Branch 22 taken 6 times.
✓ Branch 23 taken 203 times.
10800 flatModel.variables := list(Variable.mapExp(var, SimplifyExp.combineBinaries) for var in flatModel.variables);
655 flatModel.equations := list(Equation.mapExp(eqn, SimplifyExp.combineBinaries) for eqn in flatModel.equations);
656 flatModel.initialEquations := list(Equation.mapExp(eqn, SimplifyExp.combineBinaries) for eqn in flatModel.initialEquations);
657 flatModel.algorithms := list(Algorithm.mapExp(alg, SimplifyExp.combineBinaries) for alg in flatModel.algorithms);
658 flatModel.initialAlgorithms := list(Algorithm.mapExp(alg, SimplifyExp.combineBinaries) for alg in flatModel.initialAlgorithms);
659 end combineBinaries;
660
661 annotation(__OpenModelica_Interface="nf_frontend");
662 end NFSimplifyModel;
663