return true;
}
-/// isImplicitlyDefined - Return true if all defs of VirtReg are implicit-defs.
+/// Return true if all defs of VirtReg are implicit-defs.
/// This includes registers with no defs.
static bool isImplicitlyDefined(unsigned VirtReg,
- const MachineRegisterInfo *MRI) {
- for (MachineInstr &DI : MRI->def_instructions(VirtReg))
+ const MachineRegisterInfo &MRI) {
+ for (MachineInstr &DI : MRI.def_instructions(VirtReg))
if (!DI.isImplicitDef())
return false;
return true;
}
-/// isSourceDefinedByImplicitDef - Return true if all sources of the phi node
-/// are implicit_def's.
-static bool isSourceDefinedByImplicitDef(const MachineInstr *MPhi,
- const MachineRegisterInfo *MRI) {
- for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2)
- if (!isImplicitlyDefined(MPhi->getOperand(i).getReg(), MRI))
+/// Return true if all sources of the phi node are implicit_def's, or undef's.
+static bool allPhiOperandsUndefined(const MachineInstr &MPhi,
+ const MachineRegisterInfo &MRI) {
+ for (unsigned I = 1, E = MPhi.getNumOperands(); I != E; I += 2) {
+ const MachineOperand &MO = MPhi.getOperand(I);
+ if (!isImplicitlyDefined(MO.getReg(), MRI) && !MO.isUndef())
return false;
+ }
return true;
}
-
/// LowerPHINode - Lower the PHI node at the top of the specified block.
void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
MachineBasicBlock::iterator LastPHIIt) {
// after any remaining phi nodes) which copies the new incoming register
// into the phi node destination.
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
- if (isSourceDefinedByImplicitDef(MPhi, MRI))
- // If all sources of a PHI node are implicit_def, just emit an
+ if (allPhiOperandsUndefined(*MPhi, *MRI))
+ // If all sources of a PHI node are implicit_def or undef uses, just emit an
// implicit_def instead of a copy.
BuildMI(MBB, AfterPHIsIt, MPhi->getDebugLoc(),
TII->get(TargetOpcode::IMPLICIT_DEF), DestReg);
unsigned SrcReg = MPhi->getOperand(i*2+1).getReg();
unsigned SrcSubReg = MPhi->getOperand(i*2+1).getSubReg();
bool SrcUndef = MPhi->getOperand(i*2+1).isUndef() ||
- isImplicitlyDefined(SrcReg, MRI);
+ isImplicitlyDefined(SrcReg, *MRI);
assert(TargetRegisterInfo::isVirtualRegister(SrcReg) &&
"Machine PHI Operands must all be virtual registers!");
--- /dev/null
+# RUN: llc -mtriple amdgcn -run-pass livevars -run-pass phi-node-elimination -o - %s | FileCheck %s
+
+################################################################################
+# This test used to hit an assert in PHIElimination:
+# PHIElimination::LowerPHINode(llvm::MachineBasicBlock&, llvm::MachineBasicBlock::iterator): Assertion `KillInst->readsRegister(SrcReg) && "Cannot find kill instruction"'
+
+---
+name: foo
+tracksRegLiveness: true
+body: |
+ bb.0:
+ S_CBRANCH_SCC0 %bb.2, implicit undef $scc
+
+ bb.1:
+ %1:sreg_32_xm0 = S_MOV_B32 255
+ S_BRANCH %bb.3
+
+ bb.2:
+ %2:sreg_32_xm0 = S_MOV_B32 254
+
+ bb.3:
+ dead %3:sreg_32_xm0 = PHI undef %2, %bb.2, undef %1, %bb.1
+ %4:sreg_32_xm0 = PHI %2, %bb.2, %1, %bb.1
+ S_NOP 0, implicit %4
+...
+
+# CHECK-LABEL: name: foo
+# CHECK: bb.3:
+# CHECK-NEXT: %3:sreg_32_xm0 = COPY killed %4
+# CHECK-NEXT: dead %2:sreg_32_xm0 = IMPLICIT_DEF
+# CHECK-NEXT: S_NOP 0, implicit killed %3
+
+
+################################################################################
+# Similar test as above, but with swapped order for the PHI nodes.
+# With this PHI node order we did not hit the assert, but we used to get
+#
+# bb.3:
+# dead %3:sreg_32_xm0 = COPY killed %4
+# %2:sreg_32_xm0 = COPY %4
+# S_NOP 0, implicit killed %2
+#
+# which looks weird regarding killed flags for %4.
+
+---
+name: bar
+tracksRegLiveness: true
+body: |
+ bb.0:
+ S_CBRANCH_SCC0 %bb.2, implicit undef $scc
+
+ bb.1:
+ %1:sreg_32_xm0 = S_MOV_B32 255
+ S_BRANCH %bb.3
+
+ bb.2:
+ %2:sreg_32_xm0 = S_MOV_B32 254
+
+ bb.3:
+ %4:sreg_32_xm0 = PHI %2, %bb.2, %1, %bb.1
+ dead %3:sreg_32_xm0 = PHI undef %2, %bb.2, undef %1, %bb.1
+ S_NOP 0, implicit %4
+...
+
+# CHECK-LABEL: name: bar
+# CHECK: bb.3:
+# CHECK-NEXT: dead %3:sreg_32_xm0 = IMPLICIT_DEF
+# CHECK-NEXT: %2:sreg_32_xm0 = COPY killed %4
+# CHECK-NEXT: S_NOP 0, implicit killed %2