import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.constants.NoRepConstant;
import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
import org.simantics.scl.compiler.internal.codegen.continuations.ReturnCont;
// Add valid variables and continuations
context.validContinuations.add(returnCont);
- for(SSABlock block = firstBlock; block != null; block = block.next) {
+ for(SSABlock block = firstBlock; block != null; block = block.next) {
context.validContinuations.add(block);
for(BoundVar parameter : block.parameters)
context.validBoundVariables.add(parameter);
public void simplify(SSASimplificationContext context) {
for(SSABlock block = firstBlock; block != null; block = block.next)
block.simplify(context);
- if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement &&
- firstBlock.firstStatement instanceof LetFunctions) {
- simplifySingleLambda(context);
+ if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement) {
+ if(firstBlock.firstStatement instanceof LetApply)
+ simplifySingleApply(context);
+ else if(firstBlock.firstStatement instanceof LetFunctions)
+ simplifySingleLambda(context);
}
}
+
+ /**
+ * Simplifies the following kind of function definition
+ * \x -> f x
+ * to
+ * f
+ */
+ private void simplifySingleApply(SSASimplificationContext context) {
+ if(!(parent instanceof LetFunctions) || parent.getFirstClosure().next != null)
+ return;
+ LetApply apply = (LetApply)firstBlock.firstStatement;
+ if(!(firstBlock.exit instanceof Jump))
+ return;
+ Jump exit = (Jump)firstBlock.exit;
+ if(exit.getTarget().getBinding() != returnCont)
+ return;
+ if(exit.getParameter(0).getBinding() != apply.getTarget())
+ return;
+ BoundVar[] functionParameters = getParameters();
+ ValRef[] applyParameters = apply.getParameters();
+ if(functionParameters.length > applyParameters.length)
+ return;
+ int extraApplyParameters = applyParameters.length - functionParameters.length;
+ for(int i=0;i<functionParameters.length;++i)
+ if(!representSameValues(functionParameters[i], applyParameters[extraApplyParameters+i]))
+ return;
+ for(int i=0;i<extraApplyParameters;++i) {
+ Val b = applyParameters[i].getBinding();
+ if(b instanceof BoundVar) {
+ BoundVar bv = (BoundVar)b;
+ if(bv == target || bv.getParent() == firstBlock)
+ return;
+ }
+ }
+ if(!(target instanceof BoundVar))
+ return;
+
+ // Transform
+
+ LetFunctions binder = (LetFunctions)parent;
+ SSAFunction parentFunction = binder.getParentFunction();
+ if(extraApplyParameters > 0) {
+ //System.out.println("-------------------------------------------------------------");
+ //System.out.println(parentFunction);
+ //System.out.println("-------------------------------------------------------------");
+ apply.setTarget((BoundVar)target);
+ apply.setParameters(Arrays.copyOf(applyParameters, extraApplyParameters));
+ apply.insertBefore(binder);
+ binder.detach();
+ //System.out.println(parentFunction);
+ //System.out.println("-------------------------------------------------------------");
+ }
+ else {
+ binder.detach();
+ ((BoundVar)target).replaceBy(apply.getFunction());
+ }
+ context.markModified("SSAFunction.eta-reduce");
+ }
+
+ private boolean representSameValues(BoundVar boundVar, ValRef valRef) {
+ Val val = valRef.getBinding();
+ if(val == boundVar && valRef.getTypeParameters().length == 0)
+ return true;
+ if(val instanceof NoRepConstant && Types.equals(valRef.getType(), boundVar.getType()))
+ return true;
+ return false;
+ }
+
+ /**
+ * Simplifies the following kind of function definition
+ * \x -> \y -> e
+ * to
+ * \x y -> e
+ */
private void simplifySingleLambda(SSASimplificationContext context) {
LetFunctions letF = (LetFunctions)firstBlock.firstStatement;
if(!(letF.getFirstClosure() instanceof SSAFunction))
lastBlock = f.lastBlock;
firstBlock.firstStatement = firstBlock.lastStatement = null;
- setReturnCont(f.getReturnCont());
+ setReturnCont(f.getReturnCont());
effect = f.effect;
BoundVar[] newParameters = BoundVar.copy(f.firstBlock.parameters);
firstBlock.setParameters(BoundVar.concat(getParameters(), newParameters));
}
public void mergeBlocks(SSAFunction function) {
+ if(this == function)
+ throw new InternalCompilerError();
SSABlock block = function.firstBlock;
while(block != null) {
SSABlock next = block.next;
block.forValRefs(visitor);
}
+ @Override
+ public void cleanup() {
+ for(SSABlock block = firstBlock; block != null; block = block.next)
+ block.cleanup();
+ }
}