Skip to content

Commit

Permalink
[NF] SimplifyExp improvements.
Browse files Browse the repository at this point in the history
- Added trivial simplifications of binary expressions, such as 0*e=0.
- Added simplification of transpose of an array expression.
- Turned off expansion of expressions containing calls to functions with
  array return type when -d=nfExpandOperations is used (on by default),
  to better mimic the old frontend and avoid unnecessary calls.
- Rearranged SimplifyExp and ExpandExp a bit so that expressions are
  always simplified before being expanded with -d=nfExpandOperations.
- Try to expand the argument in Expression.promoteExp to avoid getting
  promote calls in the flat model that the backend can't handle.

Belonging to [master]:
  - OpenModelica/OMCompiler#2634
  - OpenModelica/OpenModelica-testsuite#1024
  • Loading branch information
perost authored and OpenModelica-Hudson committed Sep 6, 2018
1 parent 7b82c41 commit cbc69f9
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 48 deletions.
42 changes: 10 additions & 32 deletions Compiler/NFFrontEnd/NFExpandExp.mo
Expand Up @@ -465,7 +465,7 @@ public
end if;

if expanded then
outExp := expandBinaryElementWise2(exp1, op, exp2, makeBinaryOp);
outExp := expandBinaryElementWise2(exp1, op, exp2, SimplifyExp.simplifyBinaryOp);
else
outExp := exp;
end if;
Expand Down Expand Up @@ -522,7 +522,8 @@ public

if expanded then
op := Operator.OPERATOR(Type.arrayElementType(Operator.typeOf(op)), scalarOp);
outExp := Expression.mapArrayElements(exp2, function makeBinaryOp(op = op, exp1 = exp1));
outExp := Expression.mapArrayElements(exp2,
function SimplifyExp.simplifyBinaryOp(op = op, exp1 = exp1));
else
outExp := exp;
end if;
Expand All @@ -536,7 +537,7 @@ public
algorithm
exp := match exp2
case Expression.ARRAY() then exp2;
else makeBinaryOp(exp1, op, exp2);
else SimplifyExp.simplifyBinaryOp(exp1, op, exp2);
end match;
end makeScalarArrayBinary_traverser;

Expand All @@ -555,7 +556,8 @@ public

if expanded then
op := Operator.OPERATOR(Type.arrayElementType(Operator.typeOf(op)), scalarOp);
outExp := Expression.mapArrayElements(exp1, function makeBinaryOp(op = op, exp2 = exp2));
outExp := Expression.mapArrayElements(exp1,
function SimplifyExp.simplifyBinaryOp(op = op, exp2 = exp2));
else
outExp := exp;
end if;
Expand Down Expand Up @@ -675,8 +677,8 @@ public
end if;
mul_op := Operator.makeMul(tyUnlift);
add_op := Operator.makeAdd(tyUnlift);
expl1 := list(makeBinaryOp(e1, mul_op, e2) threaded for e1 in expl1, e2 in expl2);
exp := List.reduce(expl1, function makeBinaryOp(op = add_op));
expl1 := list(SimplifyExp.simplifyBinaryOp(e1, mul_op, e2) threaded for e1 in expl1, e2 in expl2);
exp := List.reduce(expl1, function SimplifyExp.simplifyBinaryOp(op = add_op));
end makeScalarProduct;

function expandBinaryMatrixProduct
Expand Down Expand Up @@ -800,19 +802,6 @@ public
end match;
end expandBinaryPowMatrix2;

function makeBinaryOp
input Expression exp1;
input Operator op;
input Expression exp2;
output Expression exp;
algorithm
if Expression.isScalarLiteral(exp1) and Expression.isScalarLiteral(exp2) then
exp := Ceval.evalBinaryOp(exp1, op, exp2);
else
exp := Expression.BINARY(exp1, op, exp2);
end if;
end makeBinaryOp;

function expandUnary
input Expression exp;
input Operator op;
Expand All @@ -825,22 +814,11 @@ public
scalar_op := Operator.scalarize(op);

if expanded then
outExp := Expression.mapArrayElements(outExp, function makeUnaryOp(op = scalar_op));
outExp := Expression.mapArrayElements(outExp,
function SimplifyExp.simplifyUnaryOp(op = scalar_op));
end if;
end expandUnary;

