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

Commit

Permalink
Handle recursion better when inlining calls
Browse files Browse the repository at this point in the history
This partially fixes FCSys.Characteristics.Examples.CellPotential (still
fails to compile functions due to them using parameters).
  • Loading branch information
sjoelund authored and OpenModelica-Hudson committed Apr 20, 2017
1 parent 894837c commit eb3f80f
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 60 deletions.
2 changes: 1 addition & 1 deletion 3rdParty
41 changes: 22 additions & 19 deletions Compiler/BackEnd/BackendDAEUtil.mo
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ encapsulated package BackendDAEUtil

import Absyn;
import AvlSetInt;
import AvlSetPath;
import BackendDAE;
import BackendDAEFunc;
import DAE;
Expand Down Expand Up @@ -2591,7 +2592,7 @@ algorithm
then vallst;

case BackendDAE.SOLVABLE() equation
(_, (_, vallst, _)) = Expression.traverseExpTopDown(inExp, traversingincidenceRowExpSolvableFinder, (inVariables, inIntegerLst, functionTree));
(_, (_, vallst, _, _)) = Expression.traverseExpTopDown(inExp, traversingincidenceRowExpSolvableFinder, (inVariables, inIntegerLst, AvlSetPath.EMPTY(), functionTree));
then vallst;

case BackendDAE.BASECLOCK_IDX() equation
Expand All @@ -2612,10 +2613,10 @@ end incidenceRowExp;

public function traversingincidenceRowExpSolvableFinder "Helper for statesAndVarsExp"
input DAE.Exp inExp;
input tuple<BackendDAE.Variables, AvlSetInt.Tree, Option<DAE.FunctionTree>> inTpl;
input tuple<BackendDAE.Variables, AvlSetInt.Tree, AvlSetPath.Tree, Option<DAE.FunctionTree>> inTpl;
output DAE.Exp outExp;
output Boolean cont;
output tuple<BackendDAE.Variables, AvlSetInt.Tree, Option<DAE.FunctionTree>> outTpl;
output tuple<BackendDAE.Variables, AvlSetInt.Tree, AvlSetPath.Tree, Option<DAE.FunctionTree>> outTpl;
algorithm
(outExp, cont, outTpl) := matchcontinue (inExp, inTpl)
local
Expand All @@ -2632,9 +2633,10 @@ algorithm
list<DAE.ComponentRef> crlst;
Option<DAE.FunctionTree> ofunctionTree;
DAE.FunctionTree functionTree;
tuple<BackendDAE.Variables, AvlSetInt.Tree, Option<DAE.FunctionTree>> tpl;
tuple<BackendDAE.Variables, AvlSetInt.Tree, AvlSetPath.Tree, Option<DAE.FunctionTree>> tpl;
Integer diffindx;
list<DAE.Subscript> subs;
AvlSetPath.Tree visitedPaths;

case (DAE.LBINARY(), tpl)
then (inExp, false, tpl);
Expand All @@ -2650,15 +2652,15 @@ algorithm
case (DAE.RANGE(), tpl)
then (inExp, false, tpl);

case (DAE.ASUB(exp=DAE.CREF(componentRef=cr), sub=explst), (vars, pa, ofunctionTree))
case (DAE.ASUB(exp=DAE.CREF(componentRef=cr), sub=explst), (vars, pa, visitedPaths, ofunctionTree))
algorithm
{e1 as DAE.RANGE()} := ExpressionSimplify.simplifyList(explst);
subs := list(DAE.INDEX(e) for e in extendRange(e1, vars));
crlst := list(ComponentReference.subscriptCref(cr, {s}) for s in subs);
(varslst, p) := BackendVariable.getVarLst(crlst, vars);
pa := incidenceRowExp1(varslst, p, pa, 0);
then
(inExp, false, (vars, pa, ofunctionTree));
(inExp, false, (vars, pa, visitedPaths, ofunctionTree));

case (DAE.ASUB(exp=e1, sub={DAE.ICONST(i)}), tpl) equation
e1 = Expression.nthArrayExp(e1, i);
Expand All @@ -2674,30 +2676,30 @@ algorithm
then (inExp, false, tpl);

// cref and $START.cref
case (DAE.CREF(componentRef=cr), (vars, pa, ofunctionTree)) equation
case (DAE.CREF(componentRef=cr), (vars, pa, visitedPaths, ofunctionTree)) equation
(varslst, p) = BackendVariable.getVar(cr, vars);
(_, p2) = BackendVariable.getVar(ComponentReference.crefPrefixStart(cr), vars);

