diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:03:47 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:04:23 +0000 |
commit | 7fa27ce4a07f19b07799a767fc29416f3b625afb (patch) | |
tree | 27825c83636c4de341eb09a74f49f5d38a15d165 /llvm/lib/CodeGen/MachineVerifier.cpp | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) |
Diffstat (limited to 'llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineVerifier.cpp | 239 |
1 files changed, 126 insertions, 113 deletions
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index ddd5a027c2cd..7acd3c4039e8 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -31,13 +31,13 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/Analysis/EHPersonalities.h" #include "llvm/CodeGen/CodeGenCommonISel.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/CodeGen/LiveIntervals.h" #include "llvm/CodeGen/LiveRangeCalc.h" #include "llvm/CodeGen/LiveStacks.h" #include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/LowLevelType.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -58,6 +58,7 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/EHPersonalities.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" @@ -71,7 +72,6 @@ #include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/LowLevelTypeImpl.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/ModRef.h" #include "llvm/Support/raw_ostream.h" @@ -95,19 +95,19 @@ namespace { Pass *const PASS; const char *Banner; - const MachineFunction *MF; - const TargetMachine *TM; - const TargetInstrInfo *TII; - const TargetRegisterInfo *TRI; - const MachineRegisterInfo *MRI; - const RegisterBankInfo *RBI; + const MachineFunction *MF = nullptr; + const TargetMachine *TM = nullptr; + const TargetInstrInfo *TII = nullptr; + const TargetRegisterInfo *TRI = nullptr; + const MachineRegisterInfo *MRI = nullptr; + const RegisterBankInfo *RBI = nullptr; - unsigned foundErrors; + unsigned foundErrors = 0; // Avoid querying the MachineFunctionProperties for each operand. - bool isFunctionRegBankSelected; - bool isFunctionSelected; - bool isFunctionTracksDebugUserValues; + bool isFunctionRegBankSelected = false; + bool isFunctionSelected = false; + bool isFunctionTracksDebugUserValues = false; using RegVector = SmallVector<Register, 16>; using RegMaskVector = SmallVector<const uint32_t *, 4>; @@ -115,8 +115,8 @@ namespace { using RegMap = DenseMap<Register, const MachineInstr *>; using BlockSet = SmallPtrSet<const MachineBasicBlock *, 8>; - const MachineInstr *FirstNonPHI; - const MachineInstr *FirstTerminator; + const MachineInstr *FirstNonPHI = nullptr; + const MachineInstr *FirstTerminator = nullptr; BlockSet FunctionBlocks; BitVector regsReserved; @@ -208,10 +208,10 @@ namespace { } // Analysis information if available - LiveVariables *LiveVars; - LiveIntervals *LiveInts; - LiveStacks *LiveStks; - SlotIndexes *Indexes; + LiveVariables *LiveVars = nullptr; + LiveIntervals *LiveInts = nullptr; + LiveStacks *LiveStks = nullptr; + SlotIndexes *Indexes = nullptr; void visitMachineFunctionBefore(); void visitMachineBasicBlockBefore(const MachineBasicBlock *MBB); @@ -296,6 +296,8 @@ namespace { void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addUsedIfAvailable<LiveStacks>(); AU.addUsedIfAvailable<LiveVariables>(); + AU.addUsedIfAvailable<SlotIndexes>(); + AU.addUsedIfAvailable<LiveIntervals>(); AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -627,8 +629,11 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { // it is an entry block or landing pad. for (const auto &LI : MBB->liveins()) { if (isAllocatable(LI.PhysReg) && !MBB->isEHPad() && - MBB->getIterator() != MBB->getParent()->begin()) { - report("MBB has allocatable live-in, but isn't entry or landing-pad.", MBB); + MBB->getIterator() != MBB->getParent()->begin() && + !MBB->isInlineAsmBrIndirectTarget()) { + report("MBB has allocatable live-in, but isn't entry, landing-pad, or " + "inlineasm-br-indirect-target.", + MBB); report_context(LI.PhysReg); } } @@ -1746,6 +1751,13 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { report("alignment immediate must be >= 1", MI); break; } + case TargetOpcode::G_CONSTANT_POOL: { + if (!MI->getOperand(1).isCPI()) + report("Src operand 1 must be a constant pool index", MI); + if (!MRI->getType(MI->getOperand(0).getReg()).isPointer()) + report("Dst operand 0 must be a pointer", MI); + break; + } default: break; } @@ -2162,6 +2174,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } const RegisterBank *RegBank = MRI->getRegBankOrNull(Reg); + const RegisterBankInfo *RBI = MF->getSubtarget().getRegBankInfo(); // If we're post-RegBankSelect, the gvreg must have a bank. if (!RegBank && isFunctionRegBankSelected) { @@ -2173,12 +2186,12 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { // Make sure the register fits into its register bank if any. if (RegBank && Ty.isValid() && - RegBank->getSize() < Ty.getSizeInBits()) { + RBI->getMaximumSize(RegBank->getID()) < Ty.getSizeInBits()) { report("Register bank is too small for virtual register", MO, MONum); errs() << "Register bank " << RegBank->getName() << " too small(" - << RegBank->getSize() << ") to fit " << Ty.getSizeInBits() - << "-bits\n"; + << RBI->getMaximumSize(RegBank->getID()) << ") to fit " + << Ty.getSizeInBits() << "-bits\n"; return; } } @@ -2427,12 +2440,11 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) { SlotIndex UseIdx = LiveInts->getInstructionIndex(*MI); // Check the cached regunit intervals. if (Reg.isPhysical() && !isReserved(Reg)) { - for (MCRegUnitIterator Units(Reg.asMCReg(), TRI); Units.isValid(); - ++Units) { - if (MRI->isReservedRegUnit(*Units)) + for (MCRegUnit Unit : TRI->regunits(Reg.asMCReg())) { + if (MRI->isReservedRegUnit(Unit)) continue; - if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units)) - checkLivenessAtUse(MO, MONum, UseIdx, *LR, *Units); + if (const LiveRange *LR = LiveInts->getCachedRegUnit(Unit)) + checkLivenessAtUse(MO, MONum, UseIdx, *LR, Unit); } } @@ -3096,108 +3108,109 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR, return; } - // No more checks for live-out segments. - if (S.end == LiveInts->getMBBEndIdx(EndMBB)) - return; - - // RegUnit intervals are allowed dead phis. - if (!Reg.isVirtual() && VNI->isPHIDef() && S.start == VNI->def && - S.end == VNI->def.getDeadSlot()) - return; - - // The live segment is ending inside EndMBB - const MachineInstr *MI = - LiveInts->getInstructionFromIndex(S.end.getPrevSlot()); - if (!MI) { - report("Live segment doesn't end at a valid instruction", EndMBB); - report_context(LR, Reg, LaneMask); - report_context(S); - return; - } - - // The block slot must refer to a basic block boundary. - if (S.end.isBlock()) { - report("Live segment ends at B slot of an instruction", EndMBB); - report_context(LR, Reg, LaneMask); - report_context(S); - } + // Checks for non-live-out segments. + if (S.end != LiveInts->getMBBEndIdx(EndMBB)) { + // RegUnit intervals are allowed dead phis. + if (!Reg.isVirtual() && VNI->isPHIDef() && S.start == VNI->def && + S.end == VNI->def.getDeadSlot()) + return; - if (S.end.isDead()) { - // Segment ends on the dead slot. - // That means there must be a dead def. - if (!SlotIndex::isSameInstr(S.start, S.end)) { - report("Live segment ending at dead slot spans instructions", EndMBB); + // The live segment is ending inside EndMBB + const MachineInstr *MI = + LiveInts->getInstructionFromIndex(S.end.getPrevSlot()); + if (!MI) { + report("Live segment doesn't end at a valid instruction", EndMBB); report_context(LR, Reg, LaneMask); report_context(S); + return; } - } - // After tied operands are rewritten, a live segment can only end at an - // early-clobber slot if it is being redefined by an early-clobber def. - // TODO: Before tied operands are rewritten, a live segment can only end at an - // early-clobber slot if the last use is tied to an early-clobber def. - if (MF->getProperties().hasProperty( - MachineFunctionProperties::Property::TiedOpsRewritten) && - S.end.isEarlyClobber()) { - if (I+1 == LR.end() || (I+1)->start != S.end) { - report("Live segment ending at early clobber slot must be " - "redefined by an EC def in the same instruction", EndMBB); + // The block slot must refer to a basic block boundary. + if (S.end.isBlock()) { + report("Live segment ends at B slot of an instruction", EndMBB); report_context(LR, Reg, LaneMask); report_context(S); } - } - // The following checks only apply to virtual registers. Physreg liveness - // is too weird to check. - if (Reg.isVirtual()) { - // A live segment can end with either a redefinition, a kill flag on a - // use, or a dead flag on a def. - bool hasRead = false; - bool hasSubRegDef = false; - bool hasDeadDef = false; - for (ConstMIBundleOperands MOI(*MI); MOI.isValid(); ++MOI) { - if (!MOI->isReg() || MOI->getReg() != Reg) - continue; - unsigned Sub = MOI->getSubReg(); - LaneBitmask SLM = Sub != 0 ? TRI->getSubRegIndexLaneMask(Sub) - : LaneBitmask::getAll(); - if (MOI->isDef()) { - if (Sub != 0) { - hasSubRegDef = true; - // An operand %0:sub0 reads %0:sub1..n. Invert the lane - // mask for subregister defs. Read-undef defs will be handled by - // readsReg below. - SLM = ~SLM; - } - if (MOI->isDead()) - hasDeadDef = true; + if (S.end.isDead()) { + // Segment ends on the dead slot. + // That means there must be a dead def. + if (!SlotIndex::isSameInstr(S.start, S.end)) { + report("Live segment ending at dead slot spans instructions", EndMBB); + report_context(LR, Reg, LaneMask); + report_context(S); } - if (LaneMask.any() && (LaneMask & SLM).none()) - continue; - if (MOI->readsReg()) - hasRead = true; } - if (S.end.isDead()) { - // Make sure that the corresponding machine operand for a "dead" live - // range has the dead flag. We cannot perform this check for subregister - // liveranges as partially dead values are allowed. - if (LaneMask.none() && !hasDeadDef) { - report("Instruction ending live segment on dead slot has no dead flag", - MI); + + // After tied operands are rewritten, a live segment can only end at an + // early-clobber slot if it is being redefined by an early-clobber def. + // TODO: Before tied operands are rewritten, a live segment can only end at + // an early-clobber slot if the last use is tied to an early-clobber def. + if (MF->getProperties().hasProperty( + MachineFunctionProperties::Property::TiedOpsRewritten) && + S.end.isEarlyClobber()) { + if (I + 1 == LR.end() || (I + 1)->start != S.end) { + report("Live segment ending at early clobber slot must be " + "redefined by an EC def in the same instruction", + EndMBB); report_context(LR, Reg, LaneMask); report_context(S); } - } else { - if (!hasRead) { - // When tracking subregister liveness, the main range must start new - // values on partial register writes, even if there is no read. - if (!MRI->shouldTrackSubRegLiveness(Reg) || LaneMask.any() || - !hasSubRegDef) { - report("Instruction ending live segment doesn't read the register", - MI); + } + + // The following checks only apply to virtual registers. Physreg liveness + // is too weird to check. + if (Reg.isVirtual()) { + // A live segment can end with either a redefinition, a kill flag on a + // use, or a dead flag on a def. + bool hasRead = false; + bool hasSubRegDef = false; + bool hasDeadDef = false; + for (ConstMIBundleOperands MOI(*MI); MOI.isValid(); ++MOI) { + if (!MOI->isReg() || MOI->getReg() != Reg) + continue; + unsigned Sub = MOI->getSubReg(); + LaneBitmask SLM = + Sub != 0 ? TRI->getSubRegIndexLaneMask(Sub) : LaneBitmask::getAll(); + if (MOI->isDef()) { + if (Sub != 0) { + hasSubRegDef = true; + // An operand %0:sub0 reads %0:sub1..n. Invert the lane + // mask for subregister defs. Read-undef defs will be handled by + // readsReg below. + SLM = ~SLM; + } + if (MOI->isDead()) + hasDeadDef = true; + } + if (LaneMask.any() && (LaneMask & SLM).none()) + continue; + if (MOI->readsReg()) + hasRead = true; + } + if (S.end.isDead()) { + // Make sure that the corresponding machine operand for a "dead" live + // range has the dead flag. We cannot perform this check for subregister + // liveranges as partially dead values are allowed. + if (LaneMask.none() && !hasDeadDef) { + report( + "Instruction ending live segment on dead slot has no dead flag", + MI); report_context(LR, Reg, LaneMask); report_context(S); } + } else { + if (!hasRead) { + // When tracking subregister liveness, the main range must start new + // values on partial register writes, even if there is no read. + if (!MRI->shouldTrackSubRegLiveness(Reg) || LaneMask.any() || + !hasSubRegDef) { + report("Instruction ending live segment doesn't read the register", + MI); + report_context(LR, Reg, LaneMask); + report_context(S); + } + } } } } |