diff options
Diffstat (limited to 'contrib/llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r-- | contrib/llvm/lib/CodeGen/MachineVerifier.cpp | 179 |
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 { |