From e44e6952dc0d5da3c5041c9b0c9365fdad138aaa Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Wed, 12 Aug 2026 03:43:54 +0800 Subject: [CodeGen] Verify local physical live-ins --- backend/lib/CodeGen/MachineLiveness.cpp | 76 +++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) (limited to 'backend/lib/CodeGen/MachineLiveness.cpp') diff --git a/backend/lib/CodeGen/MachineLiveness.cpp b/backend/lib/CodeGen/MachineLiveness.cpp index 7984e7d..9882b11 100644 --- a/backend/lib/CodeGen/MachineLiveness.cpp +++ b/backend/lib/CodeGen/MachineLiveness.cpp @@ -900,6 +900,66 @@ liveSetIntersects(const MachineOperand &Operand, const RegisterLaneSet &Virtual, return addOperandUse(Virtual, Physical, Operand, Function, Target); } +[[nodiscard]] Expected +requiredLocalPhysicalLiveIns(const MachineBasicBlock &Block, const MachineFunction &Function, + const TargetDescription &Target) { + RegisterLaneSet Virtual; + RegisterUnitLaneSet Physical; + for (const MachineInstr *Instruction = Block.lastInstruction(); Instruction != nullptr; + Instruction = Instruction->previous()) { + const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); + if (Descriptor == nullptr) { + return makeUnexpected(ErrorCode::VerificationError, + "liveness verification encountered an unknown instruction descriptor"); + } + const bool IsPhi = Descriptor->Flags.has(InstructionFlag::Phi); + for (const MachineOperand &Operand : Instruction->operands()) { + const auto *MaskOperand = Operand.getIf(); + if (MaskOperand == nullptr) + continue; + if (!MaskOperand->Mask) { + return makeUnexpected(ErrorCode::VerificationError, + "liveness verification encountered a null live-out register mask"); + } + auto Added = addRegisterMaskUses(Physical, *MaskOperand->Mask, Target); + if (!Added) + return std::unexpected(Added.error()); + } + + for (const MachineOperand &Operand : Instruction->operands()) { + if (Operand.isRegister() && Operand.isDef()) { + auto Removed = removeOperandFromLiveSet(Operand, Virtual, Physical, Function, Target); + if (!Removed) + return std::unexpected(Removed.error()); + continue; + } + const auto *MaskOperand = Operand.getIf(); + if (MaskOperand == nullptr) + continue; + if (!MaskOperand->Mask) { + return makeUnexpected(ErrorCode::VerificationError, + "liveness verification encountered a null register mask"); + } + RegisterUnitLaneSet Clobbers; + auto Added = addRegisterMaskDefs(Clobbers, *MaskOperand->Mask, Target); + if (!Added) + return std::unexpected(Added.error()); + Physical.subtract(Clobbers); + } + + if (IsPhi) + continue; + for (const MachineOperand &Operand : Instruction->operands()) { + if (!Operand.isRegister() || !Operand.isUse()) + continue; + auto Added = addOperandToLiveSet(Operand, Virtual, Physical, Function, Target); + if (!Added) + return std::unexpected(Added.error()); + } + } + return Physical; +} + [[nodiscard]] Expected buildLivenessRebuildPlan(const MachineFunction &Function, const TargetDescription &Target) { auto Variables = computeLiveVariables(Function, Target); @@ -1792,14 +1852,24 @@ Expected verifyTrackedMachineLiveness(const MachineFunction &Function, auto Plan = buildLivenessRebuildPlan(Function, Target); if (!Plan) return std::unexpected(Plan.error()); - for (const BlockLivenessPlan &BlockPlan : Plan->Blocks) { - auto Actual = liveInUnits(BlockPlan.OriginalLiveIns, Target); + for (const MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; + Block = Block->next()) { + auto Actual = liveInUnits(Block->liveIns(), Target); if (!Actual) return std::unexpected(Actual.error()); - auto Expected = liveInUnits(BlockPlan.RebuiltLiveIns, Target); + auto Expected = requiredLocalPhysicalLiveIns(*Block, Function, Target); if (!Expected) return std::unexpected(Expected.error()); if (!isSubset(*Expected, *Actual)) { + const auto Missing = std::ranges::find_if(Expected->entries(), [&Actual](const auto &Entry) { + return !Actual->contains(Entry.first, Entry.second); + }); + if (Missing != Expected->entries().end()) { + return makeUnexpected(ErrorCode::VerificationError, + "TracksLiveness block " + std::to_string(Block->stableID().value()) + + " is missing required physical register unit " + + std::to_string(Missing->first.value())); + } return makeUnexpected(ErrorCode::VerificationError, "TracksLiveness block is missing required physical live-ins"); } -- cgit v1.2.3