Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit 3b38d7b

Browse files
perostOpenModelica-Hudson
authored andcommitted
[NF] Improved parameter evaluation analysis.
- Avoid evaluating parameters that are non-final or depend on non-final parameters when Evaluate=true or -d=evaluateAllParameters is used. - Evaluate parameters that are both fixed and final if their bindings are also fixed and final. - Propagate finalness from modifiers to components, to better exploit the above optimization. Belonging to [master]: - #2990 - OpenModelica/OpenModelica-testsuite#1144
1 parent 050a820 commit 3b38d7b

File tree

6 files changed

+328
-27
lines changed

6 files changed

+328
-27
lines changed

Compiler/NFFrontEnd/NFBinding.mo

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,24 @@ public
605605
end match;
606606
end mapExp;
607607

608+
function containsExp
609+
input Binding binding;
610+
input PredFunc predFn;
611+
output Boolean res;
612+
613+
partial function PredFunc
614+
input Expression exp;
615+
output Boolean res;
616+
end PredFunc;
617+
algorithm
618+
res := match binding
619+
case UNTYPED_BINDING() then Expression.contains(binding.bindingExp, predFn);
620+
case TYPED_BINDING() then Expression.contains(binding.bindingExp, predFn);
621+
case FLAT_BINDING() then Expression.contains(binding.bindingExp, predFn);
622+
case CEVAL_BINDING() then Expression.contains(binding.bindingExp, predFn);
623+
else false;
624+
end match;
625+
end containsExp;
608626
end Binding;
609627

610628
annotation(__OpenModelica_Interface="frontend");

Compiler/NFFrontEnd/NFComponent.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ uniontype Component
826826
return;
827827
end if;
828828

829-
fixed := fixed and Expression.isTrue(Binding.getTypedExp(binding));
829+
fixed := fixed and Expression.isTrue(Binding.getExp(binding));
830830

831831
end getFixedAttribute;
832832

Compiler/NFFrontEnd/NFExpression.mo

Lines changed: 141 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3814,34 +3814,13 @@ public
38143814
algorithm
38153815
res := match cref
38163816
case ComponentRef.CREF()
3817-
then subscriptsContains(cref.subscripts, func) or
3817+
then Subscript.listContainsExp(cref.subscripts, func) or
38183818
crefContains(cref.restCref, func);
38193819

38203820
else false;
38213821
end match;
38223822
end crefContains;
38233823

3824-
function subscriptsContains
3825-
input list<Subscript> subs;
3826-
input ContainsPred func;
3827-
output Boolean res;
3828-
algorithm
3829-
for s in subs loop
3830-
res := match s
3831-
case Subscript.UNTYPED() then contains(s.exp, func);
3832-
case Subscript.INDEX() then contains(s.index, func);
3833-
case Subscript.SLICE() then contains(s.slice, func);
3834-
else false;
3835-
end match;
3836-
3837-
if res then
3838-
return;
3839-
end if;
3840-
end for;
3841-
3842-
res := false;
3843-
end subscriptsContains;
3844-
38453824
function listContains
38463825
input list<Expression> expl;
38473826
input ContainsPred func;
@@ -3911,6 +3890,146 @@ public
39113890
end match;
39123891
end callContains;
39133892

