]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAFunction.java
(refs #7250) Merging master, minor CHR bugfixes
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / ssa / SSAFunction.java
index 68dd82f15f4bb1c76d5b68c07f58cfc501e3f66c..b9e8bfbb398e0803977e305533259eb0eb6d4982 100644 (file)
@@ -5,6 +5,7 @@ import java.util.Arrays;
 
 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;
@@ -173,12 +174,88 @@ public final class SSAFunction extends SSAClosure {
     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))
@@ -202,7 +279,7 @@ public final class SSAFunction extends SSAClosure {
         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));
@@ -282,6 +359,8 @@ public final class SSAFunction extends SSAClosure {
     }
 
     public void mergeBlocks(SSAFunction function) {
+        if(this == function)
+            throw new InternalCompilerError();
         SSABlock block = function.firstBlock;
         while(block != null) {
             SSABlock next = block.next;