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;
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;
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();
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)
block.detach();
jump.destroy();
- setExit(block.exit);
+ setExit(block.exit);
/*System.out.println(">> AFTER INLINE >>");
System.out.println(getParent());