aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/CodeGen/MachineVerifier.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r--contrib/llvm/lib/CodeGen/MachineVerifier.cpp179
1 files changed, 139 insertions, 40 deletions
diff --git a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp
index e0cc2ca9a2a2..d644e41abc5b 100644
--- a/contrib/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/contrib/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -239,7 +239,8 @@ namespace {
void report(const char *msg, const MachineFunction *MF);
void report(const char *msg, const MachineBasicBlock *MBB);
void report(const char *msg, const MachineInstr *MI);
- void report(const char *msg, const MachineOperand *MO, unsigned MONum);
+ void report(const char *msg, const MachineOperand *MO, unsigned MONum,
+ LLT MOVRegType = LLT{});
void report_context(const LiveInterval &LI) const;
void report_context(const LiveRange &LR, unsigned VRegUnit,
@@ -250,16 +251,16 @@ namespace {
void report_context_liverange(const LiveRange &LR) const;
void report_context_lanemask(LaneBitmask LaneMask) const;
void report_context_vreg(unsigned VReg) const;
- void report_context_vreg_regunit(unsigned VRegOrRegUnit) const;
+ void report_context_vreg_regunit(unsigned VRegOrUnit) const;
void verifyInlineAsm(const MachineInstr *MI);
void checkLiveness(const MachineOperand *MO, unsigned MONum);
void checkLivenessAtUse(const MachineOperand *MO, unsigned MONum,
- SlotIndex UseIdx, const LiveRange &LR, unsigned Reg,
+ SlotIndex UseIdx, const LiveRange &LR, unsigned VRegOrUnit,
LaneBitmask LaneMask = LaneBitmask::getNone());
void checkLivenessAtDef(const MachineOperand *MO, unsigned MONum,
- SlotIndex DefIdx, const LiveRange &LR, unsigned Reg,
+ SlotIndex DefIdx, const LiveRange &LR, unsigned VRegOrUnit,
LaneBitmask LaneMask = LaneBitmask::getNone());
void markReachable(const MachineBasicBlock *MBB);
@@ -359,11 +360,15 @@ unsigned MachineVerifier::verify(MachineFunction &MF) {
TRI = MF.getSubtarget().getRegisterInfo();
MRI = &MF.getRegInfo();
- isFunctionRegBankSelected = MF.getProperties().hasProperty(
- MachineFunctionProperties::Property::RegBankSelected);
- isFunctionSelected = MF.getProperties().hasProperty(
- MachineFunctionProperties::Property::Selected);
-
+ const bool isFunctionFailedISel = MF.getProperties().hasProperty(
+ MachineFunctionProperties::Property::FailedISel);
+ isFunctionRegBankSelected =
+ !isFunctionFailedISel &&
+ MF.getProperties().hasProperty(
+ MachineFunctionProperties::Property::RegBankSelected);
+ isFunctionSelected = !isFunctionFailedISel &&
+ MF.getProperties().hasProperty(
+ MachineFunctionProperties::Property::Selected);
LiveVars = nullptr;
LiveInts = nullptr;
LiveStks = nullptr;
@@ -486,15 +491,14 @@ void MachineVerifier::report(const char *msg, const MachineInstr *MI) {
if (Indexes && Indexes->hasIndex(*MI))
errs() << Indexes->getInstructionIndex(*MI) << '\t';
MI->print(errs(), /*SkipOpers=*/true);
- errs() << '\n';
}
-void MachineVerifier::report(const char *msg,
- const MachineOperand *MO, unsigned MONum) {
+void MachineVerifier::report(const char *msg, const MachineOperand *MO,
+ unsigned MONum, LLT MOVRegType) {
assert(MO);
report(msg, MO->getParent());
errs() << "- operand " << MONum << ": ";
- MO->print(errs(), TRI);
+ MO->print(errs(), MOVRegType, TRI);
errs() << "\n";
}
@@ -642,7 +646,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
!(AsmInfo &&
AsmInfo->getExceptionHandlingType() == ExceptionHandling::SjLj &&
BB && isa<SwitchInst>(BB->getTerminator())) &&
- !isFuncletEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
+ !isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
report("MBB has more than one landing pad successor", MBB);
// Call AnalyzeBranch. If it succeeds, there several more conditions to check.
@@ -873,11 +877,11 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
if (MI->getNumOperands() < MCID.getNumOperands()) {
report("Too few operands", MI);
errs() << MCID.getNumOperands() << " operands expected, but "
- << MI->getNumOperands() << " given.\n";
+ << MI->getNumOperands() << " given.\n";
}
if (MI->isPHI() && MF->getProperties().hasProperty(
- MachineFunctionProperties::Property::NoPHIs))
+ MachineFunctionProperties::Property::NoPHIs))
report("Found PHI instruction with NoPHIs property set", MI);
// Check the tied operands.
@@ -886,7 +890,8 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
// Check the MachineMemOperands for basic consistency.
for (MachineInstr::mmo_iterator I = MI->memoperands_begin(),
- E = MI->memoperands_end(); I != E; ++I) {
+ E = MI->memoperands_end();
+ I != E; ++I) {
if ((*I)->isLoad() && !MI->mayLoad())
report("Missing mayLoad flag", MI);
if ((*I)->isStore() && !MI->mayStore())
@@ -897,7 +902,7 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
// Other instructions must have one, unless they are inside a bundle.
if (LiveInts) {
bool mapped = !LiveInts->isNotInMIMap(*MI);
- if (MI->isDebugValue()) {
+ if (MI->isDebugInstr()) {
if (mapped)
report("Debug instruction has a slot index", MI);
} else if (MI->isInsideBundle()) {
@@ -909,32 +914,42 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
}
}
- // Check types.
if (isPreISelGenericOpcode(MCID.getOpcode())) {
if (isFunctionSelected)
report("Unexpected generic instruction in a Selected function", MI);
- // Generic instructions specify equality constraints between some
- // of their operands. Make sure these are consistent.
+ // Check types.
SmallVector<LLT, 4> Types;
- for (unsigned i = 0; i < MCID.getNumOperands(); ++i) {
- if (!MCID.OpInfo[i].isGenericType())
+ for (unsigned I = 0; I < MCID.getNumOperands(); ++I) {
+ if (!MCID.OpInfo[I].isGenericType())
continue;
- size_t TypeIdx = MCID.OpInfo[i].getGenericTypeIndex();
+ // Generic instructions specify type equality constraints between some of
+ // their operands. Make sure these are consistent.
+ size_t TypeIdx = MCID.OpInfo[I].getGenericTypeIndex();
Types.resize(std::max(TypeIdx + 1, Types.size()));
- LLT OpTy = MRI->getType(MI->getOperand(i).getReg());
- if (Types[TypeIdx].isValid() && Types[TypeIdx] != OpTy)
- report("type mismatch in generic instruction", MI);
- Types[TypeIdx] = OpTy;
+ const MachineOperand *MO = &MI->getOperand(I);
+ LLT OpTy = MRI->getType(MO->getReg());
+ // Don't report a type mismatch if there is no actual mismatch, only a
+ // type missing, to reduce noise:
+ if (OpTy.isValid()) {
+ // Only the first valid type for a type index will be printed: don't
+ // overwrite it later so it's always clear which type was expected:
+ if (!Types[TypeIdx].isValid())
+ Types[TypeIdx] = OpTy;
+ else if (Types[TypeIdx] != OpTy)
+ report("Type mismatch in generic instruction", MO, I, OpTy);
+ } else {
+ // Generic instructions must have types attached to their operands.
+ report("Generic instruction is missing a virtual register type", MO, I);
+ }
}
- }
- // Generic opcodes must not have physical register operands.
- if (isPreISelGenericOpcode(MCID.getOpcode())) {
- for (auto &Op : MI->operands()) {
- if (Op.isReg() && TargetRegisterInfo::isPhysicalRegister(Op.getReg()))
- report("Generic instruction cannot have physical register", 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() && TargetRegisterInfo::isPhysicalRegister(MO->getReg()))
+ report("Generic instruction cannot have physical register", MO, I);
}
}
@@ -971,6 +986,88 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {
MI);
break;
}
+ case TargetOpcode::G_SEXT:
+ case TargetOpcode::G_ZEXT:
+ case TargetOpcode::G_ANYEXT:
+ case TargetOpcode::G_TRUNC:
+ case TargetOpcode::G_FPEXT:
+ case TargetOpcode::G_FPTRUNC: {
+ // Number of operands and presense of types is already checked (and
+ // reported in case of any issues), so no need to report them again. As
+ // we're trying to report as many issues as possible at once, however, the
+ // instructions aren't guaranteed to have the right number of operands or
+ // types attached to them at this point
+ assert(MCID.getNumOperands() == 2 && "Expected 2 operands G_*{EXT,TRUNC}");
+ if (MI->getNumOperands() < MCID.getNumOperands())
+ break;
+ LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
+ LLT SrcTy = MRI->getType(MI->getOperand(1).getReg());
+ if (!DstTy.isValid() || !SrcTy.isValid())
+ break;
+
+ LLT DstElTy = DstTy.isVector() ? DstTy.getElementType() : DstTy;
+ LLT SrcElTy = SrcTy.isVector() ? SrcTy.getElementType() : SrcTy;
+ if (DstElTy.isPointer() || SrcElTy.isPointer())
+ report("Generic extend/truncate can not operate on pointers", MI);
+
+ if (DstTy.isVector() != SrcTy.isVector()) {
+ report("Generic extend/truncate must be all-vector or all-scalar", MI);
+ // Generally we try to report as many issues as possible at once, but in
+ // this case it's not clear what should we be comparing the size of the
+ // scalar with: the size of the whole vector or its lane. Instead of
+ // making an arbitrary choice and emitting not so helpful message, let's
+ // avoid the extra noise and stop here.
+ break;
+ }
+ if (DstTy.isVector() && DstTy.getNumElements() != SrcTy.getNumElements())
+ report("Generic vector extend/truncate must preserve number of lanes",
+ MI);
+ unsigned DstSize = DstElTy.getSizeInBits();
+ unsigned SrcSize = SrcElTy.getSizeInBits();
+ switch (MI->getOpcode()) {
+ default:
+ if (DstSize <= SrcSize)
+ report("Generic extend has destination type no larger than source", MI);
+ break;
+ case TargetOpcode::G_TRUNC:
+ case TargetOpcode::G_FPTRUNC:
+ if (DstSize >= SrcSize)
+ report("Generic truncate has destination type no smaller than source",
+ MI);
+ break;
+ }
+ break;
+ }
+ case TargetOpcode::COPY: {
+ if (foundErrors)
+ break;
+ const MachineOperand &DstOp = MI->getOperand(0);
+ const MachineOperand &SrcOp = MI->getOperand(1);
+ LLT DstTy = MRI->getType(DstOp.getReg());
+ LLT SrcTy = MRI->getType(SrcOp.getReg());
+ if (SrcTy.isValid() && DstTy.isValid()) {
+ // If both types are valid, check that the types are the same.
+ if (SrcTy != DstTy) {
+ report("Copy Instruction is illegal with mismatching types", MI);
+ errs() << "Def = " << DstTy << ", Src = " << SrcTy << "\n";
+ }
+ }
+ if (SrcTy.isValid() || DstTy.isValid()) {
+ // If one of them have valid types, let's just check they have the same
+ // size.
+ unsigned SrcSize = TRI->getRegSizeInBits(SrcOp.getReg(), *MRI);
+ unsigned DstSize = TRI->getRegSizeInBits(DstOp.getReg(), *MRI);
+ assert(SrcSize && "Expecting size here");
+ assert(DstSize && "Expecting size here");
+ if (SrcSize != DstSize)
+ if (!DstOp.getSubReg() && !SrcOp.getSubReg()) {
+ report("Copy Instruction is illegal with mismatching sizes", MI);
+ errs() << "Def Size = " << DstSize << ", Src Size = " << SrcSize
+ << "\n";
+ }
+ }
+ break;
+ }
case TargetOpcode::STATEPOINT:
if (!MI->getOperand(StatepointOpers::IDPos).isImm() ||
!MI->getOperand(StatepointOpers::NBytesPos).isImm() ||
@@ -1101,12 +1198,14 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {
}
}
}
- if (MO->isRenamable() &&
- ((MO->isDef() && MI->hasExtraDefRegAllocReq()) ||
- (MO->isUse() && MI->hasExtraSrcRegAllocReq()))) {
- report("Illegal isRenamable setting for opcode with extra regalloc "
- "requirements",
- MO, MONum);
+ if (MO->isRenamable()) {
+ if (MRI->isReserved(Reg)) {
+ report("isRenamable set on reserved register", MO, MONum);
+ return;
+ }
+ }
+ if (MI->isDebugValue() && MO->isUse() && !MO->isDebug()) {
+ report("Use-reg is not IsDebug in a DBG_VALUE", MO, MONum);
return;
}
} else {