diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 | 
| commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
| tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/CodeGen/MachineVerifier.cpp | |
| parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) | |
Notes
Diffstat (limited to 'lib/CodeGen/MachineVerifier.cpp')
| -rw-r--r-- | lib/CodeGen/MachineVerifier.cpp | 164 | 
1 files changed, 135 insertions, 29 deletions
diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index 318776136e24..534d3699db29 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -23,6 +23,7 @@  // the verifier errors.  //===----------------------------------------------------------------------===// +#include "LiveRangeCalc.h"  #include "llvm/ADT/BitVector.h"  #include "llvm/ADT/DenseMap.h"  #include "llvm/ADT/DenseSet.h" @@ -108,6 +109,7 @@ namespace {      using RegMap = DenseMap<unsigned, const MachineInstr *>;      using BlockSet = SmallPtrSet<const MachineBasicBlock *, 8>; +    const MachineInstr *FirstNonPHI;      const MachineInstr *FirstTerminator;      BlockSet FunctionBlocks; @@ -248,6 +250,7 @@ namespace {      void report_context(const LiveRange::Segment &S) const;      void report_context(const VNInfo &VNI) const;      void report_context(SlotIndex Pos) const; +    void report_context(MCPhysReg PhysReg) const;      void report_context_liverange(const LiveRange &LR) const;      void report_context_lanemask(LaneBitmask LaneMask) const;      void report_context_vreg(unsigned VReg) const; @@ -261,6 +264,7 @@ namespace {                              LaneBitmask LaneMask = LaneBitmask::getNone());      void checkLivenessAtDef(const MachineOperand *MO, unsigned MONum,                              SlotIndex DefIdx, const LiveRange &LR, unsigned VRegOrUnit, +                            bool SubRangeCheck = false,                              LaneBitmask LaneMask = LaneBitmask::getNone());      void markReachable(const MachineBasicBlock *MBB); @@ -362,6 +366,13 @@ unsigned MachineVerifier::verify(MachineFunction &MF) {    const bool isFunctionFailedISel = MF.getProperties().hasProperty(        MachineFunctionProperties::Property::FailedISel); + +  // If we're mid-GlobalISel and we already triggered the fallback path then +  // it's expected that the MIR is somewhat broken but that's ok since we'll +  // reset it and clear the FailedISel attribute in ResetMachineFunctions. +  if (isFunctionFailedISel) +    return foundErrors; +    isFunctionRegBankSelected =        !isFunctionFailedISel &&        MF.getProperties().hasProperty( @@ -530,6 +541,10 @@ void MachineVerifier::report_context_liverange(const LiveRange &LR) const {    errs() << "- liverange:   " << LR << '\n';  } +void MachineVerifier::report_context(MCPhysReg PReg) const { +  errs() << "- p. register: " << printReg(PReg, TRI) << '\n'; +} +  void MachineVerifier::report_context_vreg(unsigned VReg) const {    errs() << "- v. register: " << printReg(VReg, TRI) << '\n';  } @@ -599,6 +614,7 @@ static bool matchPair(MachineBasicBlock::const_succ_iterator i,  void  MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {    FirstTerminator = nullptr; +  FirstNonPHI = nullptr;    if (!MF->getProperties().hasProperty(        MachineFunctionProperties::Property::NoPHIs) && MRI->tracksLiveness()) { @@ -608,6 +624,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {        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); +        report_context(LI.PhysReg);        }      }    } @@ -666,7 +683,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {          // out the bottom of the function.        } else if (MBB->succ_size() == LandingPadSuccs.size()) {          // It's possible that the block legitimately ends with a noreturn -        // call or an unreachable, in which case it won't actuall fall +        // call or an unreachable, in which case it won't actually fall          // out of the block.        } else if (MBB->succ_size() != 1+LandingPadSuccs.size()) {          report("MBB exits via unconditional fall-through but doesn't have " @@ -767,7 +784,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {                 "isn't a terminator instruction!", MBB);        }        if (Cond.empty()) { -        report("MBB exits via conditinal branch/branch but there's no " +        report("MBB exits via conditional branch/branch but there's no "                 "condition!", MBB);        }      } else { @@ -880,9 +897,15 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {             << MI->getNumOperands() << " given.\n";    } -  if (MI->isPHI() && MF->getProperties().hasProperty( -                         MachineFunctionProperties::Property::NoPHIs)) -    report("Found PHI instruction with NoPHIs property set", MI); +  if (MI->isPHI()) { +    if (MF->getProperties().hasProperty( +            MachineFunctionProperties::Property::NoPHIs)) +      report("Found PHI instruction with NoPHIs property set", MI); + +    if (FirstNonPHI) +      report("Found PHI instruction after non-PHI", MI); +  } else if (FirstNonPHI == nullptr) +    FirstNonPHI = MI;    // Check the tied operands.    if (MI->isInlineAsm()) @@ -1038,6 +1061,89 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {      }      break;    } +  case TargetOpcode::G_MERGE_VALUES: { +    // G_MERGE_VALUES should only be used to merge scalars into a larger scalar, +    // e.g. s2N = MERGE sN, sN +    // Merging multiple scalars into a vector is not allowed, should use +    // G_BUILD_VECTOR for that. +    LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); +    LLT SrcTy = MRI->getType(MI->getOperand(1).getReg()); +    if (DstTy.isVector() || SrcTy.isVector()) +      report("G_MERGE_VALUES cannot operate on vectors", MI); +    break; +  } +  case TargetOpcode::G_UNMERGE_VALUES: { +    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) +        report("G_UNMERGE_VALUES destination types do not match", MI); +    } +    if (SrcTy.getSizeInBits() != +        (DstTy.getSizeInBits() * (MI->getNumOperands() - 1))) { +      report("G_UNMERGE_VALUES source operand does not cover dest operands", +             MI); +    } +    break; +  } +  case TargetOpcode::G_BUILD_VECTOR: { +    // Source types must be scalars, dest type a vector. Total size of scalars +    // must match the dest vector size. +    LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); +    LLT SrcEltTy = MRI->getType(MI->getOperand(1).getReg()); +    if (!DstTy.isVector() || SrcEltTy.isVector()) +      report("G_BUILD_VECTOR must produce a vector from scalar operands", MI); +    for (unsigned i = 2; i < MI->getNumOperands(); ++i) { +      if (MRI->getType(MI->getOperand(1).getReg()) != +          MRI->getType(MI->getOperand(i).getReg())) +        report("G_BUILD_VECTOR source operand types are not homogeneous", MI); +    } +    if (DstTy.getSizeInBits() != +        SrcEltTy.getSizeInBits() * (MI->getNumOperands() - 1)) +      report("G_BUILD_VECTOR src operands total size don't match dest " +             "size.", +             MI); +    break; +  } +  case TargetOpcode::G_BUILD_VECTOR_TRUNC: { +    // Source types must be scalars, dest type a vector. Scalar types must be +    // larger than the dest vector elt type, as this is a truncating operation. +    LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); +    LLT SrcEltTy = MRI->getType(MI->getOperand(1).getReg()); +    if (!DstTy.isVector() || SrcEltTy.isVector()) +      report("G_BUILD_VECTOR_TRUNC must produce a vector from scalar operands", +             MI); +    for (unsigned i = 2; i < MI->getNumOperands(); ++i) { +      if (MRI->getType(MI->getOperand(1).getReg()) != +          MRI->getType(MI->getOperand(i).getReg())) +        report("G_BUILD_VECTOR_TRUNC source operand types are not homogeneous", +               MI); +    } +    if (SrcEltTy.getSizeInBits() <= DstTy.getElementType().getSizeInBits()) +      report("G_BUILD_VECTOR_TRUNC source operand types are not larger than " +             "dest elt type", +             MI); +    break; +  } +  case TargetOpcode::G_CONCAT_VECTORS: { +    // Source types should be vectors, and total size should match the dest +    // vector size. +    LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); +    LLT SrcTy = MRI->getType(MI->getOperand(1).getReg()); +    if (!DstTy.isVector() || !SrcTy.isVector()) +      report("G_CONCAT_VECTOR requires vector source and destination operands", +             MI); +    for (unsigned i = 2; i < MI->getNumOperands(); ++i) { +      if (MRI->getType(MI->getOperand(1).getReg()) != +          MRI->getType(MI->getOperand(i).getReg())) +        report("G_CONCAT_VECTOR source operand types are not homogeneous", MI); +    } +    if (DstTy.getNumElements() != +        SrcTy.getNumElements() * (MI->getNumOperands() - 1)) +      report("G_CONCAT_VECTOR num dest and source elements should match", MI); +    break; +  }    case TargetOpcode::COPY: {      if (foundErrors)        break; @@ -1395,7 +1501,7 @@ void MachineVerifier::checkLivenessAtUse(const MachineOperand *MO,  void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO,      unsigned MONum, SlotIndex DefIdx, const LiveRange &LR, unsigned VRegOrUnit, -    LaneBitmask LaneMask) { +    bool SubRangeCheck, LaneBitmask LaneMask) {    if (const VNInfo *VNI = LR.getVNInfoAt(DefIdx)) {      assert(VNI && "NULL valno is not allowed");      if (VNI->def != DefIdx) { @@ -1419,25 +1525,14 @@ void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO,    if (MO->isDead()) {      LiveQueryResult LRQ = LR.Query(DefIdx);      if (!LRQ.isDeadDef()) { -      // In case of physregs we can have a non-dead definition on another -      // operand. -      bool otherDef = false; -      if (!TargetRegisterInfo::isVirtualRegister(VRegOrUnit)) { -        const MachineInstr &MI = *MO->getParent(); -        for (const MachineOperand &MO : MI.operands()) { -          if (!MO.isReg() || !MO.isDef() || MO.isDead()) -            continue; -          unsigned Reg = MO.getReg(); -          for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) { -            if (*Units == VRegOrUnit) { -              otherDef = true; -              break; -            } -          } -        } -      } - -      if (!otherDef) { +      assert(TargetRegisterInfo::isVirtualRegister(VRegOrUnit) && +             "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 +      // are checking liveness for a subrange it is ok for the live range to +      // continue, given that we have a dead def of a subregister. +      if (SubRangeCheck || MO->getSubReg() == 0) {          report("Live range continues after dead def flag", MO, MONum);          report_context_liverange(LR);          report_context_vreg_regunit(VRegOrUnit); @@ -1532,10 +1627,12 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {          // get a report for its operand.          if (Bad) {            for (const MachineOperand &MOP : MI->uses()) { -            if (!MOP.isReg()) +            if (!MOP.isReg() || !MOP.isImplicit())                continue; -            if (!MOP.isImplicit()) + +            if (!TargetRegisterInfo::isPhysicalRegister(MOP.getReg()))                continue; +              for (MCSubRegIterator SubRegs(MOP.getReg(), TRI); SubRegs.isValid();                   ++SubRegs) {                if (*SubRegs == Reg) { @@ -1593,7 +1690,7 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {              for (const LiveInterval::SubRange &SR : LI.subranges()) {                if ((SR.LaneMask & MOMask).none())                  continue; -              checkLivenessAtDef(MO, MONum, DefIdx, SR, Reg, SR.LaneMask); +              checkLivenessAtDef(MO, MONum, DefIdx, SR, Reg, true, SR.LaneMask);              }            }          } else { @@ -2116,6 +2213,13 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,      // Skip this block.      ++MFI;    } + +  SmallVector<SlotIndex, 4> Undefs; +  if (LaneMask.any()) { +    LiveInterval &OwnerLI = LiveInts->getInterval(Reg); +    OwnerLI.computeSubRangeUndefs(Undefs, LaneMask, *MRI, *Indexes); +  } +    while (true) {      assert(LiveInts->isLiveInToMBB(LR, &*MFI));      // We don't know how to track physregs into a landing pad. @@ -2141,7 +2245,9 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,        // instruction with subregister intervals        // only one of the subregisters (not necessarily the current one) needs to        // be defined. -      if (!PVNI && (LaneMask.none() || !IsPHI) ) { +      if (!PVNI && (LaneMask.none() || !IsPHI)) { +        if (LiveRangeCalc::isJointlyDominated(*PI, Undefs, *Indexes)) +          continue;          report("Register not marked live out of predecessor", *PI);          report_context(LR, Reg, LaneMask);          report_context(*VNI);  | 
