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