aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:20:56 +0000
commitbdd1243df58e60e85101c09001d9812a789b6bc4 (patch)
treea1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp
parent781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff)
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp186
1 files changed, 140 insertions, 46 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp b/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp
index 93e68918b632..ddd5a027c2cd 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/contrib/llvm-project/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -73,6 +73,7 @@
#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"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
@@ -294,6 +295,7 @@ namespace {
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addUsedIfAvailable<LiveStacks>();
+ AU.addUsedIfAvailable<LiveVariables>();
AU.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -564,7 +566,7 @@ void MachineVerifier::report_context_vreg(Register VReg) const {
}
void MachineVerifier::report_context_vreg_regunit(Register VRegOrUnit) const {
- if (Register::isVirtualRegister(VRegOrUnit)) {
+ if (VRegOrUnit.isVirtual()) {
report_context_vreg(VRegOrUnit);
} else {
errs() << "- regunit: " << printRegUnit(VRegOrUnit, TRI) << '\n';
@@ -632,6 +634,13 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
}
}
+ if (MBB->isIRBlockAddressTaken()) {
+ if (!MBB->getAddressTakenIRBlock()->hasAddressTaken())
+ report("ir-block-address-taken is associated with basic block not used by "
+ "a blockaddress.",
+ MBB);
+ }
+
// Count the number of landing pad successors.
SmallPtrSet<const MachineBasicBlock*, 4> LandingPadSuccs;
for (const auto *succ : MBB->successors()) {
@@ -821,8 +830,12 @@ void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) {
if (!FirstTerminator)
FirstTerminator = MI;
} else if (FirstTerminator) {
- report("Non-terminator instruction after the first terminator", MI);
- errs() << "First terminator was:\t" << *FirstTerminator;
+ // For GlobalISel, G_INVOKE_REGION_START is a terminator that we allow to
+ // precede non-terminators.
+ if (FirstTerminator->getOpcode() != TargetOpcode::G_INVOKE_REGION_START) {
+ report("Non-terminator instruction after the first terminator", MI);
+ errs() << "First terminator was:\t" << *FirstTerminator;
+ }
}
}
@@ -869,6 +882,34 @@ void MachineVerifier::verifyInlineAsm(const MachineInstr *MI) {
if (!MO.isReg() || !MO.isImplicit())
report("Expected implicit register after groups", &MO, OpNo);
}
+
+ if (MI->getOpcode() == TargetOpcode::INLINEASM_BR) {
+ const MachineBasicBlock *MBB = MI->getParent();
+
+ for (unsigned i = InlineAsm::MIOp_FirstOperand, e = MI->getNumOperands();
+ i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+
+ if (!MO.isMBB())
+ continue;
+
+ // Check the successor & predecessor lists look ok, assume they are
+ // not. Find the indirect target without going through the successors.
+ const MachineBasicBlock *IndirectTargetMBB = MO.getMBB();
+ if (!IndirectTargetMBB) {
+ report("INLINEASM_BR indirect target does not exist", &MO, i);
+ break;
+ }
+
+ if (!MBB->isSuccessor(IndirectTargetMBB))
+ report("INLINEASM_BR indirect target missing from successor list", &MO,
+ i);
+
+ if (!IndirectTargetMBB->isPredecessor(MBB))
+ report("INLINEASM_BR indirect target predecessor list missing parent",
+ &MO, i);
+ }
+ }
}
bool MachineVerifier::verifyAllRegOpsScalar(const MachineInstr &MI,
@@ -937,11 +978,11 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
SmallVector<LLT, 4> Types;
for (unsigned I = 0, E = std::min(MCID.getNumOperands(), NumOps);
I != E; ++I) {
- if (!MCID.OpInfo[I].isGenericType())
+ if (!MCID.operands()[I].isGenericType())
continue;
// Generic instructions specify type equality constraints between some of
// their operands. Make sure these are consistent.
- size_t TypeIdx = MCID.OpInfo[I].getGenericTypeIndex();
+ size_t TypeIdx = MCID.operands()[I].getGenericTypeIndex();
Types.resize(std::max(TypeIdx + 1, Types.size()));
const MachineOperand *MO = &MI->getOperand(I);
@@ -969,7 +1010,7 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
// Generic opcodes must not have physical register operands.
for (unsigned I = 0; I < MI->getNumOperands(); ++I) {
const MachineOperand *MO = &MI->getOperand(I);
- if (MO->isReg() && Register::isPhysicalRegister(MO->getReg()))
+ if (MO->isReg() && MO->getReg().isPhysical())
report("Generic instruction cannot have physical register", MO, I);
}
@@ -1274,17 +1315,38 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
break;
}
case TargetOpcode::G_UNMERGE_VALUES: {
+ unsigned NumDsts = MI->getNumOperands() - 1;
LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
- LLT SrcTy = MRI->getType(MI->getOperand(MI->getNumOperands()-1).getReg());
- // For now G_UNMERGE can split vectors.
- for (unsigned i = 0; i < MI->getNumOperands()-1; ++i) {
- if (MRI->getType(MI->getOperand(i).getReg()) != DstTy)
+ for (unsigned i = 1; i < NumDsts; ++i) {
+ if (MRI->getType(MI->getOperand(i).getReg()) != DstTy) {
report("G_UNMERGE_VALUES destination types do not match", MI);
+ break;
+ }
}
- if (SrcTy.getSizeInBits() !=
- (DstTy.getSizeInBits() * (MI->getNumOperands() - 1))) {
- report("G_UNMERGE_VALUES source operand does not cover dest operands",
- MI);
+
+ LLT SrcTy = MRI->getType(MI->getOperand(NumDsts).getReg());
+ if (DstTy.isVector()) {
+ // This case is the converse of G_CONCAT_VECTORS.
+ if (!SrcTy.isVector() || SrcTy.getScalarType() != DstTy.getScalarType() ||
+ SrcTy.getNumElements() != NumDsts * DstTy.getNumElements())
+ report("G_UNMERGE_VALUES source operand does not match vector "
+ "destination operands",
+ MI);
+ } else if (SrcTy.isVector()) {
+ // This case is the converse of G_BUILD_VECTOR, but relaxed to allow
+ // mismatched types as long as the total size matches:
+ // %0:_(s64), %1:_(s64) = G_UNMERGE_VALUES %2:_(<4 x s32>)
+ if (SrcTy.getSizeInBits() != NumDsts * DstTy.getSizeInBits())
+ report("G_UNMERGE_VALUES vector source operand does not match scalar "
+ "destination operands",
+ MI);
+ } else {
+ // This case is the converse of G_MERGE_VALUES.
+ if (SrcTy.getSizeInBits() != NumDsts * DstTy.getSizeInBits()) {
+ report("G_UNMERGE_VALUES scalar source operand does not match scalar "
+ "destination operands",
+ MI);
+ }
}
break;
}
@@ -1438,10 +1500,9 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
bool NoSideEffects = MI->getOpcode() == TargetOpcode::G_INTRINSIC;
unsigned IntrID = IntrIDOp.getIntrinsicID();
if (IntrID != 0 && IntrID < Intrinsic::num_intrinsics) {
- AttributeList Attrs
- = Intrinsic::getAttributes(MF->getFunction().getContext(),
- static_cast<Intrinsic::ID>(IntrID));
- bool DeclHasSideEffects = !Attrs.hasFnAttr(Attribute::ReadNone);
+ AttributeList Attrs = Intrinsic::getAttributes(
+ MF->getFunction().getContext(), static_cast<Intrinsic::ID>(IntrID));
+ bool DeclHasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
if (NoSideEffects && DeclHasSideEffects) {
report("G_INTRINSIC used with intrinsic that accesses memory", MI);
break;
@@ -1678,16 +1739,11 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
report("Incorrect floating-point class set (operand 2)", MI);
break;
}
- const MachineOperand &SemanticsMO = MI->getOperand(3);
- if (!SemanticsMO.isImm()) {
- report("floating-point semantics (operand 3) must be an immediate", MI);
- break;
- }
- int64_t Semantics = SemanticsMO.getImm();
- if (Semantics < 0 || Semantics > APFloat::S_MaxSemantics) {
- report("Incorrect floating-point semantics (operand 3)", MI);
- break;
- }
+ break;
+ }
+ case TargetOpcode::G_ASSERT_ALIGN: {
+ if (MI->getOperand(2).getImm() < 1)
+ report("alignment immediate must be >= 1", MI);
break;
}
default:
@@ -1888,6 +1944,36 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
break;
}
} break;
+ case TargetOpcode::REG_SEQUENCE: {
+ unsigned NumOps = MI->getNumOperands();
+ if (!(NumOps & 1)) {
+ report("Invalid number of operands for REG_SEQUENCE", MI);
+ break;
+ }
+
+ for (unsigned I = 1; I != NumOps; I += 2) {
+ const MachineOperand &RegOp = MI->getOperand(I);
+ const MachineOperand &SubRegOp = MI->getOperand(I + 1);
+
+ if (!RegOp.isReg())
+ report("Invalid register operand for REG_SEQUENCE", &RegOp, I);
+
+ if (!SubRegOp.isImm() || SubRegOp.getImm() == 0 ||
+ SubRegOp.getImm() >= TRI->getNumSubRegIndices()) {
+ report("Invalid subregister index operand for REG_SEQUENCE",
+ &SubRegOp, I + 1);
+ }
+ }
+
+ Register DstReg = MI->getOperand(0).getReg();
+ if (DstReg.isPhysical())
+ report("REG_SEQUENCE does not support physical register results", MI);
+
+ if (MI->getOperand(0).getSubReg())
+ report("Invalid subreg result for REG_SEQUENCE", MI);
+
+ break;
+ }
}
}
@@ -1901,7 +1987,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
// The first MCID.NumDefs operands must be explicit register defines
if (MONum < NumDefs) {
- const MCOperandInfo &MCOI = MCID.OpInfo[MONum];
+ const MCOperandInfo &MCOI = MCID.operands()[MONum];
if (!MO->isReg())
report("Explicit definition must be a register", MO, MONum);
else if (!MO->isDef() && !MCOI.isOptionalDef())
@@ -1909,7 +1995,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
else if (MO->isImplicit())
report("Explicit definition marked as implicit", MO, MONum);
} else if (MONum < MCID.getNumOperands()) {
- const MCOperandInfo &MCOI = MCID.OpInfo[MONum];
+ const MCOperandInfo &MCOI = MCID.operands()[MONum];
// Don't check if it's the last operand in a variadic instruction. See,
// e.g., LDM_RET in the arm back end. Check non-variadic operands only.
bool IsOptional = MI->isVariadic() && MONum == MCID.getNumOperands() - 1;
@@ -1941,11 +2027,11 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
report("Operand should be tied", MO, MONum);
else if (unsigned(TiedTo) != MI->findTiedOperandIdx(MONum))
report("Tied def doesn't match MCInstrDesc", MO, MONum);
- else if (Register::isPhysicalRegister(MO->getReg())) {
+ else if (MO->getReg().isPhysical()) {
const MachineOperand &MOTied = MI->getOperand(TiedTo);
if (!MOTied.isReg())
report("Tied counterpart must be a register", &MOTied, TiedTo);
- else if (Register::isPhysicalRegister(MOTied.getReg()) &&
+ else if (MOTied.getReg().isPhysical() &&
MO->getReg() != MOTied.getReg())
report("Tied physical registers must match.", &MOTied, TiedTo);
}
@@ -2017,7 +2103,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
// Check register classes.
unsigned SubIdx = MO->getSubReg();
- if (Register::isPhysicalRegister(Reg)) {
+ if (Reg.isPhysical()) {
if (SubIdx) {
report("Illegal subregister index for physical register", MO, MONum);
return;
@@ -2255,8 +2341,18 @@ void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO,
bool SubRangeCheck,
LaneBitmask LaneMask) {
if (const VNInfo *VNI = LR.getVNInfoAt(DefIdx)) {
- assert(VNI && "NULL valno is not allowed");
- if (VNI->def != DefIdx) {
+ // The LR can correspond to the whole reg and its def slot is not obliged
+ // to be the same as the MO' def slot. E.g. when we check here "normal"
+ // subreg MO but there is other EC subreg MO in the same instruction so the
+ // whole reg has EC def slot and differs from the currently checked MO' def
+ // slot. For example:
+ // %0 [16e,32r:0) 0@16e L..3 [16e,32r:0) 0@16e L..C [16r,32r:0) 0@16r
+ // Check that there is an early-clobber def of the same superregister
+ // somewhere is performed in visitMachineFunctionAfter()
+ if (((SubRangeCheck || MO->getSubReg() == 0) && VNI->def != DefIdx) ||
+ !SlotIndex::isSameInstr(VNI->def, DefIdx) ||
+ (VNI->def != DefIdx &&
+ (!VNI->def.isEarlyClobber() || !DefIdx.isRegister()))) {
report("Inconsistent valno->def", MO, MONum);
report_context_liverange(LR);
report_context_vreg_regunit(VRegOrUnit);
@@ -2277,8 +2373,7 @@ void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO,
if (MO->isDead()) {
LiveQueryResult LRQ = LR.Query(DefIdx);
if (!LRQ.isDeadDef()) {
- assert(Register::isVirtualRegister(VRegOrUnit) &&
- "Expecting a virtual register.");
+ assert(VRegOrUnit.isVirtual() && "Expecting a virtual register.");
// A dead subreg def only tells us that the specific subreg is dead. There
// could be other non-dead defs of other subregs, or we could have other
// parts of the register being live through the instruction. So unless we
@@ -2688,7 +2783,7 @@ void MachineVerifier::checkPHIOps(const MachineBasicBlock &MBB) {
MODef.isEarlyClobber() || MODef.isDebug())
report("Unexpected flag on PHI operand", &MODef, 0);
Register DefReg = MODef.getReg();
- if (!Register::isVirtualRegister(DefReg))
+ if (!DefReg.isVirtual())
report("Expected first PHI operand to be a virtual register", &MODef, 0);
for (unsigned I = 1, E = Phi.getNumOperands(); I != E; I += 2) {
@@ -2920,12 +3015,11 @@ void MachineVerifier::verifyLiveRangeValue(const LiveRange &LR,
for (ConstMIBundleOperands MOI(*MI); MOI.isValid(); ++MOI) {
if (!MOI->isReg() || !MOI->isDef())
continue;
- if (Register::isVirtualRegister(Reg)) {
+ if (Reg.isVirtual()) {
if (MOI->getReg() != Reg)
continue;
} else {
- if (!Register::isPhysicalRegister(MOI->getReg()) ||
- !TRI->hasRegUnit(MOI->getReg(), Reg))
+ if (!MOI->getReg().isPhysical() || !TRI->hasRegUnit(MOI->getReg(), Reg))
continue;
}
if (LaneMask.any() &&
@@ -3007,8 +3101,8 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
return;
// RegUnit intervals are allowed dead phis.
- if (!Register::isVirtualRegister(Reg) && VNI->isPHIDef() &&
- S.start == VNI->def && S.end == VNI->def.getDeadSlot())
+ if (!Reg.isVirtual() && VNI->isPHIDef() && S.start == VNI->def &&
+ S.end == VNI->def.getDeadSlot())
return;
// The live segment is ending inside EndMBB
@@ -3055,7 +3149,7 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
// The following checks only apply to virtual registers. Physreg liveness
// is too weird to check.
- if (Register::isVirtualRegister(Reg)) {
+ 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;
@@ -3128,7 +3222,7 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
while (true) {
assert(LiveInts->isLiveInToMBB(LR, &*MFI));
// We don't know how to track physregs into a landing pad.
- if (!Register::isVirtualRegister(Reg) && MFI->isEHPad()) {
+ if (!Reg.isVirtual() && MFI->isEHPad()) {
if (&*MFI == EndMBB)
break;
++MFI;
@@ -3196,7 +3290,7 @@ void MachineVerifier::verifyLiveRange(const LiveRange &LR, Register Reg,
void MachineVerifier::verifyLiveInterval(const LiveInterval &LI) {
Register Reg = LI.reg();
- assert(Register::isVirtualRegister(Reg));
+ assert(Reg.isVirtual());
verifyLiveRange(LI, Reg);
LaneBitmask Mask;