1
0
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:
Bjorn Pettersson 2018-09-30 17:26:58 +00:00
parent 74b9872a0d
commit b92a8375b0
2 changed files with 82 additions and 13 deletions

View File

@ -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!");

View 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