@@ -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;
575577end 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+
577684protected 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;
16721779end 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
16741789end Patternm ;
0 commit comments