aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineVerifier.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-07-26 19:03:47 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-26 19:04:23 +0000
commit7fa27ce4a07f19b07799a767fc29416f3b625afb (patch)
tree27825c83636c4de341eb09a74f49f5d38a15d165 /llvm/lib/CodeGen/MachineVerifier.cpp
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r--llvm/lib/CodeGen/MachineVerifier.cpp239
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);
+ }
+ }
}
}
}