use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class LinearScanIntervalDumper method printInterval.
private static void printInterval(Interval interval, IntervalVisitor visitor) {
Value hint = interval.locationHint(false) != null ? interval.locationHint(false).operand : null;
AllocatableValue operand = interval.operand;
String type = isRegister(operand) ? "fixed" : operand.getValueKind().getPlatformKind().toString();
visitor.visitIntervalStart(interval.splitParent().operand, operand, interval.location(), hint, type);
// print ranges
Range cur = interval.first();
while (!cur.isEndMarker()) {
visitor.visitRange(cur.from, cur.to);
cur = cur.next;
assert cur != null : "range list not closed with range sentinel";
}
// print use positions
int prev = -1;
UsePosList usePosList = interval.usePosList();
for (int i = usePosList.size() - 1; i >= 0; --i) {
assert prev < usePosList.usePos(i) : "use positions not sorted";
visitor.visitUsePos(usePosList.usePos(i), usePosList.registerPriority(i));
prev = usePosList.usePos(i);
}
visitor.visitIntervalEnd(interval.spillState());
}
use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class LinearScanOptimizeSpillPositionPhase method optimizeInterval.
@SuppressWarnings("try")
private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval interval, LIRGenerationResult res) {
if (interval == null || !interval.isSplitParent() || interval.spillState() != SpillState.SpillInDominator) {
return;
}
AbstractBlockBase<?> defBlock = allocator.blockForId(interval.spillDefinitionPos());
AbstractBlockBase<?> spillBlock = null;
Interval firstSpillChild = null;
try (Indent indent = debug.logAndIndent("interval %s (%s)", interval, defBlock)) {
for (Interval splitChild : interval.getSplitChildren()) {
if (isStackSlotValue(splitChild.location())) {
if (firstSpillChild == null || splitChild.from() < firstSpillChild.from()) {
firstSpillChild = splitChild;
} else {
assert firstSpillChild.from() < splitChild.from();
}
// iterate all blocks where the interval has use positions
for (AbstractBlockBase<?> splitBlock : blocksForInterval(splitChild)) {
if (dominates(defBlock, splitBlock)) {
debug.log("Split interval %s, block %s", splitChild, splitBlock);
if (spillBlock == null) {
spillBlock = splitBlock;
} else {
spillBlock = commonDominator(spillBlock, splitBlock);
assert spillBlock != null;
}
}
}
}
}
if (spillBlock == null) {
debug.log("not spill interval found");
// no spill interval
interval.setSpillState(SpillState.StoreAtDefinition);
return;
}
debug.log(DebugContext.VERBOSE_LEVEL, "Spill block candidate (initial): %s", spillBlock);
// move out of loops
if (defBlock.getLoopDepth() < spillBlock.getLoopDepth()) {
spillBlock = moveSpillOutOfLoop(defBlock, spillBlock);
}
debug.log(DebugContext.VERBOSE_LEVEL, "Spill block candidate (after loop optimizaton): %s", spillBlock);
/*
* The spill block is the begin of the first split child (aka the value is on the
* stack).
*
* The problem is that if spill block has more than one predecessor, the values at the
* end of the predecessors might differ. Therefore, we would need a spill move in all
* predecessors. To avoid this we spill in the dominator.
*/
assert firstSpillChild != null;
if (!defBlock.equals(spillBlock) && spillBlock.equals(allocator.blockForId(firstSpillChild.from()))) {
AbstractBlockBase<?> dom = spillBlock.getDominator();
if (debug.isLogEnabled()) {
debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom);
}
spillBlock = dom;
}
if (defBlock.equals(spillBlock)) {
debug.log(DebugContext.VERBOSE_LEVEL, "Definition is the best choice: %s", defBlock);
// definition is the best choice
interval.setSpillState(SpillState.StoreAtDefinition);
return;
}
assert dominates(defBlock, spillBlock);
betterSpillPos.increment(debug);
if (debug.isLogEnabled()) {
debug.log("Better spill position found (Block %s)", spillBlock);
}
if (defBlock.probability() <= spillBlock.probability()) {
debug.log(DebugContext.VERBOSE_LEVEL, "Definition has lower probability %s (%f) is lower than spill block %s (%f)", defBlock, defBlock.probability(), spillBlock, spillBlock.probability());
// better spill block has the same probability -> do nothing
interval.setSpillState(SpillState.StoreAtDefinition);
return;
}
LIRInsertionBuffer insertionBuffer = insertionBuffers[spillBlock.getId()];
if (insertionBuffer == null) {
insertionBuffer = new LIRInsertionBuffer();
insertionBuffers[spillBlock.getId()] = insertionBuffer;
insertionBuffer.init(allocator.getLIR().getLIRforBlock(spillBlock));
}
int spillOpId = allocator.getFirstLirInstructionId(spillBlock);
// insert spill move
AllocatableValue fromLocation = interval.getSplitChildAtOpId(spillOpId, OperandMode.DEF, allocator).location();
AllocatableValue toLocation = LinearScan.canonicalSpillOpr(interval);
LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation);
move.setComment(res, "LSRAOptimizeSpillPos: optimize spill pos");
debug.log(DebugContext.VERBOSE_LEVEL, "Insert spill move %s", move);
move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID);
/*
* We can use the insertion buffer directly because we always insert at position 1.
*/
insertionBuffer.append(1, move);
betterSpillPosWithLowerProbability.increment(debug);
interval.setSpillDefinitionPos(spillOpId);
}
}
use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class ShadowedRegisterValue method forEachComponent.
@Override
public CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) {
RegisterValue newRegister = (RegisterValue) proc.doValue(inst, register, mode, registerFlags);
AllocatableValue newStackSlot = (AllocatableValue) proc.doValue(inst, stackslot, mode, stackslotFlags);
if (register.equals(newRegister) || stackslot.equals(newStackSlot)) {
return this;
}
return new ShadowedRegisterValue(newRegister, newStackSlot);
}
use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class TraceGlobalMoveResolutionPhase method addMappingToRegister.
private static void addMappingToRegister(MoveResolver moveResolver, Value from, RegisterValue register) {
if (isShadowedRegisterValue(from)) {
RegisterValue fromReg = asShadowedRegisterValue(from).getRegister();
AllocatableValue fromStack = asShadowedRegisterValue(from).getStackSlot();
checkAndAddMapping(moveResolver, fromReg, register, fromStack);
} else {
checkAndAddMapping(moveResolver, from, register, null);
}
}
use of jdk.vm.ci.meta.AllocatableValue in project graal by oracle.
the class TraceGlobalMoveResolutionPhase method addMappingToStackSlot.
private static void addMappingToStackSlot(MoveResolver moveResolver, Value from, AllocatableValue stack) {
if (isShadowedRegisterValue(from)) {
ShadowedRegisterValue shadowedFrom = asShadowedRegisterValue(from);
RegisterValue fromReg = shadowedFrom.getRegister();
AllocatableValue fromStack = shadowedFrom.getStackSlot();
if (!fromStack.equals(stack)) {
checkAndAddMapping(moveResolver, fromReg, stack, fromStack);
}
} else {
checkAndAddMapping(moveResolver, from, stack, null);
}
}
Aggregations