Search in sources :

Example 91 with Value

use of jdk.vm.ci.meta.Value 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;
}
Also used : LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) LIRValueUtil.isStackSlotValue(org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue) ConstantValue(org.graalvm.compiler.lir.ConstantValue) Value(jdk.vm.ci.meta.Value) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) OperandMode(org.graalvm.compiler.lir.LIRInstruction.OperandMode)

Example 92 with Value

use of jdk.vm.ci.meta.Value 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 93 with Value

use of jdk.vm.ci.meta.Value in project graal by oracle.

the class LinearScanLifetimeAnalysisPhase method buildIntervals.

@SuppressWarnings("try")
protected void buildIntervals(boolean detailedAsserts) {
    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);
            }
        };
        InstructionValueConsumer tempConsumer = (op, operand, mode, flags) -> {
            if (LinearScan.isVariableOrRegister(operand)) {
                addTemp((AllocatableValue) operand, op.id(), RegisterPriority.MustHaveRegister, operand.getValueKind(), detailedAsserts);
                addRegisterHint(op, operand, mode, flags, false);
            }
        };
        InstructionValueConsumer aliveConsumer = (op, operand, mode, flags) -> {
            if (LinearScan.isVariableOrRegister(operand)) {
                RegisterPriority p = registerPriorityOfInputOperand(flags);
                int opId = op.id();
                int blockFrom = allocator.getFirstLirInstructionId((allocator.blockForId(opId)));
                addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getValueKind(), detailedAsserts);
                addRegisterHint(op, operand, mode, flags, false);
            }
        };
        InstructionValueConsumer inputConsumer = (op, operand, mode, flags) -> {
            if (LinearScan.isVariableOrRegister(operand)) {
                int opId = op.id();
                int blockFrom = allocator.getFirstLirInstructionId((allocator.blockForId(opId)));
                RegisterPriority p = registerPriorityOfInputOperand(flags);
                addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getValueKind(), detailedAsserts);
                addRegisterHint(op, operand, mode, flags, false);
            }
        };
        InstructionValueConsumer stateProc = (op, operand, mode, flags) -> {
            if (LinearScan.isVariableOrRegister(operand)) {
                int opId = op.id();
                int blockFrom = allocator.getFirstLirInstructionId((allocator.blockForId(opId)));
                addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getValueKind(), detailedAsserts);
            }
        };
        // create a list with all caller-save registers (cpu, fpu, xmm)
        RegisterArray callerSaveRegs = allocator.getRegisterAllocationConfig().getRegisterConfig().getCallerSaveRegisters();
        // 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())) {
                ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
                final int blockFrom = allocator.getFirstLirInstructionId(block);
                int blockTo = allocator.getLastLirInstructionId(block);
                assert blockFrom == instructions.get(0).id();
                assert blockTo == instructions.get(instructions.size() - 1).id();
                // 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);
                    }
                    addUse(operand, blockFrom, blockTo + 2, RegisterPriority.None, LIRKind.Illegal, detailedAsserts);
                    /*
                         * Add special use positions for loop-end blocks when the interval is used
                         * anywhere inside this loop. It's possible that the block was part of a
                         * non-natural loop, so it might have an invalid loop index.
                         */
                    if (block.isLoopEnd() && block.getLoop() != null && isIntervalInLoop(operandNum, block.getLoop().getIndex())) {
                        allocator.intervalFor(operandNum).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd, detailedAsserts);
                    }
                }
                /*
                     * Iterate all instructions of the block in reverse order. definitions of
                     * intervals are processed before uses.
                     */
                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)) {
                        // 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");
                            }
                        }
                        op.visitEachOutput(outputConsumer);
                        op.visitEachTemp(tempConsumer);
                        op.visitEachAlive(aliveConsumer);
                        op.visitEachInput(inputConsumer);
                        /*
                             * Add uses of live locals from interpreter's point of view for proper
                             * debug information generation. Treat these operands as temp values (if
                             * the live range is extended to a call site, the value would be in a
                             * register at the call otherwise).
                             */
                        op.visitEachState(stateProc);
                        // special steps for some instructions (especially moves)
                        handleMethodArguments(op);
                    }
                }
            // end of instruction iteration
            }
        }
        /*
             * Add the range [0, 1] to all fixed intervals. the register allocator need not handle
             * unhandled fixed intervals.
             */
        for (Interval interval : allocator.intervals()) {
            if (interval != null && isRegister(interval.operand)) {
                interval.addRange(0, 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) RegisterPriority(org.graalvm.compiler.lir.alloc.lsra.Interval.RegisterPriority) Indent(org.graalvm.compiler.debug.Indent) InstructionValueConsumer(org.graalvm.compiler.lir.InstructionValueConsumer) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) BitSet(java.util.BitSet) RegisterArray(jdk.vm.ci.code.RegisterArray) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) Register(jdk.vm.ci.code.Register) ValueUtil.isRegister(jdk.vm.ci.code.ValueUtil.isRegister) ValueUtil.asRegister(jdk.vm.ci.code.ValueUtil.asRegister)

