< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java

Print this page




 159     void computeLocalLiveSets() {
 160         int liveSize = allocator.liveSetSize();
 161 
 162         intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops());
 163 
 164         try {
 165             final BitSet liveGenScratch = new BitSet(liveSize);
 166             final BitSet liveKillScratch = new BitSet(liveSize);
 167             // iterate all blocks
 168             for (final AbstractBlockBase<?> block : allocator.sortedBlocks()) {
 169                 try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) {
 170 
 171                     liveGenScratch.clear();
 172                     liveKillScratch.clear();
 173 
 174                     ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
 175                     int numInst = instructions.size();
 176 
 177                     ValueConsumer useConsumer = (operand, mode, flags) -> {
 178                         if (isVariable(operand)) {
 179                             int operandNum = allocator.operandNumber(operand);
 180                             if (!liveKillScratch.get(operandNum)) {
 181                                 liveGenScratch.set(operandNum);
 182                                 if (debug.isLogEnabled()) {
 183                                     debug.log("liveGen for operand %d(%s)", operandNum, operand);
 184                                 }
 185                             }
 186                             if (block.getLoop() != null) {
 187                                 intervalInLoop.setBit(operandNum, block.getLoop().getIndex());
 188                             }
 189                         }
 190 
 191                         if (allocator.detailedAsserts) {
 192                             verifyInput(block, liveKillScratch, operand);
 193                         }
 194                     };
 195                     ValueConsumer stateConsumer = (operand, mode, flags) -> {
 196                         if (LinearScan.isVariableOrRegister(operand)) {
 197                             int operandNum = allocator.operandNumber(operand);
 198                             if (!liveKillScratch.get(operandNum)) {
 199                                 liveGenScratch.set(operandNum);
 200                                 if (debug.isLogEnabled()) {
 201                                     debug.log("liveGen in state for operand %d(%s)", operandNum, operand);
 202                                 }
 203                             }
 204                         }
 205                     };
 206                     ValueConsumer defConsumer = (operand, mode, flags) -> {
 207                         if (isVariable(operand)) {
 208                             int varNum = allocator.operandNumber(operand);
 209                             liveKillScratch.set(varNum);
 210                             if (debug.isLogEnabled()) {
 211                                 debug.log("liveKill for operand %d(%s)", varNum, operand);
 212                             }
 213                             if (block.getLoop() != null) {
 214                                 intervalInLoop.setBit(varNum, block.getLoop().getIndex());
 215                             }
 216                         }
 217 
 218                         if (allocator.detailedAsserts) {
 219                             /*
 220                              * Fixed intervals are never live at block boundaries, so they need not
 221                              * be processed in live sets. Process them only in debug mode so that
 222                              * this can be checked
 223                              */
 224                             verifyTemp(liveKillScratch, operand);
 225                         }
 226                     };
 227 
 228                     // iterate all instructions of the block


 251 
 252                     if (debug.isLogEnabled()) {
 253                         debug.log("liveGen  B%d %s", block.getId(), blockSets.liveGen);
 254                         debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill);
 255                     }
 256 
 257                 }
 258             } // end of block iteration
 259         } catch (OutOfMemoryError oom) {
 260             throw new PermanentBailoutException(oom, "Out-of-memory during live set allocation of size %d", liveSize);
 261         }
 262     }
 263 
 264     private void verifyTemp(BitSet liveKill, Value operand) {
 265         /*
 266          * Fixed intervals are never live at block boundaries, so they need not be processed in live
 267          * sets. Process them only in debug mode so that this can be checked
 268          */
 269         if (isRegister(operand)) {
 270             if (allocator.isProcessed(operand)) {
 271                 liveKill.set(allocator.operandNumber(operand));
 272             }
 273         }
 274     }
 275 
 276     private void verifyInput(AbstractBlockBase<?> block, BitSet liveKill, Value operand) {
 277         /*
 278          * Fixed intervals are never live at block boundaries, so they need not be processed in live
 279          * sets. This is checked by these assertions to be sure about it. The entry block may have
 280          * incoming values in registers, which is ok.
 281          */
 282         if (isRegister(operand) && block != allocator.getLIR().getControlFlowGraph().getStartBlock()) {
 283             if (allocator.isProcessed(operand)) {
 284                 assert liveKill.get(allocator.operandNumber(operand)) : "using fixed register " + asRegister(operand) + " that is not defined in this block " + block;
 285             }
 286         }




 287     }
 288 
 289     /**
 290      * Performs a backward dataflow analysis to compute global live sets (i.e.
 291      * {@link BlockData#liveIn} and {@link BlockData#liveOut}) for each block.
 292      */
 293     @SuppressWarnings("try")
 294     protected void computeGlobalLiveSets() {
 295         try (Indent indent = debug.logAndIndent("compute global live sets")) {
 296             int numBlocks = allocator.blockCount();
 297             boolean changeOccurred;
 298             boolean changeOccurredInBlock;
 299             int iterationCount = 0;
 300             BitSet scratch = new BitSet(allocator.liveSetSize()); // scratch set for calculations
 301 
 302             /*
 303              * Perform a backward dataflow analysis to compute liveOut and liveIn for each block.
 304              * The loop is executed until a fixpoint is reached (no changes in an iteration).
 305              */
 306             do {




 159     void computeLocalLiveSets() {
 160         int liveSize = allocator.liveSetSize();
 161 
 162         intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops());
 163 
 164         try {
 165             final BitSet liveGenScratch = new BitSet(liveSize);
 166             final BitSet liveKillScratch = new BitSet(liveSize);
 167             // iterate all blocks
 168             for (final AbstractBlockBase<?> block : allocator.sortedBlocks()) {
 169                 try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) {
 170 
 171                     liveGenScratch.clear();
 172                     liveKillScratch.clear();
 173 
 174                     ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
 175                     int numInst = instructions.size();
 176 
 177                     ValueConsumer useConsumer = (operand, mode, flags) -> {
 178                         if (isVariable(operand)) {
 179                             int operandNum = getOperandNumber(operand);
 180                             if (!liveKillScratch.get(operandNum)) {
 181                                 liveGenScratch.set(operandNum);
 182                                 if (debug.isLogEnabled()) {
 183                                     debug.log("liveGen for operand %d(%s)", operandNum, operand);
 184                                 }
 185                             }
 186                             if (block.getLoop() != null) {
 187                                 intervalInLoop.setBit(operandNum, block.getLoop().getIndex());
 188                             }
 189                         }
 190 
 191                         if (allocator.detailedAsserts) {
 192                             verifyInput(block, liveKillScratch, operand);
 193                         }
 194                     };
 195                     ValueConsumer stateConsumer = (operand, mode, flags) -> {
 196                         if (LinearScan.isVariableOrRegister(operand)) {
 197                             int operandNum = getOperandNumber(operand);
 198                             if (!liveKillScratch.get(operandNum)) {
 199                                 liveGenScratch.set(operandNum);
 200                                 if (debug.isLogEnabled()) {
 201                                     debug.log("liveGen in state for operand %d(%s)", operandNum, operand);
 202                                 }
 203                             }
 204                         }
 205                     };
 206                     ValueConsumer defConsumer = (operand, mode, flags) -> {
 207                         if (isVariable(operand)) {
 208                             int varNum = getOperandNumber(operand);
 209                             liveKillScratch.set(varNum);
 210                             if (debug.isLogEnabled()) {
 211                                 debug.log("liveKill for operand %d(%s)", varNum, operand);
 212                             }
 213                             if (block.getLoop() != null) {
 214                                 intervalInLoop.setBit(varNum, block.getLoop().getIndex());
 215                             }
 216                         }
 217 
 218                         if (allocator.detailedAsserts) {
 219                             /*
 220                              * Fixed intervals are never live at block boundaries, so they need not
 221                              * be processed in live sets. Process them only in debug mode so that
 222                              * this can be checked
 223                              */
 224                             verifyTemp(liveKillScratch, operand);
 225                         }
 226                     };
 227 
 228                     // iterate all instructions of the block


 251 
 252                     if (debug.isLogEnabled()) {
 253                         debug.log("liveGen  B%d %s", block.getId(), blockSets.liveGen);
 254                         debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill);
 255                     }
 256 
 257                 }
 258             } // end of block iteration
 259         } catch (OutOfMemoryError oom) {
 260             throw new PermanentBailoutException(oom, "Out-of-memory during live set allocation of size %d", liveSize);
 261         }
 262     }
 263 
 264     private void verifyTemp(BitSet liveKill, Value operand) {
 265         /*
 266          * Fixed intervals are never live at block boundaries, so they need not be processed in live
 267          * sets. Process them only in debug mode so that this can be checked
 268          */
 269         if (isRegister(operand)) {
 270             if (allocator.isProcessed(operand)) {
 271                 liveKill.set(getOperandNumber(operand));
 272             }
 273         }
 274     }
 275 
 276     private void verifyInput(AbstractBlockBase<?> block, BitSet liveKill, Value operand) {
 277         /*
 278          * Fixed intervals are never live at block boundaries, so they need not be processed in live
 279          * sets. This is checked by these assertions to be sure about it. The entry block may have
 280          * incoming values in registers, which is ok.
 281          */
 282         if (isRegister(operand) && block != allocator.getLIR().getControlFlowGraph().getStartBlock()) {
 283             if (allocator.isProcessed(operand)) {
 284                 assert liveKill.get(getOperandNumber(operand)) : "using fixed register " + asRegister(operand) + " that is not defined in this block " + block;
 285             }
 286         }
 287     }
 288 
 289     protected int getOperandNumber(Value operand) {
 290         return allocator.operandNumber(operand);
 291     }
 292 
 293     /**
 294      * Performs a backward dataflow analysis to compute global live sets (i.e.
 295      * {@link BlockData#liveIn} and {@link BlockData#liveOut}) for each block.
 296      */
 297     @SuppressWarnings("try")
 298     protected void computeGlobalLiveSets() {
 299         try (Indent indent = debug.logAndIndent("compute global live sets")) {
 300             int numBlocks = allocator.blockCount();
 301             boolean changeOccurred;
 302             boolean changeOccurredInBlock;
 303             int iterationCount = 0;
 304             BitSet scratch = new BitSet(allocator.liveSetSize()); // scratch set for calculations
 305 
 306             /*
 307              * Perform a backward dataflow analysis to compute liveOut and liveIn for each block.
 308              * The loop is executed until a fixpoint is reached (no changes in an iteration).
 309              */
 310             do {


< prev index next >