--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.optimization;\r
+\r
+import org.simantics.scl.compiler.common.names.Name;\r
+import org.simantics.scl.compiler.constants.SCLConstant;\r
+import org.simantics.scl.compiler.internal.codegen.analysis.StatementBrowser;\r
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
+import org.simantics.scl.compiler.internal.codegen.references.Val;\r
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAStatement;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;\r
+import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
+\r
+public enum FoldlBuildFusion implements Optimization {\r
+ INSTANCE;\r
+\r
+ private static final Name BUILD = Name.create("Prelude", "build");\r
+ \r
+ private static class Analysis extends StatementBrowser {\r
+ \r
+ @Override\r
+ protected void unanalyzedBrowse() {\r
+ //System.out.println("- unanalyzedBrowse");\r
+ stopBrowse();\r
+ }\r
+ \r
+ @Override\r
+ protected void handleLoop(SSABlock block,\r
+ SSAStatement recursiveStatement) {\r
+ //System.out.println("- loop");\r
+ stopBrowse();\r
+ }\r
+ \r
+ @Override\r
+ protected void visitStatement(SSAStatement statement) {\r
+ if(statement instanceof LetApply) {\r
+ LetApply apply = (LetApply)statement;\r
+ if(apply.hasEffect()) {\r
+ //System.out.println("- effectful statement between");\r
+ stopBrowse();\r
+ }\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void inline(SSASimplificationContext context, LetApply foldlApplication) { \r
+ ValRef[] foldlParameters = foldlApplication.getParameters();\r
+ if(foldlParameters.length != 3) // TODO case parameters.length > 3\r
+ return;\r
+ Val list = foldlParameters[2].getBinding();\r
+ if(!(list instanceof BoundVar))\r
+ return;\r
+ if(list.hasMoreThanOneOccurences())\r
+ return;\r
+ BoundVar listVar = (BoundVar)list;\r
+ if(!(listVar.getParent() instanceof LetApply))\r
+ return;\r
+ LetApply buildApplication = (LetApply)listVar.getParent();\r
+ \r
+ { // Check that buildApplication.getFunction() is Prelude.build\r
+ if(buildApplication.getParameters().length != 1)\r
+ return;\r
+ Val buildFunction = buildApplication.getFunction().getBinding();\r
+ if(!(buildFunction instanceof SCLConstant))\r
+ return;\r
+ if(((SCLConstant)buildFunction).getName() != BUILD)\r
+ return;\r
+ }\r
+\r
+ if(buildApplication.hasEffect() && foldlApplication.hasEffect())\r
+ return;\r
+ \r
+ Analysis analysis = new Analysis();\r
+ analysis.browseBetween(buildApplication, foldlApplication);\r
+ if(analysis.isStopped())\r
+ return;\r
+ \r
+ /*PrintingContext cx = new PrintingContext();\r
+ cx.append("listDef: ");\r
+ listDef.toString(cx);\r
+ cx.append("apply: ");\r
+ apply.toString(cx);*/\r
+ \r
+ foldlApplication.setParameters(new ValRef[] {foldlParameters[1], foldlParameters[0]});\r
+ foldlParameters[2].remove();\r
+ ValRef foldlFunctionRef = foldlApplication.getFunction();\r
+ foldlApplication.setFunction(buildApplication.getParameters()[0].createOccurrence(\r
+ foldlFunctionRef.getTypeParameters()[0], foldlFunctionRef.getTypeParameters()[2]));\r
+ foldlFunctionRef.remove(); \r
+ buildApplication.remove();\r
+ \r
+ /*cx.append("transformed apply: ");\r
+ apply.toString(cx);\r
+ System.out.println(cx.toString());*/\r
+ \r
+ context.markModified("foldl/build");\r
+ }\r
+}\r