mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[PHIElimination] Lower a PHI node with only undef uses as IMPLICIT_DEF
Summary: The lowering of PHI nodes used to detect if all inputs originated from IMPLICIT_DEF's. If so the PHI node was replaced by an IMPLICIT_DEF. Now we also consider undef uses when checking the inputs. So if all inputs are implicitly defined or undef we lower the PHI to an IMPLICIT_DEF. This makes PHIElimination::LowerPHINode more consistent as it checks both implicit and undef properties at later stages. Reviewers: MatzeB, tstellar Reviewed By: MatzeB Subscribers: jvesely, nhaehnle, llvm-commits Differential Revision: https://reviews.llvm.org/D52558 llvm-svn: 343417
This commit is contained in:
parent
74b9872a0d
commit
b92a8375b0
@ -211,26 +211,26 @@ bool PHIElimination::EliminatePHINodes(MachineFunction &MF,
|
||||
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) {
|
||||
@ -255,8 +255,8 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
|
||||
// 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);
|
||||
@ -373,7 +373,7 @@ void PHIElimination::LowerPHINode(MachineBasicBlock &MBB,
|
||||
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!");
|
||||
|
||||
|
69
test/CodeGen/AMDGPU/phi-elimination-assertion.mir
Normal file
69
test/CodeGen/AMDGPU/phi-elimination-assertion.mir
Normal file
@ -0,0 +1,69 @@
|
||||
# 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
|
Loading…
Reference in New Issue
Block a user