< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java

Print this page




  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.nodes;
  24 
  25 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
  26 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
  27 
  28 import java.util.ArrayList;
  29 import java.util.Arrays;
  30 import java.util.Iterator;
  31 import java.util.List;
  32 


  33 import org.graalvm.compiler.core.common.calc.Condition;
  34 import org.graalvm.compiler.core.common.type.IntegerStamp;
  35 import org.graalvm.compiler.core.common.type.Stamp;
  36 import org.graalvm.compiler.core.common.type.StampFactory;
  37 import org.graalvm.compiler.debug.CounterKey;
  38 import org.graalvm.compiler.debug.DebugContext;
  39 import org.graalvm.compiler.debug.GraalError;
  40 import org.graalvm.compiler.graph.Node;
  41 import org.graalvm.compiler.graph.NodeClass;
  42 import org.graalvm.compiler.graph.iterators.NodeIterable;
  43 import org.graalvm.compiler.graph.spi.Canonicalizable;
  44 import org.graalvm.compiler.graph.spi.Simplifiable;
  45 import org.graalvm.compiler.graph.spi.SimplifierTool;
  46 import org.graalvm.compiler.nodeinfo.InputType;
  47 import org.graalvm.compiler.nodeinfo.NodeInfo;
  48 import org.graalvm.compiler.nodes.calc.CompareNode;
  49 import org.graalvm.compiler.nodes.calc.ConditionalNode;
  50 import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
  51 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
  52 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
  53 import org.graalvm.compiler.nodes.calc.IsNullNode;
  54 import org.graalvm.compiler.nodes.calc.NormalizeCompareNode;


  55 import org.graalvm.compiler.nodes.java.InstanceOfNode;

  56 import org.graalvm.compiler.nodes.spi.LIRLowerable;
  57 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  58 import org.graalvm.compiler.nodes.util.GraphUtil;
  59 import org.graalvm.util.EconomicMap;
  60 import org.graalvm.util.Equivalence;
  61 
  62 import jdk.vm.ci.meta.Constant;
  63 import jdk.vm.ci.meta.ConstantReflectionProvider;
  64 import jdk.vm.ci.meta.JavaConstant;
  65 import jdk.vm.ci.meta.JavaKind;
  66 import jdk.vm.ci.meta.PrimitiveConstant;
  67 
  68 /**
  69  * The {@code IfNode} represents a branch that can go one of two directions depending on the outcome
  70  * of a comparison.
  71  */
  72 @NodeInfo(cycles = CYCLES_2, size = SIZE_2, sizeRationale = "2 jmps")
  73 public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable {
  74     public static final NodeClass<IfNode> TYPE = NodeClass.create(IfNode.class);
  75 


 239                     AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor();
 240                     nextIf.setFalseSuccessor(null);
 241                     intermediateBegin.setNext(null);
 242                     this.setFalseSuccessor(null);
 243 
 244                     this.replaceAtPredecessor(nextIf);
 245                     nextIf.setFalseSuccessor(intermediateBegin);
 246                     intermediateBegin.setNext(this);
 247                     this.setFalseSuccessor(bothFalseBegin);
 248                     nextIf.setTrueSuccessorProbability(probabilityB);
 249                     if (probabilityB == 1.0) {
 250                         this.setTrueSuccessorProbability(0.0);
 251                     } else {
 252                         double newProbability = this.trueSuccessorProbability / (1.0 - probabilityB);
 253                         this.setTrueSuccessorProbability(Math.min(1.0, newProbability));
 254                     }
 255                     return;
 256                 }
 257             }
 258         }





















































































































 259     }
 260 
 261     /**
 262      * Try to optimize this as if it were a {@link ConditionalNode}.
 263      */
 264     private boolean conditionalNodeOptimization(SimplifierTool tool) {
 265         if (trueSuccessor().next() instanceof AbstractEndNode && falseSuccessor().next() instanceof AbstractEndNode) {
 266             AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next();
 267             AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next();
 268             if (trueEnd.merge() != falseEnd.merge()) {
 269                 return false;
 270             }
 271             if (!(trueEnd.merge() instanceof MergeNode)) {
 272                 return false;
 273             }
 274             MergeNode merge = (MergeNode) trueEnd.merge();
 275             if (merge.usages().count() != 1 || merge.phis().count() != 1) {
 276                 return false;
 277             }
 278 




  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.nodes;
  24 
  25 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
  26 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
  27 
  28 import java.util.ArrayList;
  29 import java.util.Arrays;
  30 import java.util.Iterator;
  31 import java.util.List;
  32 
  33 import jdk.vm.ci.meta.MetaAccessProvider;
  34 import jdk.vm.ci.meta.ResolvedJavaType;
  35 import org.graalvm.compiler.core.common.calc.Condition;
  36 import org.graalvm.compiler.core.common.type.IntegerStamp;
  37 import org.graalvm.compiler.core.common.type.Stamp;
  38 import org.graalvm.compiler.core.common.type.StampFactory;
  39 import org.graalvm.compiler.debug.CounterKey;
  40 import org.graalvm.compiler.debug.DebugContext;
  41 import org.graalvm.compiler.debug.GraalError;
  42 import org.graalvm.compiler.graph.Node;
  43 import org.graalvm.compiler.graph.NodeClass;
  44 import org.graalvm.compiler.graph.iterators.NodeIterable;
  45 import org.graalvm.compiler.graph.spi.Canonicalizable;
  46 import org.graalvm.compiler.graph.spi.Simplifiable;
  47 import org.graalvm.compiler.graph.spi.SimplifierTool;
  48 import org.graalvm.compiler.nodeinfo.InputType;
  49 import org.graalvm.compiler.nodeinfo.NodeInfo;
  50 import org.graalvm.compiler.nodes.calc.CompareNode;
  51 import org.graalvm.compiler.nodes.calc.ConditionalNode;
  52 import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
  53 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
  54 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
  55 import org.graalvm.compiler.nodes.calc.IsNullNode;
  56 import org.graalvm.compiler.nodes.calc.NormalizeCompareNode;
  57 import org.graalvm.compiler.nodes.calc.ObjectEqualsNode;
  58 import org.graalvm.compiler.nodes.extended.UnboxNode;
  59 import org.graalvm.compiler.nodes.java.InstanceOfNode;
  60 import org.graalvm.compiler.nodes.java.LoadFieldNode;
  61 import org.graalvm.compiler.nodes.spi.LIRLowerable;
  62 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  63 import org.graalvm.compiler.nodes.util.GraphUtil;
  64 import org.graalvm.util.EconomicMap;
  65 import org.graalvm.util.Equivalence;
  66 
  67 import jdk.vm.ci.meta.Constant;
  68 import jdk.vm.ci.meta.ConstantReflectionProvider;
  69 import jdk.vm.ci.meta.JavaConstant;
  70 import jdk.vm.ci.meta.JavaKind;
  71 import jdk.vm.ci.meta.PrimitiveConstant;
  72 
  73 /**
  74  * The {@code IfNode} represents a branch that can go one of two directions depending on the outcome
  75  * of a comparison.
  76  */
  77 @NodeInfo(cycles = CYCLES_2, size = SIZE_2, sizeRationale = "2 jmps")
  78 public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable {
  79     public static final NodeClass<IfNode> TYPE = NodeClass.create(IfNode.class);
  80 


 244                     AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor();
 245                     nextIf.setFalseSuccessor(null);
 246                     intermediateBegin.setNext(null);
 247                     this.setFalseSuccessor(null);
 248 
 249                     this.replaceAtPredecessor(nextIf);
 250                     nextIf.setFalseSuccessor(intermediateBegin);
 251                     intermediateBegin.setNext(this);
 252                     this.setFalseSuccessor(bothFalseBegin);
 253                     nextIf.setTrueSuccessorProbability(probabilityB);
 254                     if (probabilityB == 1.0) {
 255                         this.setTrueSuccessorProbability(0.0);
 256                     } else {
 257                         double newProbability = this.trueSuccessorProbability / (1.0 - probabilityB);
 258                         this.setTrueSuccessorProbability(Math.min(1.0, newProbability));
 259                     }
 260                     return;
 261                 }
 262             }
 263         }
 264 
 265         if (tryEliminateBoxedReferenceEquals(tool)) {
 266             return;
 267         }
 268     }
 269 
 270     private boolean isUnboxedFrom(MetaAccessProvider meta, ValueNode x, ValueNode src) {
 271         if (x == src) {
 272             return true;
 273         } else if (x instanceof UnboxNode) {
 274             return isUnboxedFrom(meta, ((UnboxNode) x).getValue(), src);
 275         } else if (x instanceof PiNode) {
 276             PiNode pi = (PiNode) x;
 277             return isUnboxedFrom(meta, pi.getOriginalNode(), src);
 278         } else if (x instanceof LoadFieldNode) {
 279             LoadFieldNode load = (LoadFieldNode) x;
 280             ResolvedJavaType integerType = meta.lookupJavaType(Integer.class);
 281             if (load.getValue().stamp().javaType(meta).equals(integerType)) {
 282                 return isUnboxedFrom(meta, load.getValue(), src);
 283             } else {
 284                 return false;
 285             }
 286         } else {
 287             return false;
 288         }
 289     }
 290 
 291     /**
 292      * Attempts to replace the following pattern:
 293      *
 294      * <pre>
 295      * Integer x = ...;
 296      * Integer y = ...;
 297      * if ((x == y) || x.equals(y)) { ... }
 298      * </pre>
 299      *
 300      * with:
 301      *
 302      * <pre>
 303      * Integer x = ...;
 304      * Integer y = ...;
 305      * if (x.equals(y)) { ... }
 306      * </pre>
 307      *
 308      * whenever the probability that the reference check will pass is relatively small.
 309      *
 310      * See GR-1315 for more information.
 311      */
 312     private boolean tryEliminateBoxedReferenceEquals(SimplifierTool tool) {
 313         if (!(condition instanceof ObjectEqualsNode)) {
 314             return false;
 315         }
 316 
 317         MetaAccessProvider meta = tool.getMetaAccess();
 318         ObjectEqualsNode equalsCondition = (ObjectEqualsNode) condition;
 319         ValueNode x = equalsCondition.getX();
 320         ValueNode y = equalsCondition.getY();
 321         ResolvedJavaType integerType = meta.lookupJavaType(Integer.class);
 322 
 323         // At least one argument for reference equal must be a boxed primitive.
 324         if (!x.stamp().javaType(meta).equals(integerType) && !y.stamp().javaType(meta).equals(integerType)) {
 325             return false;
 326         }
 327 
 328         // The reference equality check is usually more efficient compared to a boxing check.
 329         // The success of the reference equals must therefore be relatively rare, otherwise it makes
 330         // no sense to eliminate it.
 331         if (getTrueSuccessorProbability() > 0.4) {
 332             return false;
 333         }
 334 
 335         // True branch must be empty.
 336         if (trueSuccessor instanceof BeginNode || trueSuccessor instanceof LoopExitNode) {
 337             if (trueSuccessor.next() instanceof EndNode) {
 338                 // Empty true branch.
 339             } else {
 340                 return false;
 341             }
 342         } else {
 343             return false;
 344         }
 345 
 346         // False branch must only check the unboxed values.
 347         UnboxNode unbox = null;
 348         FixedGuardNode unboxCheck = null;
 349         for (FixedNode node : falseSuccessor.getBlockNodes()) {
 350             if (!(node instanceof BeginNode || node instanceof UnboxNode || node instanceof FixedGuardNode || node instanceof EndNode ||
 351                             node instanceof LoadFieldNode || node instanceof LoopExitNode)) {
 352                 return false;
 353             }
 354             if (node instanceof UnboxNode) {
 355                 if (unbox == null) {
 356                     unbox = (UnboxNode) node;
 357                 } else {
 358                     return false;
 359                 }
 360             }
 361             if (!(node instanceof FixedGuardNode)) {
 362                 continue;
 363             }
 364             FixedGuardNode fixed = (FixedGuardNode) node;
 365             if (!(fixed.condition() instanceof IntegerEqualsNode)) {
 366                 continue;
 367             }
 368             IntegerEqualsNode equals = (IntegerEqualsNode) fixed.condition();
 369             if ((isUnboxedFrom(meta, equals.getX(), x) && isUnboxedFrom(meta, equals.getY(), y)) || (isUnboxedFrom(meta, equals.getX(), y) && isUnboxedFrom(meta, equals.getY(), x))) {
 370                 unboxCheck = fixed;
 371             }
 372         }
 373         if (unbox == null || unboxCheck == null) {
 374             return false;
 375         }
 376 
 377         // Falsify the reference check.
 378         setCondition(graph().addOrUnique(LogicConstantNode.contradiction()));
 379 
 380         return true;
 381     }
 382 
 383     /**
 384      * Try to optimize this as if it were a {@link ConditionalNode}.
 385      */
 386     private boolean conditionalNodeOptimization(SimplifierTool tool) {
 387         if (trueSuccessor().next() instanceof AbstractEndNode && falseSuccessor().next() instanceof AbstractEndNode) {
 388             AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next();
 389             AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next();
 390             if (trueEnd.merge() != falseEnd.merge()) {
 391                 return false;
 392             }
 393             if (!(trueEnd.merge() instanceof MergeNode)) {
 394                 return false;
 395             }
 396             MergeNode merge = (MergeNode) trueEnd.merge();
 397             if (merge.usages().count() != 1 || merge.phis().count() != 1) {
 398                 return false;
 399             }
 400 


< prev index next >