pa = incidenceRowExp1(varslst, p, pa, 0);
pa = incidenceRowExp1(varslst, p2, pa, 0);
then (inExp, true, (vars, pa, ofunctionTree));
then (inExp, true, (vars, pa, visitedPaths, ofunctionTree));

// only cref
case (DAE.CREF(componentRef=cr), (vars, pa, ofunctionTree)) equation
case (DAE.CREF(componentRef=cr), (vars, pa, visitedPaths, ofunctionTree)) equation
(varslst, p) = BackendVariable.getVar(cr, vars);
pa = incidenceRowExp1(varslst, p, pa, 0);
then (inExp, true, (vars, pa, ofunctionTree));
then (inExp, true, (vars, pa, visitedPaths, ofunctionTree));

case (DAE.CALL(path=Absyn.IDENT(name="der"), expLst={DAE.CREF(componentRef=cr)}), (vars, pa, ofunctionTree)) equation
case (DAE.CALL(path=Absyn.IDENT(name="der"), expLst={DAE.CREF(componentRef=cr)}), (vars, pa, visitedPaths, ofunctionTree)) equation
(varslst, p) = BackendVariable.getVar(cr, vars);
pa = incidenceRowExp1(varslst, p, pa, 1);
then (inExp, false,(vars, pa, ofunctionTree));
then (inExp, false,(vars, pa, visitedPaths, ofunctionTree));

/* higher derivative, is only present during index reduction */
case (DAE.CALL(path=Absyn.IDENT(name="der"), expLst={DAE.CREF(componentRef=cr), DAE.ICONST(diffindx)}), (vars, pa, ofunctionTree)) equation
case (DAE.CALL(path=Absyn.IDENT(name="der"), expLst={DAE.CREF(componentRef=cr), DAE.ICONST(diffindx)}), (vars, pa, visitedPaths, ofunctionTree)) equation
(varslst, p) = BackendVariable.getVar(cr, vars);
pa = incidenceRowExp1(varslst, p, pa, diffindx);
then (inExp, false,(vars, pa, ofunctionTree));
then (inExp, false,(vars, pa, visitedPaths, ofunctionTree));

/* pre(v) is considered a known variable */
case (DAE.CALL(path=Absyn.IDENT(name="pre")), tpl)
Expand All @@ -2713,11 +2715,12 @@ algorithm
then (inExp, not b, tpl);

// use the inlined function to analyze the ocuring variables
case (DAE.CALL(), tpl as (_, _, SOME(functionTree))) equation
(e1,_) = Inline.forceInlineCall(inExp, {}, (SOME(functionTree), {DAE.NORM_INLINE(),DAE.DEFAULT_INLINE()}));
false = referenceEq(inExp,e1);
(_, tpl) = Expression.traverseExpTopDown(e1, traversingincidenceRowExpSolvableFinder, tpl);
then (inExp, false, tpl);
case (DAE.CALL(), (vars, pa, visitedPaths, ofunctionTree as SOME(functionTree))) guard not AvlSetPath.hasKey(visitedPaths, inExp.path)
algorithm
(e1,_) := Inline.forceInlineCall(inExp, {}, (SOME(functionTree), {DAE.NORM_INLINE(),DAE.DEFAULT_INLINE()}));
false := referenceEq(inExp,e1);
(_, tpl) := Expression.traverseExpTopDown(e1, traversingincidenceRowExpSolvableFinder, (vars, pa, AvlSetPath.add(visitedPaths, inExp.path), ofunctionTree));
then (inExp, false, tpl);

else (inExp, true, inTpl);
end matchcontinue;
Expand Down
47 changes: 42 additions & 5 deletions Compiler/FrontEnd/Expression.mo
Original file line number Diff line number Diff line change
Expand Up @@ -10678,16 +10678,20 @@ public function splitArray
"Splits an array into a list of elements."
input DAE.Exp inExp;
output list<DAE.Exp> outExp;
output Boolean didSplit;
algorithm
outExp := match(inExp)
(outExp,didSplit) := match(inExp)
local
list<DAE.Exp> expl;
list<list<DAE.Exp>> mat;
Integer istart, istop, istep;
Option<DAE.Exp> step;

case DAE.ARRAY(array = expl) then expl;
case DAE.MATRIX(matrix = mat) then List.flatten(mat);
else {inExp};

