X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fcodegen%2Fanalysis%2FLoopAnalysis.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fcodegen%2Fanalysis%2FLoopAnalysis.java;h=db74fc32cd78293f093b70874b3a41d7403c2ebc;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=34f6578e33e847619a4ed6c3c62c090d9f0d2399;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/LoopAnalysis.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/LoopAnalysis.java index 34f6578e3..db74fc32c 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/LoopAnalysis.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/analysis/LoopAnalysis.java @@ -1,89 +1,89 @@ -package org.simantics.scl.compiler.internal.codegen.analysis; - -import org.simantics.scl.compiler.common.names.Name; -import org.simantics.scl.compiler.common.names.Names; -import org.simantics.scl.compiler.constants.SCLConstant; -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.binders.ValRefBinder; -import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply; - -import gnu.trove.set.hash.THashSet; - -public class LoopAnalysis { - - /** - * Checks if it is possible to return to the loop after exiting - * before exiting the function where the block belongs to. - */ - private static boolean isLoopingBlock(SSABlock block) { - THashSet handled = new THashSet(); - for(SSABlock succBlock : block.getExit().getSuccessors()) - if(isLoopingBlock(block, handled, succBlock)) - return true; - return false; - } - - /** - * Checks if it is possible to execute block more than once without visiting - * the breaker block. It is assumed that breaker is a dominator of the block. - */ - public static boolean isLoopingBlockWithBreaker(SSABlock block, SSABlock breaker) { - SSAFunction function = block.getParent(); - - if(function == block.getParent()) { - THashSet handled = new THashSet(); - handled.add(breaker); - for(SSABlock succBlock : block.getExit().getSuccessors()) - if(isLoopingBlock(block, handled, succBlock)) - return true; - return false; - } - else { - if(isLoopingBlock(block)) - return false; - Val functionTarget = function.getTarget(); - if(functionTarget.hasMoreThanOneOccurences()) - return false; - ValRef occ = functionTarget.getOccurrence(); - if(occ == null) - return false; - ValRefBinder occParent = occ.getParent(); - if(!(occParent instanceof LetApply)) - return true; // Not necessarily the right answer, but we don't try to analyse further - LetApply apply = (LetApply)occParent; - if(!isAppliedAtMostOnce(apply, occ, function)) - return true; - return isLoopingBlockWithBreaker(apply.getParent(), breaker); - } - } - - private static boolean isAppliedAtMostOnce(LetApply apply, ValRef funRef, SSAFunction function) { - ValRef applyFunctionRef = apply.getFunction(); - if(funRef == applyFunctionRef) { - return apply.getParameters().length == function.getArity(); - } - Val applyFunction = applyFunctionRef.getBinding(); - if(!(applyFunction instanceof SCLConstant)) - return false; // Not necessarily the right answer - Name name = ((SCLConstant)applyFunction).getName(); - if(name == Names.Prelude_build) - return true; - return false; - } - - private static boolean isLoopingBlock(SSABlock originalBlock, - THashSet handled, SSABlock block) { - if(!handled.add(block)) - return false; - if(block == originalBlock) - return true; - for(SSABlock succBlock : block.getExit().getSuccessors()) - if(isLoopingBlock(originalBlock, handled, succBlock)) - return true; - return false; - } - -} +package org.simantics.scl.compiler.internal.codegen.analysis; + +import org.simantics.scl.compiler.common.names.Name; +import org.simantics.scl.compiler.common.names.Names; +import org.simantics.scl.compiler.constants.SCLConstant; +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.binders.ValRefBinder; +import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply; + +import gnu.trove.set.hash.THashSet; + +public class LoopAnalysis { + + /** + * Checks if it is possible to return to the loop after exiting + * before exiting the function where the block belongs to. + */ + private static boolean isLoopingBlock(SSABlock block) { + THashSet handled = new THashSet(); + for(SSABlock succBlock : block.getExit().getSuccessors()) + if(isLoopingBlock(block, handled, succBlock)) + return true; + return false; + } + + /** + * Checks if it is possible to execute block more than once without visiting + * the breaker block. It is assumed that breaker is a dominator of the block. + */ + public static boolean isLoopingBlockWithBreaker(SSABlock block, SSABlock breaker) { + SSAFunction function = block.getParent(); + + if(function == block.getParent()) { + THashSet handled = new THashSet(); + handled.add(breaker); + for(SSABlock succBlock : block.getExit().getSuccessors()) + if(isLoopingBlock(block, handled, succBlock)) + return true; + return false; + } + else { + if(isLoopingBlock(block)) + return false; + Val functionTarget = function.getTarget(); + if(functionTarget.hasMoreThanOneOccurences()) + return false; + ValRef occ = functionTarget.getOccurrence(); + if(occ == null) + return false; + ValRefBinder occParent = occ.getParent(); + if(!(occParent instanceof LetApply)) + return true; // Not necessarily the right answer, but we don't try to analyse further + LetApply apply = (LetApply)occParent; + if(!isAppliedAtMostOnce(apply, occ, function)) + return true; + return isLoopingBlockWithBreaker(apply.getParent(), breaker); + } + } + + private static boolean isAppliedAtMostOnce(LetApply apply, ValRef funRef, SSAFunction function) { + ValRef applyFunctionRef = apply.getFunction(); + if(funRef == applyFunctionRef) { + return apply.getParameters().length == function.getArity(); + } + Val applyFunction = applyFunctionRef.getBinding(); + if(!(applyFunction instanceof SCLConstant)) + return false; // Not necessarily the right answer + Name name = ((SCLConstant)applyFunction).getName(); + if(name == Names.Prelude_build) + return true; + return false; + } + + private static boolean isLoopingBlock(SSABlock originalBlock, + THashSet handled, SSABlock block) { + if(!handled.add(block)) + return false; + if(block == originalBlock) + return true; + for(SSABlock succBlock : block.getExit().getSuccessors()) + if(isLoopingBlock(originalBlock, handled, succBlock)) + return true; + return false; + } + +}