X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fconstants%2FSCLConstant.java;h=0fe09df8b8d5845400550d5ff3638a9ed8fca46c;hp=ce39a6780e4ba8920360ca15a241d6ad543f54fa;hb=91682baa9a8252390f09b80fd724f47e5957b234;hpb=4bf8562ab7cbb3747f9c5844a07469291d43e905 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java index ce39a6780..0fe09df8b 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java @@ -1,376 +1,383 @@ -package org.simantics.scl.compiler.constants; - -import java.util.ArrayList; -import java.util.Arrays; - -import org.simantics.scl.compiler.common.names.Name; -import org.simantics.scl.compiler.common.names.Named; -import org.simantics.scl.compiler.internal.codegen.optimization.Optimization; -import org.simantics.scl.compiler.internal.codegen.optimization.OptimizationMap; -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.SSAFunction; -import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump; -import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply; -import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions; -import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext; -import org.simantics.scl.compiler.types.TVar; -import org.simantics.scl.compiler.types.Type; -import org.simantics.scl.compiler.types.Types; - -public class SCLConstant extends DelegateConstant implements Named { - - public Name name; // Needed only for debugging - public SSAFunction definition; - public SSAFunction inlinableDefinition; - public int inlineArity = Integer.MAX_VALUE; - public int inlinePhaseMask = 0xffffffff; - public boolean isPrivate = false; - - public SCLConstant(Name name, Type type) { - super(type); - this.name = name; - } - - public void setInlineArity(int inlineArity, int inlinePhaseMask) { - this.inlineArity = inlineArity; - this.inlinePhaseMask = inlinePhaseMask; - //System.out.println(name + " " + inlineArity + " " + inlinePhaseMask); - } - - public void setPrivate(boolean isPrivate) { - this.isPrivate = isPrivate; - } - - public void setDefinition(SSAFunction definition) { - this.definition = definition; - } - - public SSAFunction getDefinition() { - return definition; - } - - @Override - public void inline(SSASimplificationContext context, LetApply apply) { - if(inlineTailCallToSelf(context, apply)) { - return; - } - /*if(tryBetaReduce(context, apply)) { - return; - }*/ - if(basicInline(context, apply)) { - return; - } - trySpecialize(context, apply); - - Optimization opt = OptimizationMap.OPTIMIZATIONS.get(name); - if(opt != null) - opt.inline(context, apply); - } - - static int inlineCount = 0; - - private boolean canInlineInPhase(int phase) { - return ((inlinePhaseMask >> phase)&1) == 1; - } - - private boolean basicInline(SSASimplificationContext context, LetApply apply) { - if(!canInlineInPhase(context.getPhase())) { - //System.out.println("Cannot optimize " + name + " in phase " + context.getPhase()); - return false; - } - ValRef functionRef = apply.getFunction(); - ValRef[] parameters = apply.getParameters(); - SSAFunction def = inlinableDefinition == null ? definition : inlinableDefinition; - if(parameters.length < inlineArity && - (!isPrivate - || parameters.length != def.getArity() - || hasMoreThanOneOccurences())) - return false; - - //if(def.getArity() == 0) - // return false; // FIXME - - //System.out.println("basicInline: " + apply); - //System.out.println("def: " + def); - - if(isPrivate && !hasMoreThanOneOccurences()) - context.removeConstant(name); - else - def = (SSAFunction)def.copy(); - - if(parameters.length >= def.getArity()) { - if(parameters.length != def.getArity()) - apply.split(def.getArity()); - apply.inline(def); - context.markModified("SCLConstant.beta-constant " + getName()); - } - else /*if(parameters.length < def.getArity())*/ { - def.applyTypes(functionRef.getTypeParameters()); - def.apply(parameters); - - def.setTarget(apply.getTarget()); - new LetFunctions(def).insertBefore(apply); - - apply.remove(); - context.markModified("SCLConstant.partial-beta-constant " + getName()); - } - - /*Name newName = Name.create(name.module, - name.name + "_S" + (++inlineCount)); - SCLConstant newConstant = new SCLConstant(newName, type); - newConstant.setPrivate(true); - newConstant.setDefinition(definition.copy()); */ - /*System.out.println("*** 1 *************************************"); - System.out.println(definition); - System.out.println("*** 2 *************************************"); - System.out.println(newConstant.definition); - - function.remove(); - apply.setFunction(newConstant.createOccurrence(function.getTypeParameters())); - - context.addConstant(newConstant); - - context.markModified(); - - newConstant.trySpecialize(context, apply); - */ - - return true; - } - - private boolean inlineTailCallToSelf(SSASimplificationContext context, LetApply apply) { - SSAFunction thisFunction = apply.getParent().getParent(); - if(thisFunction != definition) - return false; - ValRef ref = apply.getTarget().getOccurrence(); - if(ref == null || ref.getNext() != null) - return false; - if(!(ref.getParent() instanceof Jump)) - return false; - Jump jump = (Jump)ref.getParent(); - if(jump.getParameters().length != 1) - return false; - if(jump.getTarget().getBinding() != thisFunction.getReturnCont()) - return false; - if(apply.getParameters().length != thisFunction.getArity()) - return false; - - jump.getTarget().remove(); - jump.setTarget(thisFunction.getFirstBlock().createOccurrence()); - jump.setParameters(apply.getParameters()); - - apply.getFunction().remove(); - apply.detach(); - - context.markModified("SCLConstant.simplify-tail-call"); - - return true; - } - - private void trySpecialize(SSASimplificationContext context, LetApply apply) { - if(!isPrivate) - return; - if(hasMoreThanOneOccurences()) - return; - if(apply.getParent().getParent() == definition) - return; - - // Specialization of type parameters - { - ValRef functionRef = apply.getFunction(); - Type[] pValues = functionRef.getTypeParameters(); - boolean hasComplexTypes = false; - for(Type type : pValues) - if(!(Types.canonical(type) instanceof TVar)) { - hasComplexTypes = true; - break; - } - if(hasComplexTypes) { - /*PrintingContext pc = new PrintingContext(); - pc.append(">> BEFORE >>\n"); - definition.toString(pc);*/ - - TVar[] pVars = definition.getTypeParameters(); - TVar[] pVarsTail; - if(pVars.length == pValues.length) - pVarsTail = TVar.EMPTY_ARRAY; - else { - pVarsTail = Arrays.copyOfRange(pVars, pValues.length, pVars.length); - pVars = Arrays.copyOf(pVars, pValues.length); - } - type = Types.instantiate(type, pValues); - /*pc.append("REPLACE: "); - pc.append(pVars); - pc.append(" -> "); - pc.append(pValues); - pc.append('\n');*/ - definition.replace(pVars, pValues); - TVar[] newParameters = Types.freeVarsArray(pValues); - type = Types.forAll(newParameters, type); - functionRef.setTypeParameters(newParameters); - definition.setTypeParameters(Types.concat(newParameters, pVarsTail)); - - /*pc.append(">> AFTER >>\n"); - definition.toString(pc); - System.out.println(pc);*/ - context.markModified("SCLConstant.specialize-types"); - } - } - - if(!definition.getFirstBlock().hasNoOccurences()) - // TODO We can flex this requirement if all jumps to the first block - // give same values to the first block - return; - - // Specialization of parameters - ValRef[] parameters = apply.getParameters(); - ValRef[] specialization = null; - int arity = Math.min(parameters.length, definition.getArity()); - for(int i=0;i newParameters = new ArrayList(parameters.length); - for(int i=0;i " + constant.getBinding()); - System.out.println("replace: " + this); - System.out.println("of type: " + this.getType()); - System.out.println("by: " + binding); - System.out.println("of type: " + binding.getType()); - System.out.println("parameters: " + Types.toString(definition.getTypeParameters())); - System.out.println("parameters2: " + Types.toString(constant.getTypeParameters())); - System.out.println("private: " + isPrivate);*/ - replaceBy(binding, - definition.getTypeParameters(), - constant.getTypeParameters()); - if(isPrivate) { - definition.destroy(); - context.removeConstant(name); - } - context.markModified("SCLConstant.simplify-constant"); - return true; - } - return false; - } - - public void simplify(SSASimplificationContext context) { - if(!hasNoOccurences() /* TODO why this condition is needed? */) { - if(simplifyConstantFunction(context)) - return; - } - /*if(isPrivate) - definition.tryToMakeMonadic(context);*/ - definition.simplify(context); - if(inlineArity == Integer.MAX_VALUE && definition.isSimpleEnoughForInline()) { - inlineArity = definition.getArity(); - inlinableDefinition = (SSAFunction)definition.copy(); - context.markModified("mark inlineable " + name); - // FIXME this will make self calling function inlinable that may crash the compiler - } - } - - public void saveInlinableDefinition() { - if(inlineArity < Integer.MAX_VALUE) - inlinableDefinition = (SSAFunction)definition.copy(); - } -} +package org.simantics.scl.compiler.constants; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Named; +import org.simantics.scl.compiler.internal.codegen.optimization.Optimization; +import org.simantics.scl.compiler.internal.codegen.optimization.OptimizationMap; +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.SSAFunction; +import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump; +import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply; +import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions; +import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext; +import org.simantics.scl.compiler.types.TVar; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; + +public class SCLConstant extends DelegateConstant implements Named { + + public Name name; // Needed only for debugging + public SSAFunction definition; + public SSAFunction inlinableDefinition; + public int inlineArity = Integer.MAX_VALUE; + public int inlinePhaseMask = 0xffffffff; + public boolean isPrivate = false; + + public SCLConstant(Name name, Type type) { + super(type); + this.name = name; + } + + public void setInlineArity(int inlineArity, int inlinePhaseMask) { + this.inlineArity = inlineArity; + this.inlinePhaseMask = inlinePhaseMask; + //System.out.println(name + " " + inlineArity + " " + inlinePhaseMask); + } + + public void setPrivate(boolean isPrivate) { + this.isPrivate = isPrivate; + } + + public void setDefinition(SSAFunction definition) { + this.definition = definition; + } + + public SSAFunction getDefinition() { + return definition; + } + + @Override + public void inline(SSASimplificationContext context, LetApply apply) { + if(inlineTailCallToSelf(context, apply)) { + return; + } + /*if(tryBetaReduce(context, apply)) { + return; + }*/ + if(basicInline(context, apply)) { + return; + } + trySpecialize(context, apply); + + Optimization opt = OptimizationMap.OPTIMIZATIONS.get(name); + if(opt != null) + opt.inline(context, apply); + } + + static int inlineCount = 0; + + private boolean canInlineInPhase(int phase) { + return ((inlinePhaseMask >> phase)&1) == 1; + } + + private boolean basicInline(SSASimplificationContext context, LetApply apply) { + if(!canInlineInPhase(context.getPhase())) { + //System.out.println("Cannot optimize " + name + " in phase " + context.getPhase()); + return false; + } + ValRef functionRef = apply.getFunction(); + ValRef[] parameters = apply.getParameters(); + SSAFunction def = inlinableDefinition == null ? definition : inlinableDefinition; + if(parameters.length < inlineArity && + (!isPrivate + || parameters.length != def.getArity() + || hasMoreThanOneOccurences())) + return false; + + //if(def.getArity() == 0) + // return false; // FIXME + + //System.out.println("basicInline: " + apply); + //System.out.println("def: " + def); + + if(isPrivate && !hasMoreThanOneOccurences()) + context.removeConstant(name); + else + def = (SSAFunction)def.copy(); + + if(parameters.length >= def.getArity()) { + if(parameters.length != def.getArity()) + apply.split(def.getArity()); + apply.inline(def); + context.markModified("SCLConstant.beta-constant " + getName()); + } + else /*if(parameters.length < def.getArity())*/ { + def.applyTypes(functionRef.getTypeParameters()); + def.apply(apply.lineNumber, parameters); + + def.setTarget(apply.getTarget()); + new LetFunctions(def).insertBefore(apply); + + apply.remove(); + context.markModified("SCLConstant.partial-beta-constant " + getName()); + } + + /*Name newName = Name.create(name.module, + name.name + "_S" + (++inlineCount)); + SCLConstant newConstant = new SCLConstant(newName, type); + newConstant.setPrivate(true); + newConstant.setDefinition(definition.copy()); */ + /*System.out.println("*** 1 *************************************"); + System.out.println(definition); + System.out.println("*** 2 *************************************"); + System.out.println(newConstant.definition); + + function.remove(); + apply.setFunction(newConstant.createOccurrence(function.getTypeParameters())); + + context.addConstant(newConstant); + + context.markModified(); + + newConstant.trySpecialize(context, apply); + */ + + return true; + } + + private boolean inlineTailCallToSelf(SSASimplificationContext context, LetApply apply) { + SSAFunction thisFunction = apply.getParent().getParent(); + if(thisFunction != definition) + return false; + ValRef ref = apply.getTarget().getOccurrence(); + if(ref == null || ref.getNext() != null) + return false; + if(!(ref.getParent() instanceof Jump)) + return false; + Jump jump = (Jump)ref.getParent(); + if(jump.getParameters().length != 1) + return false; + if(jump.getTarget().getBinding() != thisFunction.getReturnCont()) + return false; + if(apply.getParameters().length != thisFunction.getArity()) + return false; + + jump.getTarget().remove(); + jump.setTarget(thisFunction.getFirstBlock().createOccurrence()); + jump.setParameters(apply.getParameters()); + + apply.getFunction().remove(); + apply.detach(); + + context.markModified("SCLConstant.simplify-tail-call"); + + return true; + } + + private void trySpecialize(SSASimplificationContext context, LetApply apply) { + if(!isPrivate) + return; + if(hasMoreThanOneOccurences()) + return; + if(apply.getParent().getParent() == definition) + return; + + // Specialization of type parameters + { + ValRef functionRef = apply.getFunction(); + Type[] pValues = functionRef.getTypeParameters(); + boolean hasComplexTypes = false; + for(Type type : pValues) + if(!(Types.canonical(type) instanceof TVar)) { + hasComplexTypes = true; + break; + } + if(hasComplexTypes) { + /*PrintingContext pc = new PrintingContext(); + pc.append(">> BEFORE >>\n"); + definition.toString(pc);*/ + + TVar[] pVars = definition.getTypeParameters(); + TVar[] pVarsTail; + if(pVars.length == pValues.length) + pVarsTail = TVar.EMPTY_ARRAY; + else { + pVarsTail = Arrays.copyOfRange(pVars, pValues.length, pVars.length); + pVars = Arrays.copyOf(pVars, pValues.length); + } + type = Types.instantiate(type, pValues); + /*pc.append("REPLACE: "); + pc.append(pVars); + pc.append(" -> "); + pc.append(pValues); + pc.append('\n');*/ + definition.replace(pVars, pValues); + TVar[] newParameters = Types.freeVarsArray(pValues); + type = Types.forAll(newParameters, type); + functionRef.setTypeParameters(newParameters); + definition.setTypeParameters(Types.concat(newParameters, pVarsTail)); + + /*pc.append(">> AFTER >>\n"); + definition.toString(pc); + System.out.println(pc);*/ + context.markModified("SCLConstant.specialize-types"); + } + } + + if(!definition.getFirstBlock().hasNoOccurences()) + // TODO We can flex this requirement if all jumps to the first block + // give same values to the first block + return; + + // Specialization of parameters + ValRef[] parameters = apply.getParameters(); + ValRef[] specialization = null; + int arity = Math.min(parameters.length, definition.getArity()); + for(int i=0;i newParameters = new ArrayList(parameters.length); + for(int i=0;i " + constant.getBinding()); + System.out.println("replace: " + this); + System.out.println("of type: " + this.getType()); + System.out.println("by: " + binding); + System.out.println("of type: " + binding.getType()); + System.out.println("parameters: " + Types.toString(definition.getTypeParameters())); + System.out.println("parameters2: " + Types.toString(constant.getTypeParameters())); + System.out.println("private: " + isPrivate);*/ + replaceBy(binding, + definition.getTypeParameters(), + constant.getTypeParameters()); + if(isPrivate) { + definition.destroy(); + context.removeConstant(name); + } + context.markModified("SCLConstant.simplify-constant"); + return true; + } + return false; + } + + public void simplify(SSASimplificationContext context) { + if(!hasNoOccurences() /* TODO why this condition is needed? */) { + if(simplifyConstantFunction(context)) + return; + } + /*if(isPrivate) + definition.tryToMakeMonadic(context);*/ + definition.simplify(context); + if(inlineArity == Integer.MAX_VALUE && definition.isSimpleEnoughForInline()) { + inlineArity = definition.getArity(); + inlinableDefinition = (SSAFunction)definition.copy(); + context.markModified("mark inlineable " + name); + // FIXME this will make self calling function inlinable that may crash the compiler + } + } + + public void saveInlinableDefinition() { + if(inlineArity < Integer.MAX_VALUE) + inlinableDefinition = (SSAFunction)definition.copy(); + } + + public void cleanup() { + if(definition != null) + definition.cleanup(); + if(inlinableDefinition != null) + inlinableDefinition.cleanup(); + } +}