case DAE.ARRAY(array = expl) then (expl,true);
case DAE.MATRIX(matrix = mat) then (List.flatten(mat),true);
case DAE.RANGE(DAE.T_INTEGER(),DAE.ICONST(istart),step,DAE.ICONST(istop))
then (list(DAE.ICONST(i) for i in ExpressionSimplify.simplifyRange(istart,match step case NONE() then 1; case SOME(DAE.ICONST(istep)) then istep; end match,istop)),true);
else ({inExp},false);
end match;
end splitArray;

Expand Down Expand Up @@ -12693,6 +12697,39 @@ algorithm
outContinue := not outContainsCall;
end containsAnyCall_traverser;

public function containsCallTo
"Returns true if the given expression contains any function calls,
otherwise false."
input DAE.Exp inExp;
input Absyn.Path path;
output Boolean outContainsCall;
algorithm
(_, (_,outContainsCall)) := traverseExpTopDown(inExp, containsCallTo_traverser, (path,false));
end containsCallTo;

protected function containsCallTo_traverser
input DAE.Exp inExp;
input tuple<Absyn.Path,Boolean> inTpl;
output DAE.Exp outExp = inExp;
output Boolean outContinue = false;
output tuple<Absyn.Path,Boolean> outTpl = inTpl;
protected
Boolean containsCall;
Absyn.Path path;
algorithm
(path,containsCall) := outTpl;
if containsCall then
return;
end if;
outContinue := match inExp
case DAE.CALL() then Absyn.pathEqual(path,inExp.path);
else true;
end match;
if not outContinue then
outTpl := (path,false);
end if;
end containsCallTo_traverser;

public function rangeSize
"Tries to figure out the size of a range expression. Either return the size or
fails."
Expand Down
27 changes: 20 additions & 7 deletions Compiler/FrontEnd/ExpressionSimplify.mo
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ algorithm
list<DAE.Exp> eLst, subs;
Boolean hasRange;
Option<DAE.Exp> step;
// No ASUB...
case (_, e, {}) then e;

// ASUB(CAST(e)) -> CAST(liftArray(t), ASUB(e))
case (_, DAE.CAST(tp,e), _)
equation
Expand Down Expand Up @@ -3493,20 +3496,30 @@ protected function simplifyAsubSlicing
output DAE.Exp outAsubArray;
protected
list<list<DAE.Exp>> indices;
list<DAE.Exp> asubs;
list<DAE.Exp> asubs, es;
Integer sz;
DAE.Exp elem;
DAE.Type ty;
Boolean didSplit=false,b;
algorithm
// Expand the subscripts.
indices := list(Expression.splitArray(simplify1(e)) for e in inSubscripts);
indices := list(match () case () algorithm (es,b) := Expression.splitArray(simplify1(e)); didSplit := didSplit or b; then es; end match for e in inSubscripts);
// We don't want to loop forever... So keep track of if we actually expanded something
true := didSplit;
for is in indices loop
for i in is loop
// Make sure all asubs are scalar (were split by splitArray; no function calls or weird stuff left)
_ := match Expression.typeof(i)
case DAE.T_INTEGER() then ();
case DAE.T_BOOL() then ();
case DAE.T_ENUMERATION() then ();
else fail();
end match;
end for;
end for;
// Make asubs from all combinations of the subscript indices.
asubs := List.combinationMap1(indices, simplifyAsubSlicing2, inExp);
// Make sure one or more dimensions were sliced, i.e. we got more than one element.
elem :: _ :: _ := asubs;
// Make an array expression from the asub list.
ty := Expression.typeof(elem);
outAsubArray := Expression.makeScalarArray(asubs, ty);
outAsubArray := Expression.makeScalarArray(asubs, Types.unliftArray(Expression.typeof(inExp)));
end simplifyAsubSlicing;

protected function simplifyAsubSlicing2
Expand Down
60 changes: 32 additions & 28 deletions Compiler/FrontEnd/Inline.mo
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,33 @@ encapsulated package Inline
The entry point is the inlineCalls function, or inlineCallsInFunctions
"

public import Absyn;
public import BaseHashTable;
public import DAE;
public import HashTableCG;
public import SCode;
public import Util;

public type Functiontuple = tuple<Option<DAE.FunctionTree>,list<DAE.InlineType>>;

protected import Ceval;
protected import ClassInf;
protected import ComponentReference;
protected import Config;
protected import Debug;
protected import ElementSource;
protected import Error;
protected import Expression;
protected import ExpressionDump;
protected import ExpressionSimplify;
protected import Flags;
protected import Global;
protected import List;
protected import Types;
protected import VarTransform;
import Absyn;
import AvlSetPath;
import BaseHashTable;
import DAE;
import HashTableCG;
import SCode;
import Util;

