hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/RegisterVerifier.java
changeset 46640 70bdce04c59b
parent 46344 694c102fd8ed
equal deleted inserted replaced
46638:3c5c50af29a7 46640:70bdce04c59b
    28 import java.util.ArrayList;
    28 import java.util.ArrayList;
    29 import java.util.EnumSet;
    29 import java.util.EnumSet;
    30 
    30 
    31 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
    31 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
    32 import org.graalvm.compiler.core.common.cfg.BlockMap;
    32 import org.graalvm.compiler.core.common.cfg.BlockMap;
    33 import org.graalvm.compiler.debug.Debug;
    33 import org.graalvm.compiler.debug.DebugContext;
    34 import org.graalvm.compiler.debug.Debug.Scope;
       
    35 import org.graalvm.compiler.debug.GraalError;
    34 import org.graalvm.compiler.debug.GraalError;
    36 import org.graalvm.compiler.debug.Indent;
    35 import org.graalvm.compiler.debug.Indent;
    37 import org.graalvm.compiler.lir.InstructionValueConsumer;
    36 import org.graalvm.compiler.lir.InstructionValueConsumer;
    38 import org.graalvm.compiler.lir.LIRInstruction;
    37 import org.graalvm.compiler.lir.LIRInstruction;
    39 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
    38 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
    82 
    81 
    83     }
    82     }
    84 
    83 
    85     @SuppressWarnings("try")
    84     @SuppressWarnings("try")
    86     void verify(AbstractBlockBase<?> start) {
    85     void verify(AbstractBlockBase<?> start) {
    87         try (Scope s = Debug.scope("RegisterVerifier")) {
    86         DebugContext debug = allocator.getDebug();
       
    87         try (DebugContext.Scope s = debug.scope("RegisterVerifier")) {
    88             // setup input registers (method arguments) for first block
    88             // setup input registers (method arguments) for first block
    89             Interval[] inputState = new Interval[stateSize()];
    89             Interval[] inputState = new Interval[stateSize()];
    90             setStateForBlock(start, inputState);
    90             setStateForBlock(start, inputState);
    91             addToWorkList(start);
    91             addToWorkList(start);
    92 
    92 
   100         }
   100         }
   101     }
   101     }
   102 
   102 
   103     @SuppressWarnings("try")
   103     @SuppressWarnings("try")
   104     private void processBlock(AbstractBlockBase<?> block) {
   104     private void processBlock(AbstractBlockBase<?> block) {
   105         try (Indent indent = Debug.logAndIndent("processBlock B%d", block.getId())) {
   105         DebugContext debug = allocator.getDebug();
       
   106         try (Indent indent = debug.logAndIndent("processBlock B%d", block.getId())) {
   106             // must copy state because it is modified
   107             // must copy state because it is modified
   107             Interval[] inputState = copy(stateForBlock(block));
   108             Interval[] inputState = copy(stateForBlock(block));
   108 
   109 
   109             try (Indent indent2 = Debug.logAndIndent("Input-State of intervals:")) {
   110             try (Indent indent2 = debug.logAndIndent("Input-State of intervals:")) {
   110                 printState(inputState);
   111                 printState(inputState);
   111             }
   112             }
   112 
   113 
   113             // process all operations of the block
   114             // process all operations of the block
   114             processOperations(block, inputState);
   115             processOperations(block, inputState);
   115 
   116 
   116             try (Indent indent2 = Debug.logAndIndent("Output-State of intervals:")) {
   117             try (Indent indent2 = debug.logAndIndent("Output-State of intervals:")) {
   117                 printState(inputState);
   118                 printState(inputState);
   118             }
   119             }
   119 
   120 
   120             // iterate all successors
   121             // iterate all successors
   121             for (AbstractBlockBase<?> succ : block.getSuccessors()) {
   122             for (AbstractBlockBase<?> succ : block.getSuccessors()) {
   123             }
   124             }
   124         }
   125         }
   125     }
   126     }
   126 
   127 
   127     protected void printState(Interval[] inputState) {
   128     protected void printState(Interval[] inputState) {
       
   129         DebugContext debug = allocator.getDebug();
   128         for (int i = 0; i < stateSize(); i++) {
   130         for (int i = 0; i < stateSize(); i++) {
   129             Register reg = allocator.getRegisters().get(i);
   131             Register reg = allocator.getRegisters().get(i);
   130             assert reg.number == i;
   132             assert reg.number == i;
   131             if (inputState[i] != null) {
   133             if (inputState[i] != null) {
   132                 Debug.log(" %6s %4d  --  %s", reg, inputState[i].operandNumber, inputState[i]);
   134                 debug.log(" %6s %4d  --  %s", reg, inputState[i].operandNumber, inputState[i]);
   133             } else {
   135             } else {
   134                 Debug.log(" %6s   __", reg);
   136                 debug.log(" %6s   __", reg);
   135             }
   137             }
   136         }
   138         }
   137     }
   139     }
   138 
   140 
   139     private void processSuccessor(AbstractBlockBase<?> block, Interval[] inputState) {
   141     private void processSuccessor(AbstractBlockBase<?> block, Interval[] inputState) {
       
   142         DebugContext debug = allocator.getDebug();
   140         Interval[] savedState = stateForBlock(block);
   143         Interval[] savedState = stateForBlock(block);
   141 
   144 
   142         if (savedState != null) {
   145         if (savedState != null) {
   143             // this block was already processed before.
   146             // this block was already processed before.
   144             // check if new inputState is consistent with savedState
   147             // check if new inputState is consistent with savedState
   153                         // register was valid. when the register was already invalid,
   156                         // register was valid. when the register was already invalid,
   154                         // then the old calculation was correct.
   157                         // then the old calculation was correct.
   155                         savedStateCorrect = false;
   158                         savedStateCorrect = false;
   156                         savedState[i] = null;
   159                         savedState[i] = null;
   157 
   160 
   158                         Debug.log("processSuccessor B%d: invalidating slot %d", block.getId(), i);
   161                         debug.log("processSuccessor B%d: invalidating slot %d", block.getId(), i);
   159                     }
   162                     }
   160                 }
   163                 }
   161             }
   164             }
   162 
   165 
   163             if (savedStateCorrect) {
   166             if (savedStateCorrect) {
   164                 // already processed block with correct inputState
   167                 // already processed block with correct inputState
   165                 Debug.log("processSuccessor B%d: previous visit already correct", block.getId());
   168                 debug.log("processSuccessor B%d: previous visit already correct", block.getId());
   166             } else {
   169             } else {
   167                 // must re-visit this block
   170                 // must re-visit this block
   168                 Debug.log("processSuccessor B%d: must re-visit because input state changed", block.getId());
   171                 debug.log("processSuccessor B%d: must re-visit because input state changed", block.getId());
   169                 addToWorkList(block);
   172                 addToWorkList(block);
   170             }
   173             }
   171 
   174 
   172         } else {
   175         } else {
   173             // block was not processed before, so set initial inputState
   176             // block was not processed before, so set initial inputState
   174             Debug.log("processSuccessor B%d: initial visit", block.getId());
   177             debug.log("processSuccessor B%d: initial visit", block.getId());
   175 
   178 
   176             setStateForBlock(block, copy(inputState));
   179             setStateForBlock(block, copy(inputState));
   177             addToWorkList(block);
   180             addToWorkList(block);
   178         }
   181         }
   179     }
   182     }
   180 
   183 
   181     static Interval[] copy(Interval[] inputState) {
   184     static Interval[] copy(Interval[] inputState) {
   182         return inputState.clone();
   185         return inputState.clone();
   183     }
   186     }
   184 
   187 
   185     static void statePut(Interval[] inputState, Value location, Interval interval) {
   188     static void statePut(DebugContext debug, Interval[] inputState, Value location, Interval interval) {
   186         if (location != null && isRegister(location)) {
   189         if (location != null && isRegister(location)) {
   187             Register reg = asRegister(location);
   190             Register reg = asRegister(location);
   188             int regNum = reg.number;
   191             int regNum = reg.number;
   189             if (interval != null) {
   192             if (interval != null) {
   190                 Debug.log("%s = %s", reg, interval.operand);
   193                 debug.log("%s = %s", reg, interval.operand);
   191             } else if (inputState[regNum] != null) {
   194             } else if (inputState[regNum] != null) {
   192                 Debug.log("%s = null", reg);
   195                 debug.log("%s = null", reg);
   193             }
   196             }
   194 
   197 
   195             inputState[regNum] = interval;
   198             inputState[regNum] = interval;
   196         }
   199         }
   197     }
   200     }
   207         return true;
   210         return true;
   208     }
   211     }
   209 
   212 
   210     void processOperations(AbstractBlockBase<?> block, final Interval[] inputState) {
   213     void processOperations(AbstractBlockBase<?> block, final Interval[] inputState) {
   211         ArrayList<LIRInstruction> ops = allocator.getLIR().getLIRforBlock(block);
   214         ArrayList<LIRInstruction> ops = allocator.getLIR().getLIRforBlock(block);
       
   215         DebugContext debug = allocator.getDebug();
   212         InstructionValueConsumer useConsumer = new InstructionValueConsumer() {
   216         InstructionValueConsumer useConsumer = new InstructionValueConsumer() {
   213 
   217 
   214             @Override
   218             @Override
   215             public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
   219             public void visitValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
   216                 // we skip spill moves inserted by the spill position optimization
   220                 // we skip spill moves inserted by the spill position optimization
   230                 Interval interval = intervalAt(operand);
   234                 Interval interval = intervalAt(operand);
   231                 if (op.id() != -1) {
   235                 if (op.id() != -1) {
   232                     interval = interval.getSplitChildAtOpId(op.id(), mode, allocator);
   236                     interval = interval.getSplitChildAtOpId(op.id(), mode, allocator);
   233                 }
   237                 }
   234 
   238 
   235                 statePut(inputState, interval.location(), interval.splitParent());
   239                 statePut(debug, inputState, interval.location(), interval.splitParent());
   236             }
   240             }
   237         };
   241         };
   238 
   242 
   239         // visit all instructions of the block
   243         // visit all instructions of the block
   240         for (int i = 0; i < ops.size(); i++) {
   244         for (int i = 0; i < ops.size(); i++) {
   241             final LIRInstruction op = ops.get(i);
   245             final LIRInstruction op = ops.get(i);
   242 
   246 
   243             if (Debug.isLogEnabled()) {
   247             if (debug.isLogEnabled()) {
   244                 Debug.log("%s", op.toStringWithIdPrefix());
   248                 debug.log("%s", op.toStringWithIdPrefix());
   245             }
   249             }
   246 
   250 
   247             // check if input operands are correct
   251             // check if input operands are correct
   248             op.visitEachInput(useConsumer);
   252             op.visitEachInput(useConsumer);
   249             // invalidate all caller save registers at calls
   253             // invalidate all caller save registers at calls
   250             if (op.destroysCallerSavedRegisters()) {
   254             if (op.destroysCallerSavedRegisters()) {
   251                 for (Register r : allocator.getRegisterAllocationConfig().getRegisterConfig().getCallerSaveRegisters()) {
   255                 for (Register r : allocator.getRegisterAllocationConfig().getRegisterConfig().getCallerSaveRegisters()) {
   252                     statePut(inputState, r.asValue(), null);
   256                     statePut(debug, inputState, r.asValue(), null);
   253                 }
   257                 }
   254             }
   258             }
   255             op.visitEachAlive(useConsumer);
   259             op.visitEachAlive(useConsumer);
   256             // set temp operands (some operations use temp operands also as output operands, so
   260             // set temp operands (some operations use temp operands also as output operands, so
   257             // can't set them null)
   261             // can't set them null)