diff options
| author | Matthias Braun <matze@braunis.de> | 2016-02-02 20:04:51 +0000 |
|---|---|---|
| committer | Matthias Braun <matze@braunis.de> | 2016-02-02 20:04:51 +0000 |
| commit | 1377fd6781744d5acab9f060c87c22824153cf32 (patch) | |
| tree | 3ea0a5487d2fce7cb67ab8f39a90ecd51e4163ab /llvm/lib | |
| parent | 8b175672cbbb19d328038be74fd917e405b46168 (diff) | |
| download | bcm5719-llvm-1377fd6781744d5acab9f060c87c22824153cf32.tar.gz bcm5719-llvm-1377fd6781744d5acab9f060c87c22824153cf32.zip | |
MachineVerifier: Check that defs/uses are live in subregisters as well.
llvm-svn: 259552
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/MachineVerifier.cpp | 193 |
1 files changed, 141 insertions, 52 deletions
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index de4ad4ade6d..5f0cf40040e 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -220,10 +220,19 @@ namespace { void report_context(SlotIndex Pos) const; void report_context_liverange(const LiveRange &LR) const; void report_context_regunit(unsigned RegUnit) const; + void report_context_lanemask(LaneBitmask LaneMask) const; + void report_context_vreg_regunit(unsigned VRegOrRegUnit) 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, + LaneBitmask LaneMask = 0); + void checkLivenessAtDef(const MachineOperand *MO, unsigned MONum, + SlotIndex DefIdx, const LiveRange &LR, unsigned Reg, + LaneBitmask LaneMask = 0); + void markReachable(const MachineBasicBlock *MBB); void calcRegsPassed(); void checkPHIOps(const MachineBasicBlock *MBB); @@ -451,7 +460,7 @@ void MachineVerifier::report_context(const LiveRange &LR, unsigned Reg, report_context_liverange(LR); errs() << "- register: " << PrintReg(Reg, TRI) << '\n'; if (LaneMask != 0) - errs() << "- lanemask: " << PrintLaneMask(LaneMask) << '\n'; + report_context_lanemask(LaneMask); } void MachineVerifier::report_context(const LiveRange::Segment &S) const { @@ -470,6 +479,18 @@ void MachineVerifier::report_context_regunit(unsigned RegUnit) const { errs() << "- regunit: " << PrintRegUnit(RegUnit, TRI) << '\n'; } +void MachineVerifier::report_context_vreg_regunit(unsigned VRegOrUnit) const { + if (TargetRegisterInfo::isVirtualRegister(VRegOrUnit)) { + errs() << "- v. register: " << PrintReg(VRegOrUnit, TRI) << '\n'; + } else { + errs() << "- regunit: " << PrintRegUnit(VRegOrUnit, TRI) << '\n'; + } +} + +void MachineVerifier::report_context_lanemask(LaneBitmask LaneMask) const { + errs() << "- lanemask: " << PrintLaneMask(LaneMask) << '\n'; +} + void MachineVerifier::markReachable(const MachineBasicBlock *MBB) { BBInfo &MInfo = MBBInfoMap[MBB]; if (!MInfo.reachable) { @@ -1043,6 +1064,83 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { } } +void MachineVerifier::checkLivenessAtUse(const MachineOperand *MO, + unsigned MONum, SlotIndex UseIdx, const LiveRange &LR, unsigned VRegOrUnit, + LaneBitmask LaneMask) { + LiveQueryResult LRQ = LR.Query(UseIdx); + // Check if we have a segment at the use, note however that we only need one + // live subregister range, the others may be dead. + if (!LRQ.valueIn() && LaneMask == 0) { + report("No live segment at use", MO, MONum); + report_context_liverange(LR); + report_context_vreg_regunit(VRegOrUnit); + report_context(UseIdx); + } + if (MO->isKill() && !LRQ.isKill()) { + report("Live range continues after kill flag", MO, MONum); + report_context_liverange(LR); + report_context_vreg_regunit(VRegOrUnit); + if (LaneMask != 0) + report_context_lanemask(LaneMask); + report_context(UseIdx); + } +} + +void MachineVerifier::checkLivenessAtDef(const MachineOperand *MO, + unsigned MONum, SlotIndex DefIdx, const LiveRange &LR, unsigned VRegOrUnit, + LaneBitmask LaneMask) { + if (const VNInfo *VNI = LR.getVNInfoAt(DefIdx)) { + assert(VNI && "NULL valno is not allowed"); + if (VNI->def != DefIdx) { + report("Inconsistent valno->def", MO, MONum); + report_context_liverange(LR); + report_context_vreg_regunit(VRegOrUnit); + if (LaneMask != 0) + report_context_lanemask(LaneMask); + report_context(*VNI); + report_context(DefIdx); + } + } else { + report("No live segment at def", MO, MONum); + report_context_liverange(LR); + report_context_vreg_regunit(VRegOrUnit); + if (LaneMask != 0) + report_context_lanemask(LaneMask); + report_context(DefIdx); + } + // Check that, if the dead def flag is present, LiveInts agree. + 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) { + report("Live range continues after dead def flag", MO, MONum); + report_context_liverange(LR); + report_context_vreg_regunit(VRegOrUnit); + if (LaneMask != 0) + report_context_lanemask(LaneMask); + } + } + } +} + void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) { const MachineInstr *MI = MO->getParent(); const unsigned Reg = MO->getReg(); @@ -1068,21 +1166,8 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) { // Check the cached regunit intervals. if (TargetRegisterInfo::isPhysicalRegister(Reg) && !isReserved(Reg)) { for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) { - if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units)) { - LiveQueryResult LRQ = LR->Query(UseIdx); - if (!LRQ.valueIn()) { - report("No live segment at use", MO, MONum); - report_context_liverange(*LR); - report_context_regunit(*Units); - report_context(UseIdx); - } - if (MO->isKill() && !LRQ.isKill()) { - report("Live range continues after kill flag", MO, MONum); - report_context_liverange(*LR); - report_context_regunit(*Units); - report_context(UseIdx); - } - } + if (const LiveRange *LR = LiveInts->getCachedRegUnit(*Units)) + checkLivenessAtUse(MO, MONum, UseIdx, *LR, *Units); } } @@ -1090,18 +1175,28 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) { if (LiveInts->hasInterval(Reg)) { // This is a virtual register interval. const LiveInterval &LI = LiveInts->getInterval(Reg); - LiveQueryResult LRQ = LI.Query(UseIdx); - if (!LRQ.valueIn()) { - report("No live segment at use", MO, MONum); - report_context(LI); - report_context(UseIdx); - } - // Check for extra kill flags. - // Note that we allow missing kill flags for now. - if (MO->isKill() && !LRQ.isKill()) { - report("Live range continues after kill flag", MO, MONum); - report_context(LI); - report_context(UseIdx); + checkLivenessAtUse(MO, MONum, UseIdx, LI, Reg); + + if (LI.hasSubRanges() && !MO->isDef()) { + unsigned SubRegIdx = MO->getSubReg(); + LaneBitmask MOMask = SubRegIdx != 0 + ? TRI->getSubRegIndexLaneMask(SubRegIdx) + : MRI->getMaxLaneMaskForVReg(Reg); + LaneBitmask LiveInMask = 0; + for (const LiveInterval::SubRange &SR : LI.subranges()) { + if ((MOMask & SR.LaneMask) == 0) + continue; + checkLivenessAtUse(MO, MONum, UseIdx, SR, Reg, SR.LaneMask); + LiveQueryResult LRQ = SR.Query(UseIdx); + if (LRQ.valueIn()) + LiveInMask |= SR.LaneMask; + } + // At least parts of the register has to be live at the use. + if ((LiveInMask & MOMask) == 0) { + report("No live subrange at use", MO, MONum); + report_context(LI); + report_context(UseIdx); + } } } else { report("Virtual register has no live interval", MO, MONum); @@ -1174,35 +1269,29 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) { report("Multiple virtual register defs in SSA form", MO, MONum); // Check LiveInts for a live segment, but only for virtual registers. - if (LiveInts && TargetRegisterInfo::isVirtualRegister(Reg) && - !LiveInts->isNotInMIMap(MI)) { + if (LiveInts && !LiveInts->isNotInMIMap(MI)) { SlotIndex DefIdx = LiveInts->getInstructionIndex(MI); DefIdx = DefIdx.getRegSlot(MO->isEarlyClobber()); - if (LiveInts->hasInterval(Reg)) { - const LiveInterval &LI = LiveInts->getInterval(Reg); - if (const VNInfo *VNI = LI.getVNInfoAt(DefIdx)) { - assert(VNI && "NULL valno is not allowed"); - if (VNI->def != DefIdx) { - report("Inconsistent valno->def", MO, MONum); - report_context(LI); - report_context(*VNI); - report_context(DefIdx); + + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + if (LiveInts->hasInterval(Reg)) { + const LiveInterval &LI = LiveInts->getInterval(Reg); + checkLivenessAtDef(MO, MONum, DefIdx, LI, Reg); + + if (LI.hasSubRanges()) { + unsigned SubRegIdx = MO->getSubReg(); + LaneBitmask MOMask = SubRegIdx != 0 + ? TRI->getSubRegIndexLaneMask(SubRegIdx) + : MRI->getMaxLaneMaskForVReg(Reg); + for (const LiveInterval::SubRange &SR : LI.subranges()) { + if ((SR.LaneMask & MOMask) == 0) + continue; + checkLivenessAtDef(MO, MONum, DefIdx, SR, Reg, SR.LaneMask); + } } } else { - report("No live segment at def", MO, MONum); - report_context(LI); - report_context(DefIdx); + report("Virtual register has no Live interval", MO, MONum); } - // Check that, if the dead def flag is present, LiveInts agree. - if (MO->isDead()) { - LiveQueryResult LRQ = LI.Query(DefIdx); - if (!LRQ.isDeadDef()) { - report("Live range continues after dead def flag", MO, MONum); - report_context(LI); - } - } - } else { - report("Virtual register has no Live interval", MO, MONum); } } } |

