use of org.graalvm.compiler.lir.ValueConsumer in project graal by oracle.
the class HotSpotBackend method gatherDestroyedCallerRegisters.
/**
* Finds all the registers that are defined by some given LIR.
*
* @param lir the LIR to examine
* @return the registers that are defined by or used as temps for any instruction in {@code lir}
*/
protected final EconomicSet<Register> gatherDestroyedCallerRegisters(LIR lir) {
final EconomicSet<Register> destroyedRegisters = EconomicSet.create(Equivalence.IDENTITY);
ValueConsumer defConsumer = new ValueConsumer() {
@Override
public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
if (ValueUtil.isRegister(value)) {
final Register reg = ValueUtil.asRegister(value);
destroyedRegisters.add(reg);
}
}
};
for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
if (block == null) {
continue;
}
for (LIRInstruction op : lir.getLIRforBlock(block)) {
if (op instanceof LabelOp) {
// Don't consider this as a definition
} else {
op.visitEachTemp(defConsumer);
op.visitEachOutput(defConsumer);
}
}
}
return translateToCallerRegisters(destroyedRegisters);
}
use of org.graalvm.compiler.lir.ValueConsumer in project graal by oracle.
the class SSALinearScanLifetimeAnalysisPhase method addRegisterHint.
@Override
protected void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet<OperandFlag> flags, final boolean hintAtDef) {
super.addRegisterHint(op, targetValue, mode, flags, hintAtDef);
if (hintAtDef && op instanceof LabelOp) {
LabelOp label = (LabelOp) op;
Interval to = allocator.getOrCreateInterval((AllocatableValue) targetValue);
SSAUtil.forEachPhiRegisterHint(allocator.getLIR(), allocator.blockForId(label.id()), label, targetValue, mode, (ValueConsumer) (registerHint, valueMode, valueFlags) -> {
if (LinearScan.isVariableOrRegister(registerHint)) {
Interval from = allocator.getOrCreateInterval((AllocatableValue) registerHint);
setHint(debug, op, to, from);
setHint(debug, op, from, to);
}
});
}
}
use of org.graalvm.compiler.lir.ValueConsumer in project graal by oracle.
the class GlobalLivenessInfo method verifyBlock.
private boolean verifyBlock(AbstractBlockBase<?> block, LIR lir) {
BitSet liveSet = new BitSet(lir.numVariables());
int[] liveIn = getBlockIn(block);
for (int varNum : liveIn) {
liveSet.set(varNum);
}
ValueConsumer proc = new ValueConsumer() {
@Override
public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
if (LIRValueUtil.isVariable(value)) {
Variable var = LIRValueUtil.asVariable(value);
if (mode == OperandMode.DEF) {
liveSet.set(var.index);
} else {
assert liveSet.get(var.index) : String.format("Variable %s but not defined in block %s (liveIn: %s)", var, block, Arrays.toString(liveIn));
}
}
}
};
for (LIRInstruction op : lir.getLIRforBlock(block)) {
op.visitEachInput(proc);
op.visitEachAlive(proc);
op.visitEachState(proc);
op.visitEachOutput(proc);
// no need for checking temp
}
return true;
}
use of org.graalvm.compiler.lir.ValueConsumer in project graal by oracle.
the class LinearScanLifetimeAnalysisPhase method numberInstructions.
/**
* Numbers all instructions in all blocks. The numbering follows the
* {@linkplain ComputeBlockOrder linear scan order}.
*/
protected void numberInstructions() {
allocator.initIntervals();
ValueConsumer setVariableConsumer = (value, mode, flags) -> {
if (isVariable(value)) {
allocator.getOrCreateInterval(asVariable(value));
}
};
// Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node.
int numInstructions = 0;
for (AbstractBlockBase<?> block : allocator.sortedBlocks()) {
numInstructions += allocator.getLIR().getLIRforBlock(block).size();
}
// initialize with correct length
allocator.initOpIdMaps(numInstructions);
int opId = 0;
int index = 0;
for (AbstractBlockBase<?> block : allocator.sortedBlocks()) {
allocator.initBlockData(block);
ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
int numInst = instructions.size();
for (int j = 0; j < numInst; j++) {
LIRInstruction op = instructions.get(j);
op.setId(opId);
allocator.putOpIdMaps(index, op, block);
assert allocator.instructionForId(opId) == op : "must match";
op.visitEachTemp(setVariableConsumer);
op.visitEachOutput(setVariableConsumer);
index++;
// numbering of lirOps by two
opId += 2;
}
}
assert index == numInstructions : "must match";
assert (index << 1) == opId : "must match: " + (index << 1);
}
use of org.graalvm.compiler.lir.ValueConsumer in project graal by oracle.
the class LinearScanLifetimeAnalysisPhase method computeLocalLiveSets.
/**
* Computes local live sets (i.e. {@link BlockData#liveGen} and {@link BlockData#liveKill})
* separately for each block.
*/
@SuppressWarnings("try")
void computeLocalLiveSets() {
int liveSize = allocator.liveSetSize();
intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops());
try {
// iterate all blocks
for (final AbstractBlockBase<?> block : allocator.sortedBlocks()) {
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);
int numInst = instructions.size();
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 (block.getLoop() != null) {
intervalInLoop.setBit(operandNum, block.getLoop().getIndex());
}
}
if (allocator.detailedAsserts) {
verifyInput(block, liveKill, operand);
}
};
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);
}
}
}
};
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 (block.getLoop() != null) {
intervalInLoop.setBit(varNum, block.getLoop().getIndex());
}
}
if (allocator.detailedAsserts) {
/*
* Fixed intervals are never live at block boundaries, so they need not
* be processed in live sets. Process them only in debug mode so that
* this can be checked
*/
verifyTemp(liveKill, operand);
}
};
// 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)) {
op.visitEachInput(useConsumer);
op.visitEachAlive(useConsumer);
/*
* Add uses of live locals from interpreter's point of view for proper
* debug information generation.
*/
op.visitEachState(stateConsumer);
op.visitEachTemp(defConsumer);
op.visitEachOutput(defConsumer);
}
}
// end of instruction iteration
BlockData blockSets = allocator.getBlockData(block);
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);
}
}
}
// end of block iteration
} catch (OutOfMemoryError oom) {
throw new PermanentBailoutException(oom, "Out-of-memory during live set allocation of size %d", liveSize);
}
}
Aggregations