src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Fri Jul 7 09:30:40 2017
--- new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Fri Jul 7 09:30:40 2017
*** 39,50 ****
--- 39,49 ----
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.PermanentBailoutException;
import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
import org.graalvm.compiler.core.common.util.BitMap2D;
! import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.Debug.Scope;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.Indent;
import org.graalvm.compiler.lir.InstructionValueConsumer;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
*** 71,92 ****
--- 70,93 ----
import jdk.vm.ci.meta.ValueKind;
public class LinearScanLifetimeAnalysisPhase extends LinearScanAllocationPhase {
protected final LinearScan allocator;
+ protected final DebugContext debug;
/**
* @param linearScan
*/
protected LinearScanLifetimeAnalysisPhase(LinearScan linearScan) {
allocator = linearScan;
+ debug = allocator.getDebug();
}
@Override
protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
numberInstructions();
! Debug.dump(Debug.VERBOSE_LEVEL, lirGenRes.getLIR(), "Before register allocation");
! debug.dump(DebugContext.VERBOSE_LEVEL, lirGenRes.getLIR(), "Before register allocation");
computeLocalLiveSets();
computeGlobalLiveSets();
buildIntervals(DetailedAsserts.getValue(allocator.getOptions()));
}
*** 158,168 ****
--- 159,169 ----
intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops());
// iterate all blocks
for (final AbstractBlockBase<?> block : allocator.sortedBlocks()) {
! try (Indent indent = Debug.logAndIndent("compute local live sets for block %s", block)) {
! try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) {
final BitSet liveGen = new BitSet(liveSize);
final BitSet liveKill = new BitSet(liveSize);
ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
*** 171,182 ****
--- 172,183 ----
ValueConsumer useConsumer = (operand, mode, flags) -> {
if (isVariable(operand)) {
int operandNum = allocator.operandNumber(operand);
if (!liveKill.get(operandNum)) {
liveGen.set(operandNum);
! if (Debug.isLogEnabled()) {
! Debug.log("liveGen for operand %d(%s)", operandNum, operand);
! if (debug.isLogEnabled()) {
! debug.log("liveGen for operand %d(%s)", operandNum, operand);
}
}
if (block.getLoop() != null) {
intervalInLoop.setBit(operandNum, block.getLoop().getIndex());
}
*** 189,210 ****
--- 190,211 ----
ValueConsumer stateConsumer = (operand, mode, flags) -> {
if (LinearScan.isVariableOrRegister(operand)) {
int operandNum = allocator.operandNumber(operand);
if (!liveKill.get(operandNum)) {
liveGen.set(operandNum);
! if (Debug.isLogEnabled()) {
! Debug.log("liveGen in state for operand %d(%s)", operandNum, operand);
! if (debug.isLogEnabled()) {
! debug.log("liveGen in state for operand %d(%s)", operandNum, operand);
}
}
}
};
ValueConsumer defConsumer = (operand, mode, flags) -> {
if (isVariable(operand)) {
int varNum = allocator.operandNumber(operand);
liveKill.set(varNum);
! if (Debug.isLogEnabled()) {
! Debug.log("liveKill for operand %d(%s)", varNum, operand);
! if (debug.isLogEnabled()) {
! debug.log("liveKill for operand %d(%s)", varNum, operand);
}
if (block.getLoop() != null) {
intervalInLoop.setBit(varNum, block.getLoop().getIndex());
}
}
*** 221,231 ****
--- 222,232 ----
// iterate all instructions of the block
for (int j = 0; j < numInst; j++) {
final LIRInstruction op = instructions.get(j);
! try (Indent indent2 = Debug.logAndIndent("handle op %d: %s", op.id(), op)) {
! try (Indent indent2 = debug.logAndIndent("handle op %d: %s", op.id(), op)) {
op.visitEachInput(useConsumer);
op.visitEachAlive(useConsumer);
/*
* Add uses of live locals from interpreter's point of view for proper debug
* information generation.
*** 240,252 ****
--- 241,253 ----
blockSets.liveGen = liveGen;
blockSets.liveKill = liveKill;
blockSets.liveIn = new BitSet(liveSize);
blockSets.liveOut = new BitSet(liveSize);
! if (Debug.isLogEnabled()) {
! Debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen);
! Debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill);
! if (debug.isLogEnabled()) {
! debug.log("liveGen B%d %s", block.getId(), blockSets.liveGen);
! debug.log("liveKill B%d %s", block.getId(), blockSets.liveKill);
}
}
} // end of block iteration
}
*** 280,290 ****
--- 281,291 ----
* Performs a backward dataflow analysis to compute global live sets (i.e.
* {@link BlockData#liveIn} and {@link BlockData#liveOut}) for each block.
*/
@SuppressWarnings("try")
protected void computeGlobalLiveSets() {
! try (Indent indent = Debug.logAndIndent("compute global live sets")) {
! try (Indent indent = debug.logAndIndent("compute global live sets")) {
int numBlocks = allocator.blockCount();
boolean changeOccurred;
boolean changeOccurredInBlock;
int iterationCount = 0;
BitSet liveOut = new BitSet(allocator.liveSetSize()); // scratch set for calculations
*** 294,304 ****
--- 295,305 ----
* The loop is executed until a fixpoint is reached (no changes in an iteration).
*/
do {
changeOccurred = false;
! try (Indent indent2 = Debug.logAndIndent("new iteration %d", iterationCount)) {
! try (Indent indent2 = debug.logAndIndent("new iteration %d", iterationCount)) {
// iterate all blocks in reverse order
for (int i = numBlocks - 1; i >= 0; i--) {
AbstractBlockBase<?> block = allocator.blockAt(i);
BlockData blockSets = allocator.getBlockData(block);
*** 344,355 ****
--- 345,356 ----
liveIn.clear();
liveIn.or(blockSets.liveOut);
liveIn.andNot(blockSets.liveKill);
liveIn.or(blockSets.liveGen);
! if (Debug.isLogEnabled()) {
! Debug.log("block %d: livein = %s, liveout = %s", block.getId(), liveIn, blockSets.liveOut);
! if (debug.isLogEnabled()) {
! debug.log("block %d: livein = %s, liveout = %s", block.getId(), liveIn, blockSets.liveOut);
}
}
}
iterationCount++;
*** 379,400 ****
--- 380,401 ----
}
}
@SuppressWarnings("try")
protected void reportFailure(int numBlocks) {
! try (Scope s = Debug.forceLog()) {
! try (Indent indent = Debug.logAndIndent("report failure")) {
! try (DebugContext.Scope s = debug.forceLog()) {
! try (Indent indent = debug.logAndIndent("report failure")) {
BitSet startBlockLiveIn = allocator.getBlockData(allocator.getLIR().getControlFlowGraph().getStartBlock()).liveIn;
! try (Indent indent2 = Debug.logAndIndent("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):")) {
! try (Indent indent2 = debug.logAndIndent("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined):")) {
for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) {
Interval interval = allocator.intervalFor(operandNum);
if (interval != null) {
Value operand = interval.operand;
! Debug.log("var %d; operand=%s; node=%s", operandNum, operand, getSourceForOperandFromDebugContext(operand));
! debug.log("var %d; operand=%s; node=%s", operandNum, operand, getSourceForOperandFromDebugContext(debug, operand));
} else {
! Debug.log("var %d; missing operand", operandNum);
! debug.log("var %d; missing operand", operandNum);
}
}
}
// print some additional information to simplify debugging
*** 402,436 ****
--- 403,437 ----
Interval interval = allocator.intervalFor(operandNum);
Value operand = null;
Object valueForOperandFromDebugContext = null;
if (interval != null) {
operand = interval.operand;
! valueForOperandFromDebugContext = getSourceForOperandFromDebugContext(debug, operand);
}
! try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) {
! try (Indent indent2 = debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) {
ArrayDeque<AbstractBlockBase<?>> definedIn = new ArrayDeque<>();
EconomicSet<AbstractBlockBase<?>> usedIn = EconomicSet.create(Equivalence.IDENTITY);
for (AbstractBlockBase<?> block : allocator.sortedBlocks()) {
if (allocator.getBlockData(block).liveGen.get(operandNum)) {
usedIn.add(block);
! try (Indent indent3 = Debug.logAndIndent("used in block B%d", block.getId())) {
! try (Indent indent3 = debug.logAndIndent("used in block B%d", block.getId())) {
for (LIRInstruction ins : allocator.getLIR().getLIRforBlock(block)) {
! try (Indent indent4 = Debug.logAndIndent("%d: %s", ins.id(), ins)) {
! try (Indent indent4 = debug.logAndIndent("%d: %s", ins.id(), ins)) {
ins.forEachState((liveStateOperand, mode, flags) -> {
! Debug.log("operand=%s", liveStateOperand);
! debug.log("operand=%s", liveStateOperand);
return liveStateOperand;
});
}
}
}
}
if (allocator.getBlockData(block).liveKill.get(operandNum)) {
definedIn.add(block);
! try (Indent indent3 = Debug.logAndIndent("defined in block B%d", block.getId())) {
! try (Indent indent3 = debug.logAndIndent("defined in block B%d", block.getId())) {
for (LIRInstruction ins : allocator.getLIR().getLIRforBlock(block)) {
! Debug.log("%d: %s", ins.id(), ins);
! debug.log("%d: %s", ins.id(), ins);
}
}
}
}
*** 449,468 ****
--- 450,469 ----
definedIn.add(successor);
}
}
}
}
! try (Indent indent3 = Debug.logAndIndent("**** offending usages are in: ")) {
! try (Indent indent3 = debug.logAndIndent("**** offending usages are in: ")) {
for (AbstractBlockBase<?> block : usedIn) {
! Debug.log("B%d", block.getId());
! debug.log("B%d", block.getId());
}
}
}
}
}
} catch (Throwable e) {
! throw Debug.handle(e);
! throw debug.handle(e);
}
}
protected void verifyLiveness() {
/*
*** 491,502 ****
--- 492,503 ----
interval.addRange(from, to);
// Register use position at even instruction id.
interval.addUsePos(to & ~1, registerPriority, detailedAsserts);
! if (Debug.isLogEnabled()) {
! Debug.log("add use: %s, from %d to %d (%s)", interval, from, to, registerPriority.name());
! if (debug.isLogEnabled()) {
! debug.log("add use: %s, from %d to %d (%s)", interval, from, to, registerPriority.name());
}
}
protected void addTemp(AllocatableValue operand, int tempPos, RegisterPriority registerPriority, ValueKind<?> kind, boolean detailedAsserts) {
if (!allocator.isProcessed(operand)) {
*** 510,521 ****
--- 511,522 ----
interval.addRange(tempPos, tempPos + 1);
interval.addUsePos(tempPos, registerPriority, detailedAsserts);
interval.addMaterializationValue(null);
! if (Debug.isLogEnabled()) {
! Debug.log("add temp: %s tempPos %d (%s)", interval, tempPos, RegisterPriority.MustHaveRegister.name());
! if (debug.isLogEnabled()) {
! debug.log("add temp: %s tempPos %d (%s)", interval, tempPos, RegisterPriority.MustHaveRegister.name());
}
}
protected void addDef(AllocatableValue operand, LIRInstruction op, RegisterPriority registerPriority, ValueKind<?> kind, boolean detailedAsserts) {
if (!allocator.isProcessed(operand)) {
*** 541,564 ****
--- 542,565 ----
/*
* Dead value - make vacuous interval also add register priority for dead intervals
*/
interval.addRange(defPos, defPos + 1);
interval.addUsePos(defPos, registerPriority, detailedAsserts);
! if (Debug.isLogEnabled()) {
! Debug.log("Warning: def of operand %s at %d occurs without use", operand, defPos);
! if (debug.isLogEnabled()) {
! debug.log("Warning: def of operand %s at %d occurs without use", operand, defPos);
}
}
changeSpillDefinitionPos(op, operand, interval, defPos);
if (registerPriority == RegisterPriority.None && interval.spillState().ordinal() <= SpillState.StartInMemory.ordinal() && isStackSlot(operand)) {
// detection of method-parameters and roundfp-results
interval.setSpillState(SpillState.StartInMemory);
}
interval.addMaterializationValue(getMaterializedValue(op, operand, interval));
! if (Debug.isLogEnabled()) {
! Debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name());
! if (debug.isLogEnabled()) {
! debug.log("add def: %s defPos %d (%s)", interval, defPos, registerPriority.name());
}
}
/**
* Optimizes moves related to incoming stack based arguments. The interval for the destination
*** 572,583 ****
--- 573,584 ----
if (DetailedAsserts.getValue(allocator.getOptions())) {
assert op.id() > 0 : "invalid id";
assert allocator.blockForId(op.id()).getPredecessorCount() == 0 : "move from stack must be in first block";
assert isVariable(move.getResult()) : "result of move must be a variable";
! if (Debug.isLogEnabled()) {
! Debug.log("found move from stack slot %s to %s", slot, move.getResult());
! if (debug.isLogEnabled()) {
! debug.log("found move from stack slot %s to %s", slot, move.getResult());
}
}
Interval interval = allocator.intervalFor(move.getResult());
interval.setSpillSlot(slot);
*** 598,609 ****
--- 599,610 ----
if (hintAtDef) {
to.setLocationHint(from);
} else {
from.setLocationHint(to);
}
! if (Debug.isLogEnabled()) {
! Debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber);
! if (debug.isLogEnabled()) {
! debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber);
}
return registerHint;
}
return null;
*** 683,693 ****
--- 684,694 ----
}
@SuppressWarnings("try")
protected void buildIntervals(boolean detailedAsserts) {
! try (Indent indent = Debug.logAndIndent("build intervals")) {
! try (Indent indent = debug.logAndIndent("build intervals")) {
InstructionValueConsumer outputConsumer = (op, operand, mode, flags) -> {
if (LinearScan.isVariableOrRegister(operand)) {
addDef((AllocatableValue) operand, op, registerPriorityOfOutputOperand(op), operand.getValueKind(), detailedAsserts);
addRegisterHint(op, operand, mode, flags, true);
}
*** 733,743 ****
--- 734,744 ----
// iterate all blocks in reverse order
for (int i = allocator.blockCount() - 1; i >= 0; i--) {
AbstractBlockBase<?> block = allocator.blockAt(i);
! try (Indent indent2 = Debug.logAndIndent("handle block %d", block.getId())) {
! try (Indent indent2 = debug.logAndIndent("handle block %d", block.getId())) {
ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
final int blockFrom = allocator.getFirstLirInstructionId(block);
int blockTo = allocator.getLastLirInstructionId(block);
*** 747,758 ****
--- 748,759 ----
// Update intervals for operands live at the end of this block;
BitSet live = allocator.getBlockData(block).liveOut;
for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) {
assert live.get(operandNum) : "should not stop here otherwise";
AllocatableValue operand = allocator.intervalFor(operandNum).operand;
! if (Debug.isLogEnabled()) {
! Debug.log("live in %d: %s", operandNum, operand);
! if (debug.isLogEnabled()) {
! debug.log("live in %d: %s", operandNum, operand);
}
addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, LIRKind.Illegal, detailedAsserts);
/*
*** 771,792 ****
--- 772,793 ----
*/
for (int j = instructions.size() - 1; j >= 0; j--) {
final LIRInstruction op = instructions.get(j);
final int opId = op.id();
! try (Indent indent3 = Debug.logAndIndent("handle inst %d: %s", opId, op)) {
! try (Indent indent3 = debug.logAndIndent("handle inst %d: %s", opId, op)) {
// add a temp range for each register if operation destroys
// caller-save registers
if (op.destroysCallerSavedRegisters()) {
for (Register r : callerSaveRegs) {
if (allocator.attributes(r).isAllocatable()) {
addTemp(r.asValue(), opId, RegisterPriority.None, LIRKind.Illegal, detailedAsserts);
}
}
! if (Debug.isLogEnabled()) {
! Debug.log("operation destroys all caller-save registers");
! if (debug.isLogEnabled()) {
! debug.log("operation destroys all caller-save registers");
}
}
op.visitEachOutput(outputConsumer);
op.visitEachTemp(tempConsumer);
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File