Search in sources :

Example 1 with ValueConsumer

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);
}
Also used : LabelOp(org.graalvm.compiler.lir.StandardOp.LabelOp) Register(jdk.vm.ci.code.Register) ValueConsumer(org.graalvm.compiler.lir.ValueConsumer) EnumSet(java.util.EnumSet) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) Value(jdk.vm.ci.meta.Value) OperandMode(org.graalvm.compiler.lir.LIRInstruction.OperandMode)

Example 2 with ValueConsumer

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);
            }
        });
    }
}
Also used : OperandMode(org.graalvm.compiler.lir.LIRInstruction.OperandMode) Interval(org.graalvm.compiler.lir.alloc.lsra.Interval) ValueConsumer(org.graalvm.compiler.lir.ValueConsumer) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) RegisterPriority(org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterPriority) Value(jdk.vm.ci.meta.Value) OperandFlag(org.graalvm.compiler.lir.LIRInstruction.OperandFlag) DebugContext(org.graalvm.compiler.debug.DebugContext) LinearScan(org.graalvm.compiler.lir.alloc.lsra.LinearScan) LinearScanLifetimeAnalysisPhase(org.graalvm.compiler.lir.alloc.lsra.LinearScanLifetimeAnalysisPhase) SSAUtil(org.graalvm.compiler.lir.ssa.SSAUtil) EnumSet(java.util.EnumSet) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) LabelOp(org.graalvm.compiler.lir.StandardOp.LabelOp) LabelOp(org.graalvm.compiler.lir.StandardOp.LabelOp) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) Interval(org.graalvm.compiler.lir.alloc.lsra.Interval)

Example 3 with ValueConsumer

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;
}
Also used : Variable(org.graalvm.compiler.lir.Variable) ValueConsumer(org.graalvm.compiler.lir.ValueConsumer) EnumSet(java.util.EnumSet) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) BitSet(java.util.BitSet) Value(jdk.vm.ci.meta.Value) OperandMode(org.graalvm.compiler.lir.LIRInstruction.OperandMode)

Example 4 with ValueConsumer

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);
}
Also used : AbstractBlockBase(org.graalvm.compiler.core.common.cfg.AbstractBlockBase) PermanentBailoutException(org.graalvm.compiler.core.common.PermanentBailoutException) Constant(jdk.vm.ci.meta.Constant) LoadConstantOp(org.graalvm.compiler.lir.StandardOp.LoadConstantOp) BitMap2D(org.graalvm.compiler.core.common.util.BitMap2D) LIRValueUtil.asVariable(org.graalvm.compiler.lir.LIRValueUtil.asVariable) EconomicSet(org.graalvm.collections.EconomicSet) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) LIRGenerationResult(org.graalvm.compiler.lir.gen.LIRGenerationResult) Register(jdk.vm.ci.code.Register) Assertions(org.graalvm.compiler.debug.Assertions) ValueUtil.asStackSlot(jdk.vm.ci.code.ValueUtil.asStackSlot) ArrayList(java.util.ArrayList) InstructionValueConsumer(org.graalvm.compiler.lir.InstructionValueConsumer) SpillState(org.graalvm.compiler.lir.alloc.lsra.Interval.SpillState) OperandFlag(org.graalvm.compiler.lir.LIRInstruction.OperandFlag) DebugContext(org.graalvm.compiler.debug.DebugContext) RegisterArray(jdk.vm.ci.code.RegisterArray) ValueUtil.isRegister(jdk.vm.ci.code.ValueUtil.isRegister) ValueUtil.asRegister(jdk.vm.ci.code.ValueUtil.asRegister) ComputeBlockOrder(org.graalvm.compiler.core.common.alloc.ComputeBlockOrder) BlockData(org.graalvm.compiler.lir.alloc.lsra.LinearScan.BlockData) LIRGenerationDebugContext.getSourceForOperandFromDebugContext(org.graalvm.compiler.lir.debug.LIRGenerationDebugContext.getSourceForOperandFromDebugContext) Equivalence(org.graalvm.collections.Equivalence) EnumSet(java.util.EnumSet) ValueUtil.isStackSlot(jdk.vm.ci.code.ValueUtil.isStackSlot) OperandMode(org.graalvm.compiler.lir.LIRInstruction.OperandMode) ValueConsumer(org.graalvm.compiler.lir.ValueConsumer) LIRValueUtil.isVariable(org.graalvm.compiler.lir.LIRValueUtil.isVariable) LIRKind(org.graalvm.compiler.core.common.LIRKind) AllocationContext(org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext) TargetDescription(jdk.vm.ci.code.TargetDescription) JavaConstant(jdk.vm.ci.meta.JavaConstant) RegisterPriority(org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterPriority) Value(jdk.vm.ci.meta.Value) ValueMoveOp(org.graalvm.compiler.lir.StandardOp.ValueMoveOp) Indent(org.graalvm.compiler.debug.Indent) GraalError(org.graalvm.compiler.debug.GraalError) StackSlot(jdk.vm.ci.code.StackSlot) BitSet(java.util.BitSet) ArrayDeque(java.util.ArrayDeque) ValueKind(jdk.vm.ci.meta.ValueKind) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) InstructionValueConsumer(org.graalvm.compiler.lir.InstructionValueConsumer) ValueConsumer(org.graalvm.compiler.lir.ValueConsumer) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction)

