src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAssignLocationsPhase.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra

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

Print this page




   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  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.lir.alloc.lsra;
  24 
  25 import static org.graalvm.compiler.core.common.GraalOptions.DetailedAsserts;
  26 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
  27 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
  28 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
  29 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;
  30 import static jdk.vm.ci.code.ValueUtil.isIllegal;
  31 

  32 import java.util.Collections;
  33 import java.util.EnumSet;
  34 import java.util.List;
  35 
  36 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
  37 import org.graalvm.compiler.debug.Debug;
  38 import org.graalvm.compiler.debug.Indent;
  39 import org.graalvm.compiler.lir.ConstantValue;
  40 import org.graalvm.compiler.lir.InstructionValueProcedure;
  41 import org.graalvm.compiler.lir.LIRFrameState;
  42 import org.graalvm.compiler.lir.LIRInstruction;
  43 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
  44 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
  45 import org.graalvm.compiler.lir.StandardOp;
  46 import org.graalvm.compiler.lir.StandardOp.MoveOp;
  47 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
  48 import org.graalvm.compiler.lir.Variable;
  49 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
  50 import org.graalvm.compiler.lir.phases.AllocationPhase;
  51 
  52 import jdk.vm.ci.code.TargetDescription;
  53 import jdk.vm.ci.meta.AllocatableValue;
  54 import jdk.vm.ci.meta.Value;


  66 
  67     @Override
  68     protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
  69         assignLocations();
  70     }
  71 
  72     /**
  73      * Assigns the allocated location for an LIR instruction operand back into the instruction.
  74      *
  75      * @param op current {@link LIRInstruction}
  76      * @param operand an LIR instruction operand
  77      * @param mode the usage mode for {@code operand} by the instruction
  78      * @return the location assigned for the operand
  79      */
  80     protected Value colorLirOperand(LIRInstruction op, Variable operand, OperandMode mode) {
  81         int opId = op.id();
  82         Interval interval = allocator.intervalFor(operand);
  83         assert interval != null : "interval must exist";
  84 
  85         if (opId != -1) {
  86             if (DetailedAsserts.getValue()) {
  87                 AbstractBlockBase<?> block = allocator.blockForId(opId);
  88                 if (block.getSuccessorCount() <= 1 && opId == allocator.getLastLirInstructionId(block)) {
  89                     /*
  90                      * Check if spill moves could have been appended at the end of this block, but
  91                      * before the branch instruction. So the split child information for this branch
  92                      * would be incorrect.
  93                      */
  94                     LIRInstruction instr = allocator.getLIR().getLIRforBlock(block).get(allocator.getLIR().getLIRforBlock(block).size() - 1);
  95                     if (instr instanceof StandardOp.JumpOp) {
  96                         if (allocator.getBlockData(block).liveOut.get(allocator.operandNumber(operand))) {
  97                             assert false : String.format(
  98                                             "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow) block=%s, instruction=%s, operand=%s",
  99                                             block, instr, operand);
 100                         }
 101                     }
 102                 }
 103             }
 104 
 105             /*
 106              * Operands are not changed when an interval is split during allocation, so search the


 145                     tempOpId = allocator.getFirstLirInstructionId(block.getSuccessors()[0]);
 146                     mode = OperandMode.DEF;
 147                 }
 148             }
 149         }
 150 
 151         /*
 152          * Get current location of operand. The operand must be live because debug information is
 153          * considered when building the intervals if the interval is not live, colorLirOperand will
 154          * cause an assert on failure.
 155          */
 156         Value result = colorLirOperand(op, (Variable) operand, mode);
 157         assert !allocator.hasCall(tempOpId) || isStackSlotValue(result) || isJavaConstant(result) || !allocator.isCallerSave(result) : "cannot have caller-save register operands at calls";
 158         return result;
 159     }
 160 
 161     private void computeDebugInfo(final LIRInstruction op, LIRFrameState info) {
 162         info.forEachState(op, this::debugInfoProcedure);
 163     }
 164 
 165     private void assignLocations(List<LIRInstruction> instructions) {
 166         int numInst = instructions.size();
 167         boolean hasDead = false;
 168 
 169         for (int j = 0; j < numInst; j++) {
 170             final LIRInstruction op = instructions.get(j);
 171             if (op == null) {
 172                 /*
 173                  * this can happen when spill-moves are removed in eliminateSpillMoves
 174                  */
 175                 hasDead = true;
 176             } else if (assignLocations(op)) {
 177                 instructions.set(j, null);
 178                 hasDead = true;
 179             }
 180         }
 181 
 182         if (hasDead) {
 183             // Remove null values from the list.
 184             instructions.removeAll(Collections.singleton(null));
 185         }




   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  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.lir.alloc.lsra;
  24 
  25 import static jdk.vm.ci.code.ValueUtil.isIllegal;
  26 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
  27 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
  28 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
  29 import static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot;

  30 
  31 import java.util.ArrayList;
  32 import java.util.Collections;
  33 import java.util.EnumSet;

  34 
  35 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
  36 import org.graalvm.compiler.debug.Debug;
  37 import org.graalvm.compiler.debug.Indent;
  38 import org.graalvm.compiler.lir.ConstantValue;
  39 import org.graalvm.compiler.lir.InstructionValueProcedure;
  40 import org.graalvm.compiler.lir.LIRFrameState;
  41 import org.graalvm.compiler.lir.LIRInstruction;
  42 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
  43 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
  44 import org.graalvm.compiler.lir.StandardOp;
  45 import org.graalvm.compiler.lir.StandardOp.MoveOp;
  46 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
  47 import org.graalvm.compiler.lir.Variable;
  48 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
  49 import org.graalvm.compiler.lir.phases.AllocationPhase;
  50 
  51 import jdk.vm.ci.code.TargetDescription;
  52 import jdk.vm.ci.meta.AllocatableValue;
  53 import jdk.vm.ci.meta.Value;


  65 
  66     @Override
  67     protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
  68         assignLocations();
  69     }
  70 
  71     /**
  72      * Assigns the allocated location for an LIR instruction operand back into the instruction.
  73      *
  74      * @param op current {@link LIRInstruction}
  75      * @param operand an LIR instruction operand
  76      * @param mode the usage mode for {@code operand} by the instruction
  77      * @return the location assigned for the operand
  78      */
  79     protected Value colorLirOperand(LIRInstruction op, Variable operand, OperandMode mode) {
  80         int opId = op.id();
  81         Interval interval = allocator.intervalFor(operand);
  82         assert interval != null : "interval must exist";
  83 
  84         if (opId != -1) {
  85             if (allocator.detailedAsserts) {
  86                 AbstractBlockBase<?> block = allocator.blockForId(opId);
  87                 if (block.getSuccessorCount() <= 1 && opId == allocator.getLastLirInstructionId(block)) {
  88                     /*
  89                      * Check if spill moves could have been appended at the end of this block, but
  90                      * before the branch instruction. So the split child information for this branch
  91                      * would be incorrect.
  92                      */
  93                     LIRInstruction instr = allocator.getLIR().getLIRforBlock(block).get(allocator.getLIR().getLIRforBlock(block).size() - 1);
  94                     if (instr instanceof StandardOp.JumpOp) {
  95                         if (allocator.getBlockData(block).liveOut.get(allocator.operandNumber(operand))) {
  96                             assert false : String.format(
  97                                             "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow) block=%s, instruction=%s, operand=%s",
  98                                             block, instr, operand);
  99                         }
 100                     }
 101                 }
 102             }
 103 
 104             /*
 105              * Operands are not changed when an interval is split during allocation, so search the


 144                     tempOpId = allocator.getFirstLirInstructionId(block.getSuccessors()[0]);
 145                     mode = OperandMode.DEF;
 146                 }
 147             }
 148         }
 149 
 150         /*
 151          * Get current location of operand. The operand must be live because debug information is
 152          * considered when building the intervals if the interval is not live, colorLirOperand will
 153          * cause an assert on failure.
 154          */
 155         Value result = colorLirOperand(op, (Variable) operand, mode);
 156         assert !allocator.hasCall(tempOpId) || isStackSlotValue(result) || isJavaConstant(result) || !allocator.isCallerSave(result) : "cannot have caller-save register operands at calls";
 157         return result;
 158     }
 159 
 160     private void computeDebugInfo(final LIRInstruction op, LIRFrameState info) {
 161         info.forEachState(op, this::debugInfoProcedure);
 162     }
 163 
 164     private void assignLocations(ArrayList<LIRInstruction> instructions) {
 165         int numInst = instructions.size();
 166         boolean hasDead = false;
 167 
 168         for (int j = 0; j < numInst; j++) {
 169             final LIRInstruction op = instructions.get(j);
 170             if (op == null) {
 171                 /*
 172                  * this can happen when spill-moves are removed in eliminateSpillMoves
 173                  */
 174                 hasDead = true;
 175             } else if (assignLocations(op)) {
 176                 instructions.set(j, null);
 177                 hasDead = true;
 178             }
 179         }
 180 
 181         if (hasDead) {
 182             // Remove null values from the list.
 183             instructions.removeAll(Collections.singleton(null));
 184         }


src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanAssignLocationsPhase.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File