Example 94 with Value

use of jdk.vm.ci.meta.Value in project graal by oracle.

the class LinearScanLifetimeAnalysisPhase method reportFailure.

@SuppressWarnings("try")
protected void reportFailure(int numBlocks) {
    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):")) {
                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(debug, operand));
                    } else {
                        debug.log("var %d; missing operand", operandNum);
                    }
                }
            }
            // print some additional information to simplify debugging
            for (int operandNum = startBlockLiveIn.nextSetBit(0); operandNum >= 0; operandNum = startBlockLiveIn.nextSetBit(operandNum + 1)) {
                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)) {
                    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())) {
                                for (LIRInstruction ins : allocator.getLIR().getLIRforBlock(block)) {
                                    try (Indent indent4 = debug.logAndIndent("%d: %s", ins.id(), ins)) {
                                        ins.forEachState((liveStateOperand, mode, flags) -> {
                                            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())) {
                                for (LIRInstruction ins : allocator.getLIR().getLIRforBlock(block)) {
                                    debug.log("%d: %s", ins.id(), ins);
                                }
                            }
                        }
                    }
                    int[] hitCount = new int[numBlocks];
                    while (!definedIn.isEmpty()) {
                        AbstractBlockBase<?> block = definedIn.removeFirst();
                        usedIn.remove(block);
                        for (AbstractBlockBase<?> successor : block.getSuccessors()) {
                            if (successor.isLoopHeader()) {
                                if (!block.isLoopEnd()) {
                                    definedIn.add(successor);
                                }
                            } else {
                                if (++hitCount[successor.getId()] == successor.getPredecessorCount()) {
                                    definedIn.add(successor);
                                }
                            }
                        }
                    }
                    try (Indent indent3 = debug.logAndIndent("**** offending usages are in: ")) {
                        for (AbstractBlockBase<?> block : usedIn) {
                            debug.log("B%d", block.getId());
                        }
                    }
                }
            }
        }
    } catch (Throwable e) {
        throw debug.handle(e);
    }
}
Also used : Indent(org.graalvm.compiler.debug.Indent) LIRInstruction(org.graalvm.compiler.lir.LIRInstruction) BitSet(java.util.BitSet) DebugContext(org.graalvm.compiler.debug.DebugContext) LIRGenerationDebugContext.getSourceForOperandFromDebugContext(org.graalvm.compiler.lir.debug.LIRGenerationDebugContext.getSourceForOperandFromDebugContext) ArrayDeque(java.util.ArrayDeque) AbstractBlockBase(org.graalvm.compiler.core.common.cfg.AbstractBlockBase) Value(jdk.vm.ci.meta.Value) AllocatableValue(jdk.vm.ci.meta.AllocatableValue)

Example 95 with Value

use of jdk.vm.ci.meta.Value in project graal by oracle.

the class MoveResolver method blockRegisters.

// mark assignedReg and assignedRegHi of the interval as blocked
private void blockRegisters(Interval interval) {
    Value location = interval.location();
    if (mightBeBlocked(location)) {
        assert areMultipleReadsAllowed() || valueBlocked(location) == 0 : "location already marked as used: " + location;
        int direction = 1;
        setValueBlocked(location, direction);
        allocator.getDebug().log("block %s", location);
    }
}
Also used : Value(jdk.vm.ci.meta.Value) AllocatableValue(jdk.vm.ci.meta.AllocatableValue)

Aggregations

Value (jdk.vm.ci.meta.Value)151 AllocatableValue (jdk.vm.ci.meta.AllocatableValue)76 RegisterValue (jdk.vm.ci.code.RegisterValue)33 LIRKind (org.graalvm.compiler.core.common.LIRKind)18 LIRInstruction (org.graalvm.compiler.lir.LIRInstruction)14 LIRValueUtil.isConstantValue (org.graalvm.compiler.lir.LIRValueUtil.isConstantValue)14 LIRValueUtil.isStackSlotValue (org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue)14 OperandMode (org.graalvm.compiler.lir.LIRInstruction.OperandMode)12 Variable (org.graalvm.compiler.lir.Variable)12 ComplexMatchValue (org.graalvm.compiler.core.match.ComplexMatchValue)11 Indent (org.graalvm.compiler.debug.Indent)11 EnumSet (java.util.EnumSet)10 DebugContext (org.graalvm.compiler.debug.DebugContext)10 GraalError (org.graalvm.compiler.debug.GraalError)10 LIRFrameState (org.graalvm.compiler.lir.LIRFrameState)10 BitSet (java.util.BitSet)9 Register (jdk.vm.ci.code.Register)9 ConstantValue (org.graalvm.compiler.lir.ConstantValue)9 SPARCAddressValue (org.graalvm.compiler.lir.sparc.SPARCAddressValue)9 ValueNode (org.graalvm.compiler.nodes.ValueNode)9