Skip to content

Commit 7b76dc3

Browse files
committed
- Added optimization that converts match-expressions (for-loop searching for matching pattern) to switch (jumps to the correct case at once)
- Works for records - Seems to be broken for strings so I disabled it (it uses string hashing, and DAE.SCONST is a bit weird at times so it needs more debugging) git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@7703 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
1 parent 365d36e commit 7b76dc3

File tree

15 files changed

+243
-94
lines changed

15 files changed

+243
-94
lines changed

Compiler/FrontEnd/DAE.mo

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,7 @@ uniontype Exp "Expressions
11391139
end METARECORDCALL;
11401140

11411141
record MATCHEXPRESSION
1142-
Absyn.MatchType matchType;
1142+
MatchType matchType;
11431143
list<Exp> inputs;
11441144
list<Element> localDecls;
11451145
list<MatchCase> cases;
@@ -1183,6 +1183,13 @@ public uniontype MatchCase
11831183
end CASE;
11841184
end MatchCase;
11851185

1186+
public uniontype MatchType
1187+
record MATCHCONTINUE end MATCHCONTINUE;
1188+
record MATCH
1189+
Option<tuple<Integer,ExpType,Integer>> switch "The index of the pattern to switch over, its type and an the value to divide string hashes with";
1190+
end MATCH;
1191+
end MatchType;
1192+
11861193
public uniontype Pattern "Patterns deconstruct expressions"
11871194
record PAT_WILD "_"
11881195
end PAT_WILD;

Compiler/FrontEnd/Expression.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3509,7 +3509,7 @@ algorithm
35093509
list<String> fieldNames;
35103510
DAE.InlineType inl;
35113511
list<DAE.MatchCase> cases;
3512-
Absyn.MatchType matchTy;
3512+
DAE.MatchType matchTy;
35133513

35143514
case ((e as DAE.ICONST(_)),rel,ext_arg)
35153515
equation

Compiler/FrontEnd/ExpressionDump.mo

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ algorithm
563563
Boolean b;
564564
list<DAE.Exp> aexpl;
565565
list<list<tuple<DAE.Exp,Boolean>>> lstes;
566-
Absyn.MatchType matchTy;
566+
DAE.MatchType matchTy;
567567
DAE.ExpType et;
568568
list<DAE.MatchCase> cases;
569569
DAE.Pattern pat;
@@ -893,7 +893,7 @@ algorithm
893893

894894
case (DAE.MATCHEXPRESSION(matchType=matchTy,inputs=es,cases=cases), _, _, _)
895895
equation
896-
s1 = Dump.printMatchType(matchTy);
896+
s1 = printMatchType(matchTy);
897897
s2 = printExp2Str(DAE.TUPLE(es), stringDelimiter, opcreffunc, opcallfunc);
898898
s3 = stringAppendList(Util.listMap(cases,printCase2Str));
899899
s = stringAppendList({s1,s2,"\n",s3," end ",s1});
@@ -917,6 +917,17 @@ algorithm
917917
end matchcontinue;
918918
end printExp2Str;
919919

920+
protected function printMatchType
921+
input DAE.MatchType ty;
922+
output String str;
923+
algorithm
924+
str := match ty
925+
case DAE.MATCHCONTINUE() then "matchcontinue";
926+
case DAE.MATCH(NONE()) then "match";
927+
case DAE.MATCH(SOME(_)) then "match /* switch */";
928+
end match;
929+
end printMatchType;
930+
920931
protected function printCase2Str
921932
"Prints a matchcase as string"
922933
input DAE.MatchCase matchCase;
@@ -1776,7 +1787,7 @@ algorithm
17761787
list<list<tuple<DAE.Exp, Boolean>>> lstes;
17771788
DAE.Exp ae1;
17781789
Boolean b;
1779-
Absyn.MatchType matchTy;
1790+
DAE.MatchType matchTy;
17801791
list<DAE.MatchCase> cases;
17811792
DAE.Pattern pat;
17821793

@@ -2100,13 +2111,13 @@ algorithm
21002111

21012112
case (DAE.MATCHEXPRESSION(matchType=matchTy,inputs=es,cases=cases), _)
21022113
equation
2103-
Print.printBuf(Dump.printMatchType(matchTy));
2114+
Print.printBuf(printMatchType(matchTy));
21042115
Print.printBuf(" (");
21052116
printList(es, printExp, ",");
21062117
Print.printBuf(") \n");
21072118
Print.printBuf(stringAppendList(Util.listMap(cases,printCase2Str)));
21082119
Print.printBuf(" end ");
2109-
Print.printBuf(Dump.printMatchType(matchTy));
2120+
Print.printBuf(printMatchType(matchTy));
21102121
then ();
21112122