3893+
function containsShallow
3894+
input Expression exp;
3895+
input ContainsPred func;
3896+
output Boolean res;
3897+
algorithm
3898+
res := match exp
3899+
case CREF() then crefContainsShallow(exp.cref, func);
3900+
case ARRAY() then listContainsShallow(exp.elements, func);
3901+
3902+
case MATRIX()
3903+
algorithm
3904+
res := false;
3905+
3906+
for row in exp.elements loop
3907+
if listContainsShallow(row, func) then
3908+
res := true;
3909+
break;
3910+
end if;
3911+
end for;
3912+
then
3913+
res;
3914+
3915+
case RANGE()
3916+
then func(exp.start) or
3917+
Util.applyOptionOrDefault(exp.step, func, false) or
3918+
func(exp.stop);
3919+
3920+
case TUPLE() then listContainsShallow(exp.elements, func);
3921+
case RECORD() then listContainsShallow(exp.elements, func);
3922+
case CALL() then callContainsShallow(exp.call, func);
3923+
3924+
case SIZE()
3925+
then Util.applyOptionOrDefault(exp.dimIndex, func, false) or
3926+
func(exp.exp);
3927+
3928+
case BINARY() then func(exp.exp1) or func(exp.exp2);
3929+
case UNARY() then func(exp.exp);
3930+
case LBINARY() then func(exp.exp1) or func(exp.exp2);
3931+
case LUNARY() then func(exp.exp);
3932+
case RELATION() then func(exp.exp1) or func(exp.exp2);
3933+
case IF() then func(exp.condition) or func(exp.trueBranch) or func(exp.falseBranch);
3934+
case CAST() then func(exp.exp);
3935+
case UNBOX() then func(exp.exp);
3936+
3937+
case SUBSCRIPTED_EXP()
3938+
then func(exp.exp) or Subscript.listContainsExpShallow(exp.subscripts, func);
3939+
3940+
case TUPLE_ELEMENT() then func(exp.tupleExp);
3941+
case RECORD_ELEMENT() then func(exp.recordExp);
3942+
case PARTIAL_FUNCTION_APPLICATION() then listContains(exp.args, func);
3943+
case BOX() then func(exp.exp);
3944+
else false;
3945+
end match;
3946+
end containsShallow;
3947+
3948+
function crefContainsShallow
3949+
input ComponentRef cref;
3950+
input ContainsPred func;
3951+
output Boolean res;
3952+
algorithm
3953+
res := match cref
3954+
case ComponentRef.CREF()
3955+
then Subscript.listContainsExpShallow(cref.subscripts, func) or
3956+
crefContainsShallow(cref.restCref, func);
3957+
3958+
else false;
3959+
end match;
3960+
end crefContainsShallow;
3961+
3962+
function listContainsShallow
3963+
input list<Expression> expl;
3964+
input ContainsPred func;
3965+
output Boolean res;
3966+
algorithm
3967+
for e in expl loop
3968+
if func(e) then
3969+
res := true;
3970+
return;
3971+
end if;
3972+
end for;
3973+
3974+
res := false;
3975+
end listContainsShallow;
3976+
3977+
function callContainsShallow
3978+
input Call call;
3979+
input ContainsPred func;
3980+
output Boolean res;
3981+
algorithm
3982+
res := match call
3983+
local
3984+
Expression e;
3985+
3986+
case Call.UNTYPED_CALL()
3987+
algorithm
3988+
res := listContainsShallow(call.arguments, func);
3989+
3990+
if not res then
3991+
for arg in call.named_args loop
3992+
(_, e) := arg;
3993+
3994+
if func(e) then
3995+
res := true;
3996+
break;
3997+
end if;
3998+
end for;
3999+
end if;
4000+
then
4001+
res;
4002+
4003+
case Call.ARG_TYPED_CALL()
4004+
algorithm
4005+
for arg in call.arguments loop
4006+
(e, _, _) := arg;
4007+
4008+
if func(e) then
4009+
res := true;
4010+
return;
4011+
end if;
4012+
end for;
4013+
4014+
for arg in call.named_args loop
4015+
(_, e, _, _) := arg;
4016+
4017+
if func(e) then
4018+
res := true;
4019+
return;
4020+
end if;
4021+
end for;
4022+
then
4023+
false;
4024+
4025+
case Call.TYPED_CALL() then listContainsShallow(call.arguments, func);
4026+
case Call.UNTYPED_ARRAY_CONSTRUCTOR() then func(call.exp);
4027+
case Call.TYPED_ARRAY_CONSTRUCTOR() then func(call.exp);
4028+
case Call.UNTYPED_REDUCTION() then func(call.exp);
4029+
case Call.TYPED_REDUCTION() then func(call.exp);
4030+
end match;
4031+
end callContainsShallow;
4032+
39144033
function arrayFirstScalar
39154034
"Returns the first scalar element of an array. Fails if the array is empty."
39164035
input Expression arrayExp;

Compiler/NFFrontEnd/NFInst.mo

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,10 @@ algorithm
14071407
attr := mergeRedeclaredComponentAttributes(Util.getOption(originalAttr), attr, node);
14081408
end if;
14091409

1410+
if not attr.isFinal and Modifier.isFinal(mod) then
1411+
attr.isFinal := true;
1412+
end if;
1413+
14101414
// Create the untyped component and update the node with it. We need the
14111415
// untyped component in instClass to make sure everything is scoped
14121416
// correctly during lookup, but the class node the component should have
@@ -3185,21 +3189,21 @@ algorithm
31853189

31863190
case Component.UNTYPED_COMPONENT(binding = binding, condition = condition)
31873191
algorithm
3188-
// @adrpo: if Evaluate=true make the parameter a structural parameter
3189-
// only make it a structural parameter if is not constant, duh!, 1071 regressions :)
3190-
if c.attributes.variability == Variability.PARAMETER and
3191-
(Component.getEvaluateAnnotation(c) or evalAllParams) then
3192+
if isStructuralComponent(c, c.attributes, binding, node, evalAllParams) then
31923193
markStructuralParamsComp(c, node);
31933194
end if;
31943195

3196+
// Parameters used in array dimensions are structural.
31953197
for dim in c.dimensions loop
31963198
markStructuralParamsDim(dim);
31973199
end for;
31983200

3201+
// Parameters that determine the size of a component binding are structural.
31993202
if Binding.isBound(binding) then
32003203
markStructuralParamsExpSize(Binding.getUntypedExp(binding));
32013204
end if;
32023205

3206+
// Parameters used in a component condition are structural.
32033207
if Binding.isBound(condition) then
32043208
markStructuralParamsExp(Binding.getUntypedExp(condition));
32053209
end if;
@@ -3223,6 +3227,128 @@ algorithm
32233227
end match;
32243228
end updateImplicitVariabilityComp;
32253229

