# HG changeset patch # User Lukas Stadler # Date 1351526744 -3600 # Node ID 795df168728230f71859267d16f33a6877978564 # Parent cfd5c59df26a2a7e10eb77c046569f34594b113c renamed CheckCastElimination to ConditionalElimination, plus a few small changes diff -r cfd5c59df26a -r 795df1687282 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Oct 29 14:47:07 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Oct 29 17:05:44 2012 +0100 @@ -165,7 +165,7 @@ Debug.dump(graph, "Graph"); // TypeSystemTest.outputGraph(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); - new CheckCastEliminationPhase().apply(graph); + new ConditionalEliminationPhase().apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); diff -r cfd5c59df26a -r 795df1687282 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Oct 29 14:47:07 2012 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Oct 29 17:05:44 2012 +0100 @@ -190,7 +190,7 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); new CanonicalizerPhase(null, runtime(), null).apply(graph); - new CheckCastEliminationPhase().apply(graph); + new ConditionalEliminationPhase().apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); new GlobalValueNumberingPhase().apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); @@ -254,7 +254,7 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); new CanonicalizerPhase(null, runtime(), null).apply(graph); - new CheckCastEliminationPhase().apply(graph); + new ConditionalEliminationPhase().apply(graph); new CanonicalizerPhase(null, runtime(), null).apply(graph); Debug.dump(graph, "Graph"); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext()); diff -r cfd5c59df26a -r 795df1687282 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Oct 29 14:47:07 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Oct 29 17:05:44 2012 +0100 @@ -134,7 +134,7 @@ } if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) { - new IterativeCheckCastEliminationPhase(target, runtime, assumptions).apply(graph); + new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph); } } @@ -191,7 +191,7 @@ } if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) { - new IterativeCheckCastEliminationPhase(target, runtime, assumptions).apply(graph); + new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph); } plan.runPhases(PhasePosition.MID_LEVEL, graph); diff -r cfd5c59df26a -r 795df1687282 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CheckCastEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CheckCastEliminationPhase.java Mon Oct 29 14:47:07 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,384 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.graph.*; - -public class CheckCastEliminationPhase extends Phase { - - private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered"); - private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered"); - private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved"); - private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved"); - private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved"); - private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved"); - private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced"); - - private StructuredGraph graph; - - @Override - protected void run(StructuredGraph inputGraph) { - graph = inputGraph; - new EliminateCheckCasts(graph.start(), new State()).apply(); - } - - public static class State implements MergeableState { - - private IdentityHashMap knownTypes; - private HashSet knownNotNull; - private HashSet knownNull; - private IdentityHashMap trueConditions; - private IdentityHashMap falseConditions; - - public State() { - this.knownTypes = new IdentityHashMap<>(); - this.knownNotNull = new HashSet<>(); - this.knownNull = new HashSet<>(); - this.trueConditions = new IdentityHashMap<>(); - this.falseConditions = new IdentityHashMap<>(); - } - - public State(State other) { - this.knownTypes = new IdentityHashMap<>(other.knownTypes); - this.knownNotNull = new HashSet<>(other.knownNotNull); - this.knownNull = new HashSet<>(other.knownNull); - this.trueConditions = new IdentityHashMap<>(other.trueConditions); - this.falseConditions = new IdentityHashMap<>(other.falseConditions); - } - - @Override - public boolean merge(MergeNode merge, List withStates) { - IdentityHashMap newKnownTypes = new IdentityHashMap<>(); - HashSet newKnownNotNull = new HashSet<>(); - HashSet newKnownNull = new HashSet<>(); - IdentityHashMap newTrueConditions = new IdentityHashMap<>(); - IdentityHashMap newFalseConditions = new IdentityHashMap<>(); - - for (Map.Entry entry : knownTypes.entrySet()) { - ValueNode node = entry.getKey(); - ResolvedJavaType type = entry.getValue(); - - for (State other : withStates) { - ResolvedJavaType otherType = other.getNodeType(node); - type = widen(type, otherType); - if (type == null) { - break; - } - } - if (type == null && type != node.objectStamp().type()) { - newKnownTypes.put(node, type); - } - } - for (ValueNode node : knownNotNull) { - boolean notNull = true; - for (State other : withStates) { - if (!other.knownNotNull.contains(node)) { - notNull = false; - break; - } - } - if (notNull) { - newKnownNotNull.add(node); - } - } - for (ValueNode node : knownNull) { - boolean nul = true; - for (State other : withStates) { - if (!other.knownNull.contains(node)) { - nul = false; - break; - } - } - if (nul) { - newKnownNull.add(node); - } - } - for (Map.Entry entry : trueConditions.entrySet()) { - BooleanNode check = entry.getKey(); - ValueNode guard = entry.getValue(); - - for (State other : withStates) { - ValueNode otherGuard = other.trueConditions.get(check); - if (otherGuard == null) { - guard = null; - break; - } - if (otherGuard != guard) { - guard = merge; - } - } - if (guard != null) { - newTrueConditions.put(check, guard); - } - } - for (Map.Entry entry : falseConditions.entrySet()) { - BooleanNode check = entry.getKey(); - ValueNode guard = entry.getValue(); - - for (State other : withStates) { - ValueNode otherGuard = other.falseConditions.get(check); - if (otherGuard == null) { - guard = null; - break; - } - if (otherGuard != guard) { - guard = merge; - } - } - if (guard != null) { - newFalseConditions.put(check, guard); - } - } - - /* - // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values) - if (!(merge instanceof LoopBeginNode)) { - for (PhiNode phi : merge.phis()) { - if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) { - ValueNode firstValue = phi.valueAt(0); - ResolvedJavaType type = getNodeType(firstValue); - boolean notNull = knownNotNull.contains(firstValue); - boolean nul = knownNull.contains(firstValue); - - for (int i = 0; i < withStates.size(); i++) { - State otherState = withStates.get(i); - ValueNode value = phi.valueAt(i + 1); - ResolvedJavaType otherType = otherState.getNodeType(value); - type = widen(type, otherType); - notNull &= otherState.knownNotNull.contains(value); - nul &= otherState.knownNull.contains(value); - } - if (type == null && type != phi.declaredType()) { - newKnownTypes.put(phi, type); - } - if (notNull) { - newKnownNotNull.add(phi); - } - if (nul) { - newKnownNull.add(phi); - } - } - } - } - */ - this.knownTypes = newKnownTypes; - this.knownNotNull = newKnownNotNull; - this.knownNull = newKnownNull; - this.trueConditions = newTrueConditions; - this.falseConditions = newFalseConditions; - return true; - } - - public ResolvedJavaType getNodeType(ValueNode node) { - ResolvedJavaType result = knownTypes.get(node); - return result == null ? node.objectStamp().type() : result; - } - - @Override - public void loopBegin(LoopBeginNode loopBegin) { - } - - @Override - public void loopEnds(LoopBeginNode loopBegin, List loopEndStates) { - } - - @Override - public void afterSplit(FixedNode node) { - } - - @Override - public State clone() { - return new State(this); - } - } - - public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) { - if (a == null || b == null) { - return null; - } else if (a == b) { - return a; - } else { - return a.findLeastCommonAncestor(b); - } - } - - public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) { - if (a == null) { - return b; - } else if (b == null) { - return a; - } else if (a == b) { - return a; - } else if (a.isSubtypeOf(b)) { - return a; - } else if (b.isSubtypeOf(a)) { - return b; - } else { - return a; - } - } - - public class EliminateCheckCasts extends PostOrderNodeIterator { - private BeginNode lastBegin = null; - - public EliminateCheckCasts(FixedNode start, State initialState) { - super(start, initialState); - } - - @Override - protected void node(FixedNode node) { - if (node instanceof BeginNode) { - BeginNode begin = (BeginNode) node; - lastBegin = begin; - Node pred = node.predecessor(); - if (pred != null && pred instanceof IfNode) { - IfNode ifNode = (IfNode) pred; - if (!(ifNode.condition() instanceof ConstantNode)) { - boolean isTrue = (node == ifNode.trueSuccessor()); - if (isTrue) { - state.trueConditions.put(ifNode.condition(), begin); - } else { - state.falseConditions.put(ifNode.condition(), begin); - } - } - if (ifNode.condition() instanceof InstanceOfNode) { - InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); - if ((node == ifNode.trueSuccessor())) { - ValueNode object = instanceOf.object(); - state.knownNotNull.add(object); - state.knownTypes.put(object, tighten(instanceOf.targetClass(), state.getNodeType(object))); - metricInstanceOfRegistered.increment(); - } - } else if (ifNode.condition() instanceof IsNullNode) { - IsNullNode nullCheck = (IsNullNode) ifNode.condition(); - boolean isNull = (node == ifNode.trueSuccessor()); - if (isNull) { - state.knownNull.add(nullCheck.object()); - } else { - state.knownNotNull.add(nullCheck.object()); - } - metricNullCheckRegistered.increment(); - } - } - for (GuardNode guard : begin.guards().snapshot()) { - BooleanNode condition = guard.condition(); - ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition); - if (existingGuards != null) { - guard.replaceAtUsages(existingGuards); - GraphUtil.killWithUnusedFloatingInputs(guard); - metricGuardsReplaced.increment(); - } else { - boolean removeCheck = false; - if (condition instanceof IsNullNode) { - IsNullNode isNull = (IsNullNode) condition; - if (guard.negated() && state.knownNotNull.contains(isNull.object())) { - removeCheck = true; - } else if (!guard.negated() && state.knownNull.contains(isNull.object())) { - removeCheck = true; - } - if (removeCheck) { - metricNullCheckGuardRemoved.increment(); - } - } - if (removeCheck) { - guard.replaceAtUsages(begin); - GraphUtil.killWithUnusedFloatingInputs(guard); - } else { - if (guard.negated()) { - state.falseConditions.put(condition, guard); - } else { - state.trueConditions.put(condition, guard); - } - } - } - } - } else if (node instanceof CheckCastNode) { - CheckCastNode checkCast = (CheckCastNode) node; - ResolvedJavaType type = state.getNodeType(checkCast.object()); - if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) { - PiNode piNode; - boolean nonNull = state.knownNotNull.contains(checkCast.object()); - piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type))); - checkCast.replaceAtUsages(piNode); - graph.removeFixed(checkCast); - metricCheckCastRemoved.increment(); - } - } else if (node instanceof IfNode) { - IfNode ifNode = (IfNode) node; - BooleanNode replaceWith = null; - BooleanNode compare = ifNode.condition(); - - if (state.trueConditions.containsKey(compare)) { - replaceWith = ConstantNode.forBoolean(true, graph); - } else if (state.falseConditions.containsKey(compare)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } else { - if (compare instanceof InstanceOfNode) { - InstanceOfNode instanceOf = (InstanceOfNode) compare; - ValueNode object = instanceOf.object(); - if (state.knownNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } else if (state.knownNotNull.contains(object)) { - ResolvedJavaType type = state.getNodeType(object); - if (type != null && type.isSubtypeOf(instanceOf.targetClass())) { - replaceWith = ConstantNode.forBoolean(true, graph); - } - } - if (replaceWith != null) { - metricInstanceOfRemoved.increment(); - } - } else if (compare instanceof IsNullNode) { - IsNullNode isNull = (IsNullNode) compare; - ValueNode object = isNull.object(); - if (state.knownNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(true, graph); - } else if (state.knownNotNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } - if (replaceWith != null) { - metricNullCheckRemoved.increment(); - } - } - } - if (replaceWith != null) { - ifNode.setCondition(replaceWith); - if (compare.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(compare); - } - } - } - } - } - -} diff -r cfd5c59df26a -r 795df1687282 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Oct 29 17:05:44 2012 +0100 @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.graph.*; + +public class ConditionalEliminationPhase extends Phase { + + private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered"); + private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered"); + private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved"); + private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved"); + private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved"); + private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved"); + private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced"); + + private StructuredGraph graph; + + @Override + protected void run(StructuredGraph inputGraph) { + graph = inputGraph; + new ConditionalElimination(graph.start(), new State()).apply(); + } + + public static class State implements MergeableState { + + private IdentityHashMap knownTypes; + private HashSet knownNotNull; + private HashSet knownNull; + private IdentityHashMap trueConditions; + private IdentityHashMap falseConditions; + + public State() { + this.knownTypes = new IdentityHashMap<>(); + this.knownNotNull = new HashSet<>(); + this.knownNull = new HashSet<>(); + this.trueConditions = new IdentityHashMap<>(); + this.falseConditions = new IdentityHashMap<>(); + } + + public State(State other) { + this.knownTypes = new IdentityHashMap<>(other.knownTypes); + this.knownNotNull = new HashSet<>(other.knownNotNull); + this.knownNull = new HashSet<>(other.knownNull); + this.trueConditions = new IdentityHashMap<>(other.trueConditions); + this.falseConditions = new IdentityHashMap<>(other.falseConditions); + } + + @Override + public boolean merge(MergeNode merge, List withStates) { + IdentityHashMap newKnownTypes = new IdentityHashMap<>(); + HashSet newKnownNotNull = new HashSet<>(); + HashSet newKnownNull = new HashSet<>(); + IdentityHashMap newTrueConditions = new IdentityHashMap<>(); + IdentityHashMap newFalseConditions = new IdentityHashMap<>(); + + for (Map.Entry entry : knownTypes.entrySet()) { + ValueNode node = entry.getKey(); + ResolvedJavaType type = entry.getValue(); + + for (State other : withStates) { + ResolvedJavaType otherType = other.getNodeType(node); + type = widen(type, otherType); + if (type == null) { + break; + } + } + if (type == null && type != node.objectStamp().type()) { + newKnownTypes.put(node, type); + } + } + for (ValueNode node : knownNotNull) { + boolean notNull = true; + for (State other : withStates) { + if (!other.knownNotNull.contains(node)) { + notNull = false; + break; + } + } + if (notNull) { + newKnownNotNull.add(node); + } + } + for (ValueNode node : knownNull) { + boolean isNull = true; + for (State other : withStates) { + if (!other.knownNull.contains(node)) { + isNull = false; + break; + } + } + if (isNull) { + newKnownNull.add(node); + } + } + for (Map.Entry entry : trueConditions.entrySet()) { + BooleanNode check = entry.getKey(); + ValueNode guard = entry.getValue(); + + for (State other : withStates) { + ValueNode otherGuard = other.trueConditions.get(check); + if (otherGuard == null) { + guard = null; + break; + } + if (otherGuard != guard) { + guard = merge; + } + } + if (guard != null) { + newTrueConditions.put(check, guard); + } + } + for (Map.Entry entry : falseConditions.entrySet()) { + BooleanNode check = entry.getKey(); + ValueNode guard = entry.getValue(); + + for (State other : withStates) { + ValueNode otherGuard = other.falseConditions.get(check); + if (otherGuard == null) { + guard = null; + break; + } + if (otherGuard != guard) { + guard = merge; + } + } + if (guard != null) { + newFalseConditions.put(check, guard); + } + } + + // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values) + if (!(merge instanceof LoopBeginNode)) { + for (PhiNode phi : merge.phis()) { + if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) { + ValueNode firstValue = phi.valueAt(0); + ResolvedJavaType type = getNodeType(firstValue); + boolean notNull = knownNotNull.contains(firstValue); + boolean isNull = knownNull.contains(firstValue); + + for (int i = 0; i < withStates.size(); i++) { + State otherState = withStates.get(i); + ValueNode value = phi.valueAt(i + 1); + ResolvedJavaType otherType = otherState.getNodeType(value); + type = widen(type, otherType); + notNull &= otherState.knownNotNull.contains(value); + isNull &= otherState.knownNull.contains(value); + } + if (type != null) { + newKnownTypes.put(phi, type); + } + if (notNull) { + newKnownNotNull.add(phi); + } + if (isNull) { + newKnownNull.add(phi); + } + } + } + } + + this.knownTypes = newKnownTypes; + this.knownNotNull = newKnownNotNull; + this.knownNull = newKnownNull; + this.trueConditions = newTrueConditions; + this.falseConditions = newFalseConditions; + return true; + } + + public ResolvedJavaType getNodeType(ValueNode node) { + ResolvedJavaType result = knownTypes.get(node); + return result == null ? node.objectStamp().type() : result; + } + + @Override + public void loopBegin(LoopBeginNode loopBegin) { + } + + @Override + public void loopEnds(LoopBeginNode loopBegin, List loopEndStates) { + } + + @Override + public void afterSplit(FixedNode node) { + } + + @Override + public State clone() { + return new State(this); + } + } + + public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null || b == null) { + return null; + } else if (a == b) { + return a; + } else { + return a.findLeastCommonAncestor(b); + } + } + + public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) { + if (a == null) { + return b; + } else if (b == null) { + return a; + } else if (a == b) { + return a; + } else if (a.isSubtypeOf(b)) { + return a; + } else if (b.isSubtypeOf(a)) { + return b; + } else { + return a; + } + } + + public class ConditionalElimination extends PostOrderNodeIterator { + private BeginNode lastBegin = null; + + public ConditionalElimination(FixedNode start, State initialState) { + super(start, initialState); + } + + @Override + protected void node(FixedNode node) { + if (node instanceof BeginNode) { + BeginNode begin = (BeginNode) node; + lastBegin = begin; + Node pred = node.predecessor(); + if (pred != null && pred instanceof IfNode) { + IfNode ifNode = (IfNode) pred; + if (!(ifNode.condition() instanceof ConstantNode)) { + boolean isTrue = (node == ifNode.trueSuccessor()); + if (isTrue) { + state.trueConditions.put(ifNode.condition(), begin); + } else { + state.falseConditions.put(ifNode.condition(), begin); + } + } + if (ifNode.condition() instanceof InstanceOfNode) { + InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); + if ((node == ifNode.trueSuccessor())) { + ValueNode object = instanceOf.object(); + state.knownNotNull.add(object); + state.knownTypes.put(object, tighten(instanceOf.targetClass(), state.getNodeType(object))); + metricInstanceOfRegistered.increment(); + } + } else if (ifNode.condition() instanceof IsNullNode) { + IsNullNode nullCheck = (IsNullNode) ifNode.condition(); + boolean isNull = (node == ifNode.trueSuccessor()); + if (isNull) { + state.knownNull.add(nullCheck.object()); + } else { + state.knownNotNull.add(nullCheck.object()); + } + metricNullCheckRegistered.increment(); + } + } + for (GuardNode guard : begin.guards().snapshot()) { + BooleanNode condition = guard.condition(); + ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition); + if (existingGuards != null) { + guard.replaceAtUsages(existingGuards); + GraphUtil.killWithUnusedFloatingInputs(guard); + metricGuardsReplaced.increment(); + } else { + boolean removeCheck = false; + if (condition instanceof IsNullNode) { + IsNullNode isNull = (IsNullNode) condition; + if (guard.negated() && state.knownNotNull.contains(isNull.object())) { + removeCheck = true; + } else if (!guard.negated() && state.knownNull.contains(isNull.object())) { + removeCheck = true; + } + if (removeCheck) { + metricNullCheckGuardRemoved.increment(); + } + } + if (removeCheck) { + guard.replaceAtUsages(begin); + GraphUtil.killWithUnusedFloatingInputs(guard); + } else { + if (guard.negated()) { + state.falseConditions.put(condition, guard); + } else { + state.trueConditions.put(condition, guard); + } + } + } + } + } else if (node instanceof CheckCastNode) { + CheckCastNode checkCast = (CheckCastNode) node; + ResolvedJavaType type = state.getNodeType(checkCast.object()); + if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) { + PiNode piNode; + boolean nonNull = state.knownNotNull.contains(checkCast.object()); + piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type))); + checkCast.replaceAtUsages(piNode); + graph.removeFixed(checkCast); + metricCheckCastRemoved.increment(); + } + } else if (node instanceof IfNode) { + IfNode ifNode = (IfNode) node; + BooleanNode replaceWith = null; + BooleanNode compare = ifNode.condition(); + + if (state.trueConditions.containsKey(compare)) { + replaceWith = ConstantNode.forBoolean(true, graph); + } else if (state.falseConditions.containsKey(compare)) { + replaceWith = ConstantNode.forBoolean(false, graph); + } else { + if (compare instanceof InstanceOfNode) { + InstanceOfNode instanceOf = (InstanceOfNode) compare; + ValueNode object = instanceOf.object(); + if (state.knownNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(false, graph); + } else if (state.knownNotNull.contains(object)) { + ResolvedJavaType type = state.getNodeType(object); + if (type != null && type.isSubtypeOf(instanceOf.targetClass())) { + replaceWith = ConstantNode.forBoolean(true, graph); + } + } + if (replaceWith != null) { + metricInstanceOfRemoved.increment(); + } + } else if (compare instanceof IsNullNode) { + IsNullNode isNull = (IsNullNode) compare; + ValueNode object = isNull.object(); + if (state.knownNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(true, graph); + } else if (state.knownNotNull.contains(object)) { + replaceWith = ConstantNode.forBoolean(false, graph); + } + if (replaceWith != null) { + metricNullCheckRemoved.increment(); + } + } + } + if (replaceWith != null) { + ifNode.setCondition(replaceWith); + if (compare.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(compare); + } + } + } + } + } + +} diff -r cfd5c59df26a -r 795df1687282 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeCheckCastEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeCheckCastEliminationPhase.java Mon Oct 29 14:47:07 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.Graph.InputChangedListener; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; - - -public class IterativeCheckCastEliminationPhase extends Phase { - private final TargetDescription target; - private final MetaAccessProvider runtime; - private final Assumptions assumptions; - - public IterativeCheckCastEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { - this.target = target; - this.runtime = runtime; - this.assumptions = assumptions; - } - - @Override - protected void run(StructuredGraph graph) { - Set canonicalizationRoots = new HashSet<>(); - CheckCastEliminationPhase eliminate = new CheckCastEliminationPhase(); - Listener listener = new Listener(canonicalizationRoots); - while (true) { - graph.trackInputChange(listener); - eliminate.apply(graph); - graph.stopTrackingInputChange(); - if (canonicalizationRoots.isEmpty()) { - break; - } - new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph); - canonicalizationRoots.clear(); - } - } - - private static class Listener implements InputChangedListener { - private final Set canonicalizationRoots; - public Listener(Set canonicalizationRoots) { - this.canonicalizationRoots = canonicalizationRoots; - } - @Override - public void inputChanged(Node node) { - canonicalizationRoots.add(node); - } - } -} diff -r cfd5c59df26a -r 795df1687282 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Oct 29 17:05:44 2012 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Graph.InputChangedListener; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; + + +public class IterativeConditionalEliminationPhase extends Phase { + private final TargetDescription target; + private final MetaAccessProvider runtime; + private final Assumptions assumptions; + + public IterativeConditionalEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { + this.target = target; + this.runtime = runtime; + this.assumptions = assumptions; + } + + @Override + protected void run(StructuredGraph graph) { + Set canonicalizationRoots = new HashSet<>(); + ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(); + Listener listener = new Listener(canonicalizationRoots); + while (true) { + graph.trackInputChange(listener); + eliminate.apply(graph); + graph.stopTrackingInputChange(); + if (canonicalizationRoots.isEmpty()) { + break; + } + new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph); + canonicalizationRoots.clear(); + } + } + + private static class Listener implements InputChangedListener { + private final Set canonicalizationRoots; + public Listener(Set canonicalizationRoots) { + this.canonicalizationRoots = canonicalizationRoots; + } + @Override + public void inputChanged(Node node) { + canonicalizationRoots.add(node); + } + } +}