Example 5 with ValueConsumer

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);
    }
}
Also used : AbstractBlockBase(org.graalvm.compiler.core.common.cfg.AbstractBlockBase) PermanentBailoutException(org.graalvm.compiler.core.common.PermanentBailoutException) Constant(jdk.vm.ci.meta.Constant) LoadConstantOp(org.graalvm.compiler.lir.StandardOp.LoadConstantOp) BitMap2D(org.graalvm.compiler.core.common.util.BitMap2D) LIRValueUtil.asVariable(org.graalvm.compiler.lir.LIRValueUtil.asVariable) EconomicSet(org.graalvm.collections.EconomicSet) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) LIRGenerationResult(org.graalvm.compiler.lir.gen.LIRGenerationResult) Register(jdk.vm.ci.code.Register) Assertions(org.graalvm.compiler.debug.Assertions) ValueUtil.asStackSlot(jdk.vm.ci.code.ValueUtil.asStackSlot) ArrayList(java.util.ArrayList) InstructionValueConsumer(org.graalvm.compiler.lir.InstructionValueConsumer) SpillState(org.graalvm.compiler.lir.alloc.lsra.Interval.SpillState) OperandFlag(org.graalvm.compiler.lir.LIRInstruction.OperandFlag) DebugContext(org.graalvm.compiler.debug.DebugContext) RegisterArray(jdk.vm.ci.code.RegisterArray) ValueUtil.isRegister(jdk.vm.ci.code.ValueUtil.isRegister) ValueUtil.asRegister(jdk.vm.ci.code.ValueUtil.asRegister) ComputeBlockOrder(org.graalvm.compiler.core.common.alloc.ComputeBlockOrder) BlockData(org.graalvm.compiler.lir.alloc.lsra.LinearScan.BlockData) LIRGenerationDebugContext.getSourceForOperandFromDebugContext(org.graalvm.compiler.lir.debug.LIRGenerationDebugContext.getSourceForOperandFromDebugContext) Equivalence(org.graalvm.collections.Equivalence) EnumSet(java.util.EnumSet) ValueUtil.isStackSlot(jdk.vm.ci.code.ValueUtil.isStackSlot) OperandMode(org.graalvm.compiler.lir.LIRInstruction.OperandMode) ValueConsumer(org.graalvm.compiler.lir.ValueConsumer) LIRValueUtil.isVariable(org.graalvm.compiler.lir.LIRValueUtil.isVariable) LIRKind(org.graalvm.compiler.core.common.LIRKind) AllocationContext(org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext) TargetDescription(jdk.vm.ci.code.TargetDescription) JavaConstant(jdk.vm.ci.meta.JavaConstant) RegisterPriority(org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterPriority) Value(jdk.vm.ci.meta.Value) ValueMoveOp(org.graalvm.compiler.lir.StandardOp.ValueMoveOp) Indent(org.graalvm.compiler.debug.Indent) GraalError(org.graalvm.compiler.debug.GraalError) StackSlot(jdk.vm.ci.code.StackSlot) BitSet(java.util.BitSet) ArrayDeque(java.util.ArrayDeque) ValueKind(jdk.vm.ci.meta.ValueKind) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) Indent(org.graalvm.compiler.debug.Indent) InstructionValueConsumer(org.graalvm.compiler.lir.InstructionValueConsumer) ValueConsumer(org.graalvm.compiler.lir.ValueConsumer) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) BitSet(java.util.BitSet) BitMap2D(org.graalvm.compiler.core.common.util.BitMap2D) BlockData(org.graalvm.compiler.lir.alloc.lsra.LinearScan.BlockData) PermanentBailoutException(org.graalvm.compiler.core.common.PermanentBailoutException)

Aggregations

EnumSet (java.util.EnumSet)6 Value (jdk.vm.ci.meta.Value)6 OperandMode (org.graalvm.compiler.lir.LIRInstruction.OperandMode)6 ValueConsumer (org.graalvm.compiler.lir.ValueConsumer)6 LIRInstruction (org.graalvm.compiler.lir.LIRInstruction)5 BitSet (java.util.BitSet)3 Register (jdk.vm.ci.code.Register)3 AllocatableValue (jdk.vm.ci.meta.AllocatableValue)3 DebugContext (org.graalvm.compiler.debug.DebugContext)3 OperandFlag (org.graalvm.compiler.lir.LIRInstruction.OperandFlag)3 RegisterPriority (org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterPriority)3 ArrayDeque (java.util.ArrayDeque)2 ArrayList (java.util.ArrayList)2 RegisterArray (jdk.vm.ci.code.RegisterArray)2 StackSlot (jdk.vm.ci.code.StackSlot)2 TargetDescription (jdk.vm.ci.code.TargetDescription)2 ValueUtil.asRegister (jdk.vm.ci.code.ValueUtil.asRegister)2 ValueUtil.asStackSlot (jdk.vm.ci.code.ValueUtil.asStackSlot)2 ValueUtil.isRegister (jdk.vm.ci.code.ValueUtil.isRegister)2 ValueUtil.isStackSlot (jdk.vm.ci.code.ValueUtil.isStackSlot)2