3230+
function isStructuralComponent
3231+
input Component component;
3232+
input Component.Attributes compAttrs;
3233+
input Binding compBinding;
3234+
input InstNode compNode;
3235+
input Boolean evalAllParams;
3236+
output Boolean isStructural;
3237+
protected
3238+
Boolean is_fixed;
3239+
algorithm
3240+
if compAttrs.variability <> Variability.PARAMETER then
3241+
// Only parameters can be structural.
3242+
isStructural := false;
3243+
elseif evalAllParams or Component.getEvaluateAnnotation(component) then
3244+
// If -d=evaluateAllParameters is set or the parameter has an Evaluate=true
3245+
// annotation we should probably evaluate the parameter, which we do by
3246+
// marking it as structural.
3247+
if not Component.getFixedAttribute(component) then
3248+
// Except non-fixed parameters.
3249+
isStructural := false;
3250+
elseif Binding.isUnbound(compBinding) then
3251+
// Except parameters with no bindings.
3252+
if not evalAllParams then
3253+
// Print a warning if a parameter has an Evaluate=true annotation but no binding.
3254+
Error.addSourceMessage(Error.UNBOUND_PARAMETER_EVALUATE_TRUE,
3255+
{InstNode.name(compNode)}, InstNode.info(compNode));
3256+
end if;
3257+
3258+
isStructural := false;
3259+
elseif isBindingNotFixed(compBinding, requireFinal = false) then
3260+
// Except parameters that depend on non-fixed parameters.
3261+
isStructural := false;
3262+
else
3263+
// All other parameters are considered structural in this case.
3264+
isStructural := true;
3265+
end if;
3266+
elseif Component.isFinal(component) and Component.getFixedAttribute(component) then
3267+
// If a parameter is fixed and final we might also want to evaluate it,
3268+
// since its binding can't be modified. But only if all parameters it
3269+
// depends on are also fixed and final.
3270+
if Binding.isUnbound(compBinding) or isBindingNotFixed(compBinding, requireFinal = true) then
3271+
isStructural := false;
3272+
else
3273+
isStructural := true;
3274+
end if;
3275+
else
3276+
isStructural := false;
3277+
end if;
3278+
end isStructuralComponent;
3279+
3280+
function isBindingNotFixed
3281+
input Binding binding;
3282+
input Boolean requireFinal;
3283+
input Integer depth = 1;
3284+
output Boolean isNotFixed;
3285+
algorithm
3286+
if depth > 4 then
3287+
isNotFixed := true;
3288+
return;
3289+
end if;
3290+
3291+
isNotFixed := match binding
3292+
case Binding.UNTYPED_BINDING()
3293+
then isExpressionNotFixed(binding.bindingExp, requireFinal, depth);
3294+
3295+
else false;
3296+
end match;
3297+
end isBindingNotFixed;
3298+
3299+
function isExpressionNotFixed
3300+
input Expression exp;
3301+
input Boolean requireFinal;
3302+
input Integer depth;
3303+
output Boolean isNotFixed;
3304+
algorithm
3305+
isNotFixed := match exp
3306+
local
3307+
InstNode node;
3308+
Component c;
3309+
Variability var;
3310+
Expression e;
3311+
3312+
case Expression.CREF()
3313+
algorithm
3314+
node := ComponentRef.node(exp.cref);
3315+
3316+
if InstNode.isComponent(node) then
3317+
c := InstNode.component(node);
3318+
var := Component.variability(c);
3319+
3320+
if var <= Variability.STRUCTURAL_PARAMETER then
3321+
isNotFixed := false;
3322+
elseif var == Variability.PARAMETER and
3323+
(not requireFinal or Component.isFinal(c)) and
3324+
Component.getFixedAttribute(c) then
3325+
isNotFixed := isBindingNotFixed(Component.getBinding(c), requireFinal, depth + 1);
3326+
else
3327+
isNotFixed := true;
3328+
end if;
3329+
else
3330+
isNotFixed := true;
3331+
end if;
3332+
then
3333+
isNotFixed or
3334+
Expression.containsShallow(exp,
3335+
function isExpressionNotFixed(requireFinal = requireFinal, depth = depth));
3336+
3337+
case Expression.SIZE()
3338+
algorithm
3339+
if isSome(exp.dimIndex) then
3340+
isNotFixed := isExpressionNotFixed(Util.getOption(exp.dimIndex), requireFinal, depth);
3341+
else
3342+
isNotFixed := false;
3343+
end if;
3344+
then
3345+
isNotFixed;
3346+
3347+
else Expression.containsShallow(exp,
3348+
function isExpressionNotFixed(requireFinal = requireFinal, depth = depth));
3349+
end match;
3350+
end isExpressionNotFixed;
3351+
32263352
function markStructuralParamsDim
32273353
input Dimension dimension;
32283354
algorithm

Compiler/NFFrontEnd/NFModifier.mo

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,16 @@ public
479479
end match;
480480
end isEach;
481481

482+
function isFinal
483+
input Modifier mod;
484+
output Boolean isFinal;
485+
algorithm
486+
isFinal := match mod
487+
case MODIFIER(finalPrefix = SCode.FINAL()) then true;
488+
else false;
489+
end match;
490+
end isFinal;
491+
482492
function map
483493
input output Modifier mod;
484494
input FuncT func;

0 commit comments

Comments
 (0)