function makeUnaryOp
input Expression exp1;
input Operator op;
output Expression exp;
algorithm
if Expression.isScalarLiteral(exp1) then
exp := Ceval.evalUnaryOp(exp1, op);
else
exp := Expression.UNARY(op, exp1);
end if;
end makeUnaryOp;

function expandLogicalBinary
input Expression exp;
output Expression outExp;
Expand Down
27 changes: 25 additions & 2 deletions Compiler/NFFrontEnd/NFExpression.mo
Expand Up @@ -43,6 +43,7 @@ protected
import Prefixes = NFPrefixes;
import Ceval = NFCeval;
import ComplexType = NFComplexType;
import ExpandExp = NFExpandExp;
import MetaModelica.Dangerous.listReverseInPlace;

public
Expand Down Expand Up @@ -2924,6 +2925,18 @@ public
end match;
end isZero;

function isOne
input Expression exp;
output Boolean isOne;
algorithm
isOne := match exp
case INTEGER() then exp.value == 1;
case REAL() then exp.value == 1.0;
case CAST() then isOne(exp.exp);
else false;
end match;
end isOne;

function isPositive
input Expression exp;
output Boolean positive;
Expand Down Expand Up @@ -3219,6 +3232,7 @@ public
Type ty;
list<Type> rest_ty;
Expression arr_exp;
Boolean expanded;

// No types left, we're done!
case (_, {}) then exp;
Expand All @@ -3230,8 +3244,17 @@ public
// An expression with array type, but which is not an array expression.
// Such an expression can't be promoted here, so we create a promote call instead.
case (_, _) guard isArray
then CALL(Call.makeTypedCall(
NFBuiltinFuncs.PROMOTE, {exp, INTEGER(dims)}, variability(exp), listHead(types)));
algorithm
(outExp, expanded) := ExpandExp.expand(exp);

if expanded then
outExp := promote2(outExp, true, dims, types);
else
outExp := CALL(Call.makeTypedCall(
NFBuiltinFuncs.PROMOTE, {exp, INTEGER(dims)}, variability(exp), listHead(types)));
end if;
then
outExp;

// A scalar expression, promote it as many times as the number of types given.
else
Expand Down
157 changes: 143 additions & 14 deletions Compiler/NFFrontEnd/NFSimplifyExp.mo
Expand Up @@ -181,8 +181,9 @@ algorithm
then
exp;

case "sum" then simplifySumProduct(listHead(args), call, isSum = true);
case "product" then simplifySumProduct(listHead(args), call, isSum = false);
case "sum" then simplifySumProduct(listHead(args), call, isSum = true);
case "product" then simplifySumProduct(listHead(args), call, isSum = false);
case "transpose" then simplifyTranspose(listHead(args), call);

else Expression.CALL(call);
end match;
Expand Down Expand Up @@ -221,6 +222,17 @@ algorithm
end if;
end simplifySumProduct;

function simplifyTranspose
input Expression arg;
input Call call;
output Expression exp;
algorithm
exp := match arg
case Expression.ARRAY() then Expression.transposeArray(arg);
else Expression.CALL(call);
end match;
end simplifyTranspose;

function simplifySize
input output Expression sizeExp;
algorithm
Expand Down Expand Up @@ -274,15 +286,122 @@ algorithm
se1 := simplify(e1);
se2 := simplify(e2);

if Flags.isSet(Flags.NF_EXPAND_OPERATIONS) then
binaryExp := ExpandExp.expand(ExpandExp.makeBinaryOp(se1, op, se2));
elseif Expression.isLiteral(se1) and Expression.isLiteral(se2) then
binaryExp := Ceval.evalBinaryOp(se1, op, se2);
elseif not (referenceEq(e1, se1) and referenceEq(e2, se2)) then
binaryExp := Expression.BINARY(se1, op, se2);
binaryExp := simplifyBinaryOp(se1, op, se2);

if Flags.isSet(Flags.NF_EXPAND_OPERATIONS) and not Expression.hasArrayCall(binaryExp) then
binaryExp := ExpandExp.expand(binaryExp);
end if;
end simplifyBinary;

function simplifyBinaryOp
input Expression exp1;
input Operator op;
input Expression exp2;
output Expression outExp;

