src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java
changeset 48861 47f19ff9903c
parent 48190 25cfedf27edc
child 49451 e06f9607f370
equal deleted inserted replaced
48860:5bce1b7e7800 48861:47f19ff9903c
    24 
    24 
    25 import java.util.ArrayDeque;
    25 import java.util.ArrayDeque;
    26 import java.util.Deque;
    26 import java.util.Deque;
    27 import java.util.List;
    27 import java.util.List;
    28 
    28 
       
    29 import org.graalvm.collections.EconomicMap;
       
    30 import org.graalvm.collections.Equivalence;
       
    31 import org.graalvm.collections.MapCursor;
       
    32 import org.graalvm.collections.Pair;
    29 import org.graalvm.compiler.core.common.cfg.BlockMap;
    33 import org.graalvm.compiler.core.common.cfg.BlockMap;
    30 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
    34 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
    31 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
    35 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
    32 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And;
    36 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And;
    33 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Or;
    37 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Or;
    85 import org.graalvm.compiler.nodes.util.GraphUtil;
    89 import org.graalvm.compiler.nodes.util.GraphUtil;
    86 import org.graalvm.compiler.phases.BasePhase;
    90 import org.graalvm.compiler.phases.BasePhase;
    87 import org.graalvm.compiler.phases.schedule.SchedulePhase;
    91 import org.graalvm.compiler.phases.schedule.SchedulePhase;
    88 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
    92 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
    89 import org.graalvm.compiler.phases.tiers.PhaseContext;
    93 import org.graalvm.compiler.phases.tiers.PhaseContext;
    90 import org.graalvm.util.EconomicMap;
       
    91 import org.graalvm.util.Equivalence;
       
    92 import org.graalvm.util.MapCursor;
       
    93 import org.graalvm.util.Pair;
       
    94 
    94 
    95 import jdk.vm.ci.meta.JavaConstant;
    95 import jdk.vm.ci.meta.JavaConstant;
    96 import jdk.vm.ci.meta.TriState;
    96 import jdk.vm.ci.meta.TriState;
    97 
    97 
    98 public class ConditionalEliminationPhase extends BasePhase<PhaseContext> {
    98 public class ConditionalEliminationPhase extends BasePhase<PhaseContext> {
   122             ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
   122             ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
   123             if (fullSchedule) {
   123             if (fullSchedule) {
   124                 if (moveGuards) {
   124                 if (moveGuards) {
   125                     cfg.visitDominatorTree(new MoveGuardsUpwards(), graph.hasValueProxies());
   125                     cfg.visitDominatorTree(new MoveGuardsUpwards(), graph.hasValueProxies());
   126                 }
   126                 }
   127                 SchedulePhase.run(graph, SchedulingStrategy.EARLIEST, cfg);
   127                 try (DebugContext.Scope scheduleScope = graph.getDebug().scope(SchedulePhase.class)) {
       
   128                     SchedulePhase.run(graph, SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER, cfg);
       
   129                 } catch (Throwable t) {
       
   130                     throw graph.getDebug().handle(t);
       
   131                 }
   128                 ScheduleResult r = graph.getLastSchedule();
   132                 ScheduleResult r = graph.getLastSchedule();
   129                 blockToNodes = r.getBlockToNodesMap();
   133                 blockToNodes = r.getBlockToNodesMap();
   130                 nodeToBlock = r.getNodeToBlockMap();
   134                 nodeToBlock = r.getNodeToBlockMap();
   131             } else {
   135             } else {
   132                 nodeToBlock = cfg.getNodeToBlock();
   136                 nodeToBlock = cfg.getNodeToBlock();
   660                      * be moved up if we're sure there's no schedule dependence. For now limit it to
   664                      * be moved up if we're sure there's no schedule dependence. For now limit it to
   661                      * the original node and constants.
   665                      * the original node and constants.
   662                      */
   666                      */
   663                     InputFilter v = new InputFilter(original);
   667                     InputFilter v = new InputFilter(original);
   664                     thisGuard.getCondition().applyInputs(v);
   668                     thisGuard.getCondition().applyInputs(v);
   665                     if (v.ok && foldGuard(thisGuard, pendingGuard, newStamp, rewireGuardFunction)) {
   669                     if (v.ok && foldGuard(thisGuard, pendingGuard, result.toBoolean(), newStamp, rewireGuardFunction)) {
   666                         return true;
   670                         return true;
   667                     }
   671                     }
   668                 }
   672                 }
   669             }
   673             }
   670             return false;
   674             return false;
   671         }
   675         }
   672 
   676 
   673         protected boolean foldGuard(DeoptimizingGuard thisGuard, DeoptimizingGuard otherGuard, Stamp guardedValueStamp, GuardRewirer rewireGuardFunction) {
   677         protected boolean foldGuard(DeoptimizingGuard thisGuard, DeoptimizingGuard otherGuard, boolean outcome, Stamp guardedValueStamp, GuardRewirer rewireGuardFunction) {
   674             if (otherGuard.getAction() == thisGuard.getAction() && otherGuard.getSpeculation() == thisGuard.getSpeculation()) {
   678             if (otherGuard.getAction() == thisGuard.getAction() && otherGuard.getSpeculation() == thisGuard.getSpeculation()) {
   675                 LogicNode condition = (LogicNode) thisGuard.getCondition().copyWithInputs();
   679                 LogicNode condition = (LogicNode) thisGuard.getCondition().copyWithInputs();
       
   680                 /*
       
   681                  * We have ...; guard(C1); guard(C2);...
       
   682                  *
       
   683                  * Where the first guard is `otherGuard` and the second one `thisGuard`.
       
   684                  *
       
   685                  * Depending on `outcome`, we have C2 => C1 or C2 => !C1.
       
   686                  *
       
   687                  * - If C2 => C1, `mustDeopt` below is false and we transform to ...; guard(C2); ...
       
   688                  *
       
   689                  * - If C2 => !C1, `mustDeopt` is true and we transform to ..; guard(C1); deopt;
       
   690                  */
   676                 GuardRewirer rewirer = (guard, result, innerGuardedValueStamp, newInput) -> {
   691                 GuardRewirer rewirer = (guard, result, innerGuardedValueStamp, newInput) -> {
   677                     if (rewireGuardFunction.rewire(guard, result, innerGuardedValueStamp, newInput)) {
   692                     // `result` is `outcome`, `guard` is `otherGuard`
   678                         otherGuard.setCondition(condition, thisGuard.isNegated());
   693                     boolean mustDeopt = result == otherGuard.isNegated();
       
   694                     if (rewireGuardFunction.rewire(guard, mustDeopt == thisGuard.isNegated(), innerGuardedValueStamp, newInput)) {
       
   695                         if (!mustDeopt) {
       
   696                             otherGuard.setCondition(condition, thisGuard.isNegated());
       
   697                         }
   679                         return true;
   698                         return true;
   680                     }
   699                     }
   681                     condition.safeDelete();
   700                     condition.safeDelete();
   682                     return false;
   701                     return false;
   683                 };
   702                 };
   684                 // Move the later test up
   703                 // Move the later test up
   685                 return rewireGuards(otherGuard, !thisGuard.isNegated(), null, guardedValueStamp, rewirer);
   704                 return rewireGuards(otherGuard, outcome, null, guardedValueStamp, rewirer);
   686             }
   705             }
   687             return false;
   706             return false;
   688         }
   707         }
   689 
   708 
   690         protected void registerCondition(LogicNode condition, boolean negated, GuardingNode guard) {
   709         protected void registerCondition(LogicNode condition, boolean negated, GuardingNode guard) {