]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java
(refs #7250) Merging master, minor CHR bugfixes
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / ssa / SSABlock.java
index c9f33ec50c7727e8a9c789858de926bfce31a282..ba9d62d27ce730bffc2b99772321406736125e07 100644 (file)
@@ -4,6 +4,7 @@ import java.util.ArrayList;
 
 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
 import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.constants.NoRepConstant;
 import org.simantics.scl.compiler.constants.SCLConstant;
 import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
 import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
@@ -21,6 +22,7 @@ import org.simantics.scl.compiler.internal.codegen.utils.Printable;
 import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;
 import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;
 import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
+import org.simantics.scl.compiler.internal.codegen.utils.SSAUtils;
 import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;
 import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;
 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
@@ -281,27 +283,42 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
             context.markModified("improve-parameters");
     }
 
+    private static Constant getOnlyPossibleValue(Type type) {
+        type = Types.canonical(type);
+        if(type == Types.UNIT)
+            return NoRepConstant.UNIT;
+        else if(type == Types.PUNIT)
+            return NoRepConstant.PUNIT;
+        return null; 
+    }
+    
     private boolean tryToImproveParameter(int position) {
         BoundVar parameter = parameters[position];
-        Val constant = null;
-        ValRef constantRef = null;
-        for(ContRef ref = getOccurrence(); ref != null; ref = ref.getNext()) {
-            Jump jump = (Jump)ref.getParent();
-            ValRef valRef = jump.getParameters()[position];
-            Val val = valRef.getBinding();
-            if(val == parameter)
-                continue;
-            if(constant == null) {
-                constant = val;
-                constantRef = valRef;
-                continue;
+        Constant onlyPossibleValue = getOnlyPossibleValue(parameter.getType());
+        if(onlyPossibleValue == null) {
+            Val constant = null;
+            ValRef constantRef = null;
+            for(ContRef ref = getOccurrence(); ref != null; ref = ref.getNext()) {
+                Jump jump = (Jump)ref.getParent();
+                ValRef valRef = jump.getParameters()[position];
+                Val val = valRef.getBinding();
+                if(val == parameter)
+                    continue;
+                if(constant == null) {
+                    constant = val;
+                    constantRef = valRef;
+                    continue;
+                }
+                if(val != constant)
+                    return false;
             }
-            if(val != constant)
-                return false;
+            if(constant == null)
+                return false; // This is a strange case, because we cannot get the parameter anywhere
+            parameter.replaceBy(constantRef);
+        }
+        else {
+            parameter.replaceBy(onlyPossibleValue);
         }
-        if(constant == null)
-            return false; // This is a strange case, because we cannot get the parameter anywhere
-        parameter.replaceBy(constantRef);
         
         for(ContRef ref = getOccurrence(); ref != null; ref = ref.getNext()) {
             Jump jump = (Jump)ref.getParent();
@@ -331,32 +348,72 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
         return result;
     }
     
+    /*
+     * This method assumes that the exit of the block is Jump.
+     */
     private boolean optimizeTailSelfCall() {
-        Jump jump = (Jump)exit;
-        if(jump.getTarget().getBinding() != parent.returnCont)
-            return false;
-        if(jump.getParameters().length != 1)
-            return false;
+        // The last statement of the block is LetApply that calls the parent function with right number of parameters 
         if(lastStatement == null || !(lastStatement instanceof LetApply))
             return false;
         LetApply apply = (LetApply)lastStatement;
-        SSABlock initialBlock = parent.firstBlock;
-        if(initialBlock.parameters.length != apply.getParameters().length)
-            return false;
         Val function = apply.getFunction().getBinding();
         if(function != parent.target)
             return false;
+        SSABlock initialBlock = parent.firstBlock;
+        if(initialBlock.parameters.length != apply.getParameters().length)
+            return false;
+
+        // The jump is a return (with one parameter)
+        // The parameter of the jump is the target of LetApply
+        Jump jump = (Jump)exit;
+        Cont targetCont = jump.getTarget().getBinding();
+        if(targetCont != parent.returnCont) {
+            SSABlock targetBlock = (SSABlock)targetCont;
+            if(targetBlock.firstStatement != null)
+                return false;
+            if(!(targetBlock.exit instanceof Jump))
+                return false;
+            Jump targetJump = (Jump)targetBlock.exit;
+            if(targetJump.getTarget().getBinding() != parent.returnCont)
+                return false;
+            if(targetJump.getParameters().length != 1)
+                return false;
+            
+            BoundVar applyTarget = apply.getTarget();
+            ValRef targetJumpParameter = targetJump.getParameter(0);
+            isSameParam: if(!SSAUtils.representSameValue(applyTarget, targetJumpParameter)) {
+                BoundVar[] targetBlockParameters = targetBlock.getParameters();
+                for(int i=0;i<targetBlockParameters.length;++i) {
+                    if(targetJumpParameter.getBinding() == targetBlockParameters[i]
+                            && jump.getParameter(i).getBinding() == applyTarget)
+                        break isSameParam;
+                }
+                return false;
+            }
+        }
+        else {
+            if(jump.getParameters().length != 1)
+                return false;
+            if(!SSAUtils.representSameValue(apply.getTarget(), jump.getParameter(0)))
+                return false;
+        }
         
         // Do modifications
         apply.detach();
         apply.getFunction().remove();
         jump.getTarget().remove();
         jump.setTarget(initialBlock.createOccurrence());
+        for(ValRef parameter : jump.getParameters())
+            parameter.remove();
         jump.setParameters(apply.getParameters());
         
         return true;
     }
 
+    /**
+     * Assumes that this block has no statements, the block is not the first block
+     * and the exit of the block is Jump.
+     */
     private boolean etaBlock(SSASimplificationContext context) {
         Jump jump = (Jump)exit;
         if(parameters.length != jump.getParameters().length)
@@ -436,7 +493,7 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
         block.detach();
         
         jump.destroy();
-        setExit(block.exit);       
+        setExit(block.exit);
         
         /*System.out.println(">> AFTER INLINE >>");
         System.out.println(getParent());
@@ -473,7 +530,7 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
 
     public void markGenerateOnFly() {
         for(SSAStatement stat = firstStatement; stat != null; stat = stat.next)
-            stat.markGenerateOnFly();        
+            stat.markGenerateOnFly();
     }
     
     public SSABlock copy(CopyContext context) {