import NFOperator.Op;
algorithm
if Expression.isLiteral(exp1) and Expression.isLiteral(exp2) then
outExp := Ceval.evalBinaryOp(exp1, op, exp2);
else
outExp := match op.op
case Op.ADD then simplifyBinaryAdd(exp1, op, exp2);
case Op.SUB then simplifyBinarySub(exp1, op, exp2);
case Op.MUL then simplifyBinaryMul(exp1, op, exp2);
case Op.DIV then simplifyBinaryDiv(exp1, op, exp2);
case Op.POW then simplifyBinaryPow(exp1, op, exp2);
else Expression.BINARY(exp1, op, exp2);
end match;
end if;
end simplifyBinaryOp;

function simplifyBinaryAdd
input Expression exp1;
input Operator op;
input Expression exp2;
output Expression outExp;
algorithm
if Expression.isZero(exp1) then
// 0 + e = e
outExp := exp2;
elseif Expression.isZero(exp2) then
// e + 0 = e
outExp := exp1;
else
outExp := Expression.BINARY(exp1, op, exp2);
end if;
end simplifyBinaryAdd;

function simplifyBinarySub
input Expression exp1;
input Operator op;
input Expression exp2;
output Expression outExp;
algorithm
if Expression.isZero(exp1) then
// 0 - e = -e
outExp := Expression.UNARY(Operator.makeUMinus(Operator.typeOf(op)), exp2);
elseif Expression.isZero(exp2) then
// e - 0 = e
outExp := exp1;
else
outExp := Expression.BINARY(exp1, op, exp2);
end if;
end simplifyBinarySub;

function simplifyBinaryMul
input Expression exp1;
input Operator op;
input Expression exp2;
input Boolean switched = false;
output Expression outExp;
algorithm
outExp := match exp1
// 0 * e = 0
case Expression.INTEGER(value = 0) then exp1;
case Expression.REAL(value = 0.0) then exp1;

// 1 * e = e
case Expression.INTEGER(value = 1) then exp2;
case Expression.REAL(value = 1.0) then exp2;

else
if switched then
Expression.BINARY(exp2, op, exp1)
else
simplifyBinaryMul(exp2, op, exp1, true);
end match;
end simplifyBinaryMul;

function simplifyBinaryDiv
input Expression exp1;
input Operator op;
input Expression exp2;
output Expression outExp;
algorithm
// e / 1 = e
if Expression.isOne(exp2) then
outExp := exp1;
else
outExp := Expression.BINARY(exp1, op, exp2);
end if;
end simplifyBinaryDiv;

function simplifyBinaryPow
input Expression exp1;
input Operator op;
input Expression exp2;
output Expression outExp;
algorithm
if Expression.isZero(exp2) then
outExp := Expression.makeOne(Operator.typeOf(op));
elseif Expression.isOne(exp2) then
outExp := exp1;
else
outExp := Expression.BINARY(exp1, op, exp2);
end if;
end simplifyBinaryPow;

function simplifyUnary
input output Expression unaryExp;
protected
Expand All @@ -292,15 +411,25 @@ algorithm
Expression.UNARY(op, e) := unaryExp;
se := simplify(e);

if Flags.isSet(Flags.NF_EXPAND_OPERATIONS) then
unaryExp := ExpandExp.expand(ExpandExp.makeUnaryOp(se, op));
elseif Expression.isLiteral(se) then
unaryExp := Ceval.evalUnaryOp(se, op);
elseif not referenceEq(e, se) then
unaryExp := Expression.UNARY(op, se);
unaryExp := simplifyUnaryOp(se, op);

if Flags.isSet(Flags.NF_EXPAND_OPERATIONS) and not Expression.hasArrayCall(unaryExp) then
unaryExp := ExpandExp.expand(unaryExp);
end if;
end simplifyUnary;

function simplifyUnaryOp
input Expression exp;
input Operator op;
output Expression outExp;
algorithm
if Expression.isLiteral(exp) then
outExp := Ceval.evalUnaryOp(exp, op);
else
outExp := Expression.UNARY(op, exp);
end if;
end simplifyUnaryOp;

function simplifyLogicBinary
input output Expression binaryExp;
protected
Expand Down

0 comments on commit cbc69f9

Please sign in to comment.