summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorMatthias Braun <matze@braunis.de>2016-02-02 20:04:51 +0000
committerMatthias Braun <matze@braunis.de>2016-02-02 20:04:51 +0000
commit1377fd6781744d5acab9f060c87c22824153cf32 (patch)
tree3ea0a5487d2fce7cb67ab8f39a90ecd51e4163ab /llvm/lib
parent8b175672cbbb19d328038be74fd917e405b46168 (diff)
downloadbcm5719-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.cpp193
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);
}
}
}
OpenPOWER on IntegriCloud