type Functiontuple = tuple<Option<DAE.FunctionTree>,list<DAE.InlineType>>;

protected

import Ceval;
import ClassInf;
import ComponentReference;
import Config;
import Debug;
import ElementSource;
import Error;
import Expression;
import ExpressionDump;
import ExpressionSimplify;
import Flags;
import Global;
import List;
import Types;
import VarTransform;

public function inlineStartAttribute
input Option<DAE.VariableAttributes> inVariableAttributesOption;
Expand Down Expand Up @@ -713,7 +716,7 @@ algorithm
then (e_1,source,true);
case (e,fns,source)
equation
(e_1,_) = Expression.traverseExpBottomUp(e,function forceInlineCall(fns=fns),{});
(e_1,_) = Expression.traverseExpBottomUp(e,function forceInlineCall(fns=fns, visitedPaths=AvlSetPath.Tree.EMPTY()),{});
b = not referenceEq(e, e_1);
if b then
source = ElementSource.addSymbolicTransformation(source,DAE.OP_INLINE(DAE.PARTIAL_EQUATION(e),DAE.PARTIAL_EQUATION(e_1)));
Expand Down Expand Up @@ -952,6 +955,7 @@ public function forceInlineCall
input output DAE.Exp exp;
input output list<DAE.Statement> assrtLst;
input Functiontuple fns;
input AvlSetPath.Tree visitedPaths = AvlSetPath.EMPTY();
algorithm
(exp,assrtLst) := matchcontinue exp
local
Expand All @@ -971,7 +975,7 @@ algorithm
Boolean generateEvents,b;
Option<SCode.Comment> comment;

case (e1 as DAE.CALL(p,args,DAE.CALL_ATTR(inlineType=inlineType)))
case (e1 as DAE.CALL(p,args,DAE.CALL_ATTR(inlineType=inlineType))) guard not AvlSetPath.hasKey(visitedPaths, p)
equation
//print(printInlineTypeStr(inlineType));
false = Config.acceptMetaModelicaGrammar();
Expand All @@ -994,7 +998,7 @@ algorithm
newExp = if not generateEvents then Expression.addNoEventToRelationsAndConds(newExp) else newExp;
(newExp,(_,_,true)) = Expression.traverseExpBottomUp(newExp,replaceArgs,(argmap,checkcr,true));
// for inlinecalls in functions
(newExp1,assrtLst) = Expression.traverseExpBottomUp(newExp,function forceInlineCall(fns=fns),assrtLst);
(newExp1,assrtLst) = Expression.traverseExpBottomUp(newExp,function forceInlineCall(fns=fns,visitedPaths=AvlSetPath.add(visitedPaths, p)),assrtLst);
then (newExp1,assrtLst);

else (exp,assrtLst);
Expand Down Expand Up @@ -1597,7 +1601,7 @@ public function simplifyAndForceInlineEquationExp "
output DAE.ElementSource source;
algorithm
(exp,source) := ExpressionSimplify.simplifyAddSymbolicOperation(inExp,inSource);
(exp,source) := inlineEquationExp(exp,function forceInlineCall(fns=fns),source);
(exp,source) := inlineEquationExp(exp,function forceInlineCall(fns=fns, visitedPaths=AvlSetPath.Tree.EMPTY()),source);
end simplifyAndForceInlineEquationExp;

public function inlineEquationExp "
Expand Down
46 changes: 46 additions & 0 deletions Compiler/Util/AvlSetPath.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
* THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
* ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from OSMC, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/

encapsulated package AvlSetPath
import Absyn;
import BaseAvlSet;
extends BaseAvlSet;
redeclare type Key = Absyn.Path;
redeclare function extends keyStr
algorithm
outString := Absyn.pathString(inKey);
end keyStr;
redeclare function extends keyCompare
algorithm
outResult := Absyn.pathCompare(inKey1, inKey2);
end keyCompare;
annotation(__OpenModelica_Interface="frontend");
end AvlSetPath;
1 change: 1 addition & 0 deletions Compiler/boot/LoadCompilerSources.mos
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ if true then /* Suppress output */
// "Util";
"../Util/Array.mo",
"../Util/AvlSetCR.mo",
"../Util/AvlSetPath.mo",
"../Util/AvlSetString.mo",
"../Util/BaseAvlTree.mo",
"../Util/BaseAvlSet.mo",
Expand Down

0 comments on commit eb3f80f

Please sign in to comment.