use of org.graalvm.compiler.lir.LIRInstruction.OperandMode 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.LIRInstruction.OperandMode 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.LIRInstruction.OperandMode 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.LIRInstruction.OperandMode in project graal by oracle.
the class TrivialTraceAllocator method handlePhiOut.
private static void handlePhiOut(LIRInstruction jump, int[] varIn, Value[] locIn) {
// handle outgoing phi values
ValueProcedure outputConsumer = new ValueProcedure() {
@Override
public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
if (isVariable(value)) {
// since incoming variables are sorted, we can do a binary search
return locIn[Arrays.binarySearch(varIn, asVariable(value).index)];
}
return value;
}
};
// Jumps have only alive values (outgoing phi values)
jump.forEachAlive(outputConsumer);
}
use of org.graalvm.compiler.lir.LIRInstruction.OperandMode in project graal by oracle.
the class LinearScanAssignLocationsPhase method debugInfoProcedure.
private Value debugInfoProcedure(LIRInstruction op, Value operand) {
if (isVirtualStackSlot(operand)) {
return operand;
}
int tempOpId = op.id();
OperandMode mode = OperandMode.USE;
AbstractBlockBase<?> block = allocator.blockForId(tempOpId);
if (block.getSuccessorCount() == 1 && tempOpId == allocator.getLastLirInstructionId(block)) {
/*
* Generating debug information for the last instruction of a block. If this instruction
* is a branch, spill moves are inserted before this branch and so the wrong operand
* would be returned (spill moves at block boundaries are not considered in the live
* ranges of intervals).
*
* Solution: use the first opId of the branch target block instead.
*/
final LIRInstruction instr = allocator.getLIR().getLIRforBlock(block).get(allocator.getLIR().getLIRforBlock(block).size() - 1);
if (instr instanceof StandardOp.JumpOp) {
if (allocator.getBlockData(block).liveOut.get(allocator.operandNumber(operand))) {
tempOpId = allocator.getFirstLirInstructionId(block.getSuccessors()[0]);
mode = OperandMode.DEF;
}
}
}
/*
* Get current location of operand. The operand must be live because debug information is
* considered when building the intervals if the interval is not live, colorLirOperand will
* cause an assert on failure.
*/
Value result = colorLirOperand(op, (Variable) operand, mode);
assert !allocator.hasCall(tempOpId) || isStackSlotValue(result) || isJavaConstant(result) || !allocator.isCallerSave(result) : "cannot have caller-save register operands at calls";
return result;
}
Aggregations