21122123
case (DAE.BOX(e),_)

Compiler/FrontEnd/ExpressionSimplify.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ algorithm
346346
e = DAE.IFEXP(e, e1_1, e2_1);
347347
then simplify(e);
348348

349-
case DAE.MATCHEXPRESSION(matchType=Absyn.MATCH(), inputs={e}, localDecls={}, cases={
349+
case DAE.MATCHEXPRESSION(matchType=DAE.MATCH(switch=_), inputs={e}, localDecls={}, cases={
350350
DAE.CASE(patterns={DAE.PAT_CONSTANT(exp=DAE.BCONST(b1))},localDecls={},body={},result=SOME(e1)),
351351
DAE.CASE(patterns={DAE.PAT_WILD()},localDecls={},body={},result=SOME(e2))
352352
})

Compiler/FrontEnd/Patternm.mo

Lines changed: 117 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ algorithm
545545
String str;
546546
DAE.Exp exp;
547547
HashTableStringToPath.HashTable ht;
548+
DAE.MatchType elabMatchTy;
548549
case (cache,env,Absyn.MATCHEXP(matchTy=matchTy,inputExp=inExp,localDecls=decls,cases=cases),impl,st,performVectorization,pre,info,numError)
549550
equation
550551
(cache,SOME((env,DAE.DAE(matchDecls)))) = addLocalDecls(cache,env,decls,Env.matchScopeName,impl,info);
@@ -559,11 +560,12 @@ algorithm
559560
// Do DCE before converting mc to m
560561
matchTy = optimizeContinueToMatch(matchTy,elabCases,info);
561562
elabCases = optimizeContinueJumps(matchTy, elabCases);
562-
ht = getUsedLocalCrefs(RTOpts.debugFlag("patternmSkipFilterUnusedAsBindings"),DAE.MATCHEXPRESSION(matchTy,elabExps,matchDecls,elabCases,et));
563+
ht = getUsedLocalCrefs(RTOpts.debugFlag("patternmSkipFilterUnusedAsBindings"),DAE.MATCHEXPRESSION(DAE.MATCHCONTINUE(),elabExps,matchDecls,elabCases,et));
563564
(matchDecls,ht) = filterUnusedDecls(matchDecls,ht,{},HashTableStringToPath.emptyHashTable());
564565
elabCases = filterUnusedAsBindings(elabCases,ht);
565566
(elabExps,elabCases) = filterUnusedPatterns(elabExps,elabCases) "filterUnusedPatterns() Then again to filter out the last parts.";
566-
exp = DAE.MATCHEXPRESSION(matchTy,elabExps,matchDecls,elabCases,et);
567+
elabMatchTy = optimizeMatchToSwitch(matchTy,elabCases,info);
568+
exp = DAE.MATCHEXPRESSION(elabMatchTy,elabExps,matchDecls,elabCases,et);
567569
then (cache,exp,prop,st);
568570
else
569571
equation
@@ -574,6 +576,111 @@ algorithm
574576
end matchcontinue;
575577
end elabMatchExpression;
576578

579+
protected function optimizeMatchToSwitch
580+
"match str case 'str1' ... case 'str2' case 'str3' => switch hash(str)...
581+
match ut case UT1 ... case UT2 ... case UT3 => switch valueConstructor(ut)...
582+
Works if all values are unique. Also works if there is one 'default' case at the end of the list.
583+
584+
NOT YET WORKING CODE! Code generation does not know about this.
585+
We need DAE.MATCH/CONTINUE/SWITCH instead of Absyn.MATCH/CONTINUE
586+
"
587+
input Absyn.MatchType matchTy;
588+
input list<DAE.MatchCase> cases;
589+
input Absyn.Info info;
590+
output DAE.MatchType outType;
591+
algorithm
592+
outType := matchcontinue (matchTy,cases,info)
593+
local
594+
tuple<Integer,DAE.ExpType,Integer> tpl;
595+
list<list<DAE.Pattern>> patternMatrix;
596+
String str;
597+
case (Absyn.MATCHCONTINUE(),_,_) then DAE.MATCHCONTINUE();
598+
case (_,cases,_)
599+
equation
600+
true = listLength(cases) > 2;
601+
patternMatrix = Util.transposeList(Util.listMap(cases,getCasePatterns));
602+
tpl = findPatternToConvertToSwitch(patternMatrix,0,info);
603+
Error.assertionOrAddSourceMessage(not RTOpts.debugFlag("patternmAllInfo"),Error.MATCH_TO_SWITCH_OPTIMIZATION, {}, info);
604+
then DAE.MATCH(SOME(tpl));
605+
else DAE.MATCH(NONE());
606+
end matchcontinue;
607+
end optimizeMatchToSwitch;
608+
609+
protected function findPatternToConvertToSwitch
610+
input list<list<DAE.Pattern>> patternMatrix;
611+
input Integer index;
612+
input Absyn.Info info;
613+
output tuple<Integer,DAE.ExpType,Integer> tpl;
614+
algorithm
615+
tpl := matchcontinue (patternMatrix,index,info)
616+
local
617+
list<DAE.Pattern> pats;
618+
String str;
619+
DAE.ExpType ty;
620+
Integer extraarg;
621+
case (pats::patternMatrix,index,info)
622+
equation
623+
(ty,extraarg) = findPatternToConvertToSwitch2(pats, {}, DAE.ET_OTHER());
624+
then ((index,ty,extraarg));
625+
case (_::patternMatrix,index,info)
626+
then findPatternToConvertToSwitch(patternMatrix,index+1,info);
627+
end matchcontinue;
628+
end findPatternToConvertToSwitch;
629+
630+
protected function findPatternToConvertToSwitch2
631+
input list<DAE.Pattern> pats;
632+
input list<Integer> ixs;
633+
input DAE.ExpType ty;
634+
output DAE.ExpType outTy;
635+
output Integer extraarg;
636+
algorithm
637+
(outTy,extraarg) := match (pats,ixs,ty)
638+
local
639+
Integer ix;
640+
String str;
641+
// Always jump to the last pattern as a default case? Seems reasonable, but requires knowledge about the other patterns...
642+
/* Disable strings...
643+
case ({},ixs,DAE.ET_STRING())
644+
equation
645+
// Should probably start at realCeil(log2(listLength(ixs))), but we don't have log2 in RML :)
646+
ix = findMinMod(ixs,1);
647+
then (DAE.ET_STRING(),ix);
648+
case (DAE.PAT_CONSTANT(exp=DAE.SCONST(str))::pats,ixs,_)
649+
equation
650+
ix = stringHashDjb2(str);
651+
false = listMember(ix,ixs);
652+
(ty,extraarg) = findPatternToConvertToSwitch2(pats,ix::ixs,DAE.ET_STRING());
653+
then (ty,extraarg);
654+
*/
655+
case ({},_,DAE.ET_METATYPE()) then (ty,0);
656+
case (DAE.PAT_CALL(index=ix)::pats,ixs,_)
657+
equation
658+
false = listMember(ix,ixs);
659+
(ty,extraarg) = findPatternToConvertToSwitch2(pats,ix::ixs,DAE.ET_METATYPE());
660+
then (ty,extraarg);
661+
end match;
662+
end findPatternToConvertToSwitch2;
663+
664+
protected function findMinMod
665+
input list<Integer> ixs;
666+
input Integer mod;
667+
output Integer outMod;
668+
algorithm
669+
outMod := matchcontinue (ixs,mod)
670+
case (ixs,mod)
671+
equation
672+
ixs = Util.listMap1(ixs, intMod, mod);
673+
ixs = Util.sort(ixs, intLt);
674+
(_,{}) = Util.splitUniqueOnBool(ixs, intEq);
675+
// This mod was high enough that all values were distinct
676+
then mod;
677+
else
678+
equation
679+
true = mod < 65536;
680+
then findMinMod(ixs,mod*2);
681+
end matchcontinue;
682+
end findMinMod;
683+
577684
protected function filterUnusedPatterns
578685
"case (1,_,_) then ...; case (2,_,_) then ...; =>"
579686
input list<DAE.Exp> inputs "We can only remove inputs that are free from side-effects";
@@ -1670,5 +1777,13 @@ algorithm
16701777
then DAE.CASE(pats,localDecls,body,result,jump,info);
16711778
end match;
16721779
end setCasePatterns;
1780+
1781+
public function getValueCtor
1782+
"Get the constructor index of a uniontype record based on its index in the uniontype"
1783+
input Integer ix;
1784+
output Integer ctor;
1785+
algorithm
1786+
ctor := ix+3;
1787+
end getValueCtor;
16731788

16741789
end Patternm;

Compiler/FrontEnd/Types.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3985,7 +3985,7 @@ algorithm
39853985
list<DAE.ExpType> expTypes;
39863986
DAE.ExpType et,ety1;
39873987
list<DAE.MatchCase> cases;
3988-
Absyn.MatchType matchTy;
3988+
DAE.MatchType matchTy;
39893989
list<DAE.Element> localDecls;
39903990

39913991
/* Array expressions: expression dimension [dim1], expected dimension [dim2] */

0 commit comments

Comments
 (0)