mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-13 23:18:51 +00:00
Fix coalescing with IMPLICIT_DEF values.
PHIElimination inserts IMPLICIT_DEF instructions to guarantee that all PHI predecessors have a live-out value. These IMPLICIT_DEF values are not considered to be real interference when coalescing virtual registers: %vreg1 = IMPLICIT_DEF %vreg2 = MOV32r0 When joining %vreg1 and %vreg2, the IMPLICIT_DEF instruction and its value number should simply be erased since the %vreg2 value number now provides a live-out value for the PHI predecesor block. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165813 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5628920346
commit
795f951c6d
@ -1241,6 +1241,9 @@ class JoinVals {
|
||||
// Value in the other live range that overlaps this def, if any.
|
||||
VNInfo *OtherVNI;
|
||||
|
||||
// Is this value an IMPLICIT_DEF?
|
||||
bool IsImplicitDef;
|
||||
|
||||
// True when the live range of this value will be pruned because of an
|
||||
// overlapping CR_Replace value in the other live range.
|
||||
bool Pruned;
|
||||
@ -1249,7 +1252,8 @@ class JoinVals {
|
||||
bool PrunedComputed;
|
||||
|
||||
Val() : Resolution(CR_Keep), WriteLanes(0), ValidLanes(0),
|
||||
RedefVNI(0), OtherVNI(0), Pruned(false), PrunedComputed(false) {}
|
||||
RedefVNI(0), OtherVNI(0), IsImplicitDef(false), Pruned(false),
|
||||
PrunedComputed(false) {}
|
||||
|
||||
bool isAnalyzed() const { return WriteLanes != 0; }
|
||||
};
|
||||
@ -1385,8 +1389,10 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) {
|
||||
}
|
||||
|
||||
// An IMPLICIT_DEF writes undef values.
|
||||
if (DefMI->isImplicitDef())
|
||||
if (DefMI->isImplicitDef()) {
|
||||
V.IsImplicitDef = true;
|
||||
V.ValidLanes &= ~V.WriteLanes;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the value in Other that overlaps VNI->def, if any.
|
||||
@ -1724,22 +1730,29 @@ void JoinVals::pruneValues(JoinVals &Other,
|
||||
switch (Vals[i].Resolution) {
|
||||
case CR_Keep:
|
||||
break;
|
||||
case CR_Replace:
|
||||
case CR_Replace: {
|
||||
// This value takes precedence over the value in Other.LI.
|
||||
LIS->pruneValue(&Other.LI, Def, &EndPoints);
|
||||
// Remove <def,read-undef> flags. This def is now a partial redef.
|
||||
if (!Def.isBlock()) {
|
||||
// Check if we're replacing an IMPLICIT_DEF value. The IMPLICIT_DEF
|
||||
// instructions are only inserted to provide a live-out value for PHI
|
||||
// predecessors, so the instruction should simply go away once its value
|
||||
// has been replaced.
|
||||
Val &OtherV = Other.Vals[Vals[i].OtherVNI->id];
|
||||
bool EraseImpDef = OtherV.IsImplicitDef && OtherV.Resolution == CR_Keep;
|
||||
if (!EraseImpDef && !Def.isBlock()) {
|
||||
// Remove <def,read-undef> flags. This def is now a partial redef.
|
||||
for (MIOperands MO(Indexes->getInstructionFromIndex(Def));
|
||||
MO.isValid(); ++MO)
|
||||
if (MO->isReg() && MO->isDef() && MO->getReg() == LI.reg)
|
||||
MO->setIsUndef(false);
|
||||
// This value will reach instructions below, but we need to make sure
|
||||
// the live range also reaches the instruction at Def.
|
||||
EndPoints.push_back(Def);
|
||||
// This value will reach instructions below, but we need to make sure
|
||||
// the live range also reaches the instruction at Def.
|
||||
EndPoints.push_back(Def);
|
||||
}
|
||||
DEBUG(dbgs() << "\t\tpruned " << PrintReg(Other.LI.reg) << " at " << Def
|
||||
<< ": " << Other.LI << '\n');
|
||||
break;
|
||||
}
|
||||
case CR_Erase:
|
||||
case CR_Merge:
|
||||
if (isPrunedValue(i, Other)) {
|
||||
@ -1762,21 +1775,41 @@ void JoinVals::pruneValues(JoinVals &Other,
|
||||
void JoinVals::eraseInstrs(SmallPtrSet<MachineInstr*, 8> &ErasedInstrs,
|
||||
SmallVectorImpl<unsigned> &ShrinkRegs) {
|
||||
for (unsigned i = 0, e = LI.getNumValNums(); i != e; ++i) {
|
||||
if (Vals[i].Resolution != CR_Erase)
|
||||
continue;
|
||||
// Get the def location before markUnused() below invalidates it.
|
||||
SlotIndex Def = LI.getValNumInfo(i)->def;
|
||||
MachineInstr *MI = Indexes->getInstructionFromIndex(Def);
|
||||
assert(MI && "No instruction to erase");
|
||||
if (MI->isCopy()) {
|
||||
unsigned Reg = MI->getOperand(1).getReg();
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg) &&
|
||||
Reg != CP.getSrcReg() && Reg != CP.getDstReg())
|
||||
ShrinkRegs.push_back(Reg);
|
||||
switch (Vals[i].Resolution) {
|
||||
case CR_Keep:
|
||||
// If an IMPLICIT_DEF value is pruned, it doesn't serve a purpose any
|
||||
// longer. The IMPLICIT_DEF instructions are only inserted by
|
||||
// PHIElimination to guarantee that all PHI predecessors have a value.
|
||||
if (!Vals[i].IsImplicitDef || !Vals[i].Pruned)
|
||||
break;
|
||||
// Remove value number i from LI. Note that this VNInfo is still present
|
||||
// in NewVNInfo, so it will appear as an unused value number in the final
|
||||
// joined interval.
|
||||
LI.getValNumInfo(i)->markUnused();
|
||||
LI.removeValNo(LI.getValNumInfo(i));
|
||||
DEBUG(dbgs() << "\t\tremoved " << i << '@' << Def << ": " << LI << '\n');
|
||||
// FALL THROUGH.
|
||||
|
||||
case CR_Erase: {
|
||||
MachineInstr *MI = Indexes->getInstructionFromIndex(Def);
|
||||
assert(MI && "No instruction to erase");
|
||||
if (MI->isCopy()) {
|
||||
unsigned Reg = MI->getOperand(1).getReg();
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg) &&
|
||||
Reg != CP.getSrcReg() && Reg != CP.getDstReg())
|
||||
ShrinkRegs.push_back(Reg);
|
||||
}
|
||||
ErasedInstrs.insert(MI);
|
||||
DEBUG(dbgs() << "\t\terased:\t" << Def << '\t' << *MI);
|
||||
LIS->RemoveMachineInstrFromMaps(MI);
|
||||
MI->eraseFromParent();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ErasedInstrs.insert(MI);
|
||||
DEBUG(dbgs() << "\t\terased:\t" << Def << '\t' << *MI);
|
||||
LIS->RemoveMachineInstrFromMaps(MI);
|
||||
MI->eraseFromParent();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,3 +477,106 @@ for.inc: ; preds = %for.cond
|
||||
}
|
||||
|
||||
declare void @fn3(...)
|
||||
|
||||
; Check coalescing of IMPLICIT_DEF instructions:
|
||||
;
|
||||
; %vreg1 = IMPLICIT_DEF
|
||||
; %vreg2 = MOV32r0
|
||||
;
|
||||
; When coalescing %vreg1 and %vreg2, the IMPLICIT_DEF instruction should be
|
||||
; erased along with its value number.
|
||||
;
|
||||
define void @rdar12474033() nounwind ssp {
|
||||
bb:
|
||||
br i1 undef, label %bb21, label %bb1
|
||||
|
||||
bb1: ; preds = %bb
|
||||
switch i32 undef, label %bb10 [
|
||||
i32 4, label %bb2
|
||||
i32 1, label %bb9
|
||||
i32 5, label %bb3
|
||||
i32 6, label %bb3
|
||||
i32 2, label %bb9
|
||||
]
|
||||
|
||||
bb2: ; preds = %bb1
|
||||
unreachable
|
||||
|
||||
bb3: ; preds = %bb1, %bb1
|
||||
br i1 undef, label %bb4, label %bb5
|
||||
|
||||
bb4: ; preds = %bb3
|
||||
unreachable
|
||||
|
||||
bb5: ; preds = %bb3
|
||||
%tmp = load <4 x float>* undef, align 1
|
||||
%tmp6 = bitcast <4 x float> %tmp to i128
|
||||
%tmp7 = load <4 x float>* undef, align 1
|
||||
%tmp8 = bitcast <4 x float> %tmp7 to i128
|
||||
br label %bb10
|
||||
|
||||
bb9: ; preds = %bb1, %bb1
|
||||
unreachable
|
||||
|
||||
bb10: ; preds = %bb5, %bb1
|
||||
%tmp11 = phi i128 [ undef, %bb1 ], [ %tmp6, %bb5 ]
|
||||
%tmp12 = phi i128 [ 0, %bb1 ], [ %tmp8, %bb5 ]
|
||||
switch i32 undef, label %bb21 [
|
||||
i32 2, label %bb18
|
||||
i32 3, label %bb13
|
||||
i32 5, label %bb16
|
||||
i32 6, label %bb17
|
||||
i32 1, label %bb18
|
||||
]
|
||||
|
||||
bb13: ; preds = %bb10
|
||||
br i1 undef, label %bb15, label %bb14
|
||||
|
||||
bb14: ; preds = %bb13
|
||||
br label %bb21
|
||||
|
||||
bb15: ; preds = %bb13
|
||||
unreachable
|
||||
|
||||
bb16: ; preds = %bb10
|
||||
unreachable
|
||||
|
||||
bb17: ; preds = %bb10
|
||||
unreachable
|
||||
|
||||
bb18: ; preds = %bb10, %bb10
|
||||
%tmp19 = bitcast i128 %tmp11 to <4 x float>
|
||||
%tmp20 = bitcast i128 %tmp12 to <4 x float>
|
||||
br label %bb21
|
||||
|
||||
bb21: ; preds = %bb18, %bb14, %bb10, %bb
|
||||
%tmp22 = phi <4 x float> [ undef, %bb ], [ undef, %bb10 ], [ undef, %bb14 ], [ %tmp20, %bb18 ]
|
||||
%tmp23 = phi <4 x float> [ undef, %bb ], [ undef, %bb10 ], [ undef, %bb14 ], [ %tmp19, %bb18 ]
|
||||
store <4 x float> %tmp23, <4 x float>* undef, align 16
|
||||
store <4 x float> %tmp22, <4 x float>* undef, align 16
|
||||
switch i32 undef, label %bb29 [
|
||||
i32 5, label %bb27
|
||||
i32 1, label %bb24
|
||||
i32 2, label %bb25
|
||||
i32 14, label %bb28
|
||||
i32 4, label %bb26
|
||||
]
|
||||
|
||||
bb24: ; preds = %bb21
|
||||
unreachable
|
||||
|
||||
bb25: ; preds = %bb21
|
||||
br label %bb29
|
||||
|
||||
bb26: ; preds = %bb21
|
||||
br label %bb29
|
||||
|
||||
bb27: ; preds = %bb21
|
||||
unreachable
|
||||
|
||||
bb28: ; preds = %bb21
|
||||
br label %bb29
|
||||
|
||||
bb29: ; preds = %bb28, %bb26, %bb25, %bb21
|
||||
unreachable
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user