Skip to content

Commit 6f36e64

Browse files
committed
[PHIElimination] Account for PHI operands that appear more than once
During lowering, the PHI instruction is detached from the function and thus it is not considered a user of its operands. The previous implementation, which removed redundant COPY of COPY instructions, skipped values which had any uses, because otherwise it can break the function. However, it had a hidden assumption that there's a single use for that operand in the detached PHI instruction. By not taking into account that an operand can be referenced more than once, it interfered with itself and created IMPLICIT_DEF's for some incoming values instead of copying the correct ones.
1 parent a068ed2 commit 6f36e64

File tree

3 files changed

+32
-18
lines changed

3 files changed

+32
-18
lines changed

llvm/lib/CodeGen/PHIElimination.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,7 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
541541
// Now loop over all of the incoming arguments, changing them to copy into the
542542
// IncomingReg register in the corresponding predecessor basic block.
543543
SmallPtrSet<MachineBasicBlock *, 8> MBBsInsertedInto;
544+
SmallVector<MachineInstr *, 8> InsertedCopies;
544545
for (int i = NumSrcs - 1; i >= 0; --i) {
545546
Register SrcReg = MPhi->getOperand(i * 2 + 1).getReg();
546547
unsigned SrcSubReg = MPhi->getOperand(i * 2 + 1).getSubReg();
@@ -581,20 +582,6 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
581582
continue;
582583
}
583584

584-
// Reuse an existing copy in the block if possible.
585-
if (IncomingReg.isVirtual()) {
586-
MachineInstr *DefMI = MRI->getUniqueVRegDef(SrcReg);
587-
const TargetRegisterClass *SrcRC = MRI->getRegClass(SrcReg);
588-
const TargetRegisterClass *IncomingRC = MRI->getRegClass(IncomingReg);
589-
if (DefMI && DefMI->isCopy() && DefMI->getParent() == &opBlock &&
590-
MRI->use_empty(SrcReg) && IncomingRC->hasSuperClassEq(SrcRC)) {
591-
DefMI->getOperand(0).setReg(IncomingReg);
592-
if (LV)
593-
LV->getVarInfo(SrcReg).AliveBlocks.clear();
594-
continue;
595-
}
596-
}
597-
598585
// Find a safe location to insert the copy, this may be the first terminator
599586
// in the block (or end()).
600587
MachineBasicBlock::iterator InsertPos =
@@ -621,6 +608,7 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
621608
NewSrcInstr = TII->createPHISourceCopy(opBlock, InsertPos, nullptr,
622609
SrcReg, SrcSubReg, IncomingReg);
623610
}
611+
InsertedCopies.emplace_back(NewSrcInstr);
624612
}
625613

626614
// We only need to update the LiveVariables kill of SrcReg if this was the
@@ -744,6 +732,32 @@ void PHIEliminationImpl::LowerPHINode(MachineBasicBlock &MBB,
744732
}
745733
}
746734

735+
// Remove redundant COPY instructions chains, which were potentially added by
736+
// the code above. This can simplify the CFG which later on prevents
737+
// suboptimal block layout.
738+
for (MachineInstr *NewCopy : InsertedCopies) {
739+
if (NewCopy->isImplicitDef())
740+
continue;
741+
Register IncomingReg = NewCopy->getOperand(0).getReg();
742+
if (!IncomingReg.isVirtual())
743+
continue;
744+
Register SrcReg = NewCopy->getOperand(1).getReg();
745+
if (!MRI->hasOneUse(SrcReg))
746+
continue;
747+
MachineInstr *DefMI = MRI->getUniqueVRegDef(SrcReg);
748+
if (!DefMI || !DefMI->isCopy() ||
749+
DefMI->getParent() != NewCopy->getParent())
750+
continue;
751+
const TargetRegisterClass *SrcRC = MRI->getRegClass(SrcReg);
752+
const TargetRegisterClass *IncomingRC = MRI->getRegClass(IncomingReg);
753+
if (!IncomingRC->hasSuperClassEq(SrcRC))
754+
continue;
755+
DefMI->getOperand(0).setReg(IncomingReg);
756+
NewCopy->removeFromParent();
757+
if (LV)
758+
LV->getVarInfo(SrcReg).AliveBlocks.clear();
759+
}
760+
747761
// Really delete the PHI instruction now, if it is not in the LoweredPHIs map.
748762
if (EliminateNow) {
749763
if (LIS)

llvm/test/CodeGen/AArch64/PHIElimination-reuse-copy.mir

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,15 @@ body: |
135135
; CHECK-NEXT: liveins: $nzcv
136136
; CHECK-NEXT: {{ $}}
137137
; CHECK-NEXT: dead [[COPY2:%[0-9]+]]:gpr32 = COPY killed [[COPY1]]
138-
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY]]
138+
; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr32 = COPY [[COPY]]
139+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY [[COPY3]]
139140
; CHECK-NEXT: Bcc 1, %bb.1, implicit $nzcv
140141
; CHECK-NEXT: {{ $}}
141142
; CHECK-NEXT: bb.2:
142143
; CHECK-NEXT: successors: %bb.1(0x80000000)
143144
; CHECK-NEXT: liveins: $nzcv
144145
; CHECK-NEXT: {{ $}}
145-
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = IMPLICIT_DEF
146+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr32 = COPY killed [[COPY3]]
146147
; CHECK-NEXT: B %bb.1
147148
bb.0:
148149
successors: %bb.1

llvm/test/CodeGen/PowerPC/vsx.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2487,8 +2487,7 @@ define double @test82(double %a, double %b, double %c, double %d) {
24872487
; CHECK-FISL-LABEL: test82:
24882488
; CHECK-FISL: # %bb.0: # %entry
24892489
; CHECK-FISL-NEXT: stfd f2, -16(r1) # 8-byte Folded Spill
2490-
; CHECK-FISL-NEXT: fmr f2, f1
2491-
; CHECK-FISL-NEXT: stfd f2, -8(r1) # 8-byte Folded Spill
2490+
; CHECK-FISL-NEXT: stfd f1, -8(r1) # 8-byte Folded Spill
24922491
; CHECK-FISL-NEXT: xscmpudp cr0, f3, f4
24932492
; CHECK-FISL-NEXT: beq cr0, .LBB67_2
24942493
; CHECK-FISL-NEXT: # %bb.1: # %entry

0 commit comments

Comments
 (0)