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