Skip to content

Commit 2f37094

Browse files
committed
[rc-id] Make RCIdentity strip off single-pred arguments.
In a bunch of use-cases we use stripSinglePredecessorArgs to eliminate this case. There is no reason to assume that this is being done in the caller of RCIdentity. Lets make sure that we handle this case here. rdar://24156136
1 parent 4ce77cb commit 2f37094

File tree

7 files changed

+80
-11
lines changed

7 files changed

+80
-11
lines changed

include/swift/SIL/SILArgument.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class SILArgument : public ValueBase {
9191
bool getIncomingValues(
9292
llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>> &OutArray);
9393

94+
/// If this SILArgument's parent block has one predecessor, return the
95+
/// incoming value from that predecessor. Returns SILValue() otherwise.
96+
SILValue getSingleIncomingValue() const;
97+
9498
/// Returns true if this SILArgument is the self argument of its
9599
/// function. This means that this will return false always for SILArguments
96100
/// of SILFunctions that do not have self argument and for non-function

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3916,11 +3916,13 @@ class CondBranchInst : public TermInst {
39163916

39173917
/// Returns the argument on the cond_br terminator that will be passed to
39183918
/// DestBB in A.
3919-
SILValue getArgForDestBB(SILBasicBlock *DestBB, SILArgument *A) const;
3919+
SILValue getArgForDestBB(const SILBasicBlock *DestBB,
3920+
const SILArgument *A) const;
39203921

39213922
/// Returns the argument on the cond_br terminator that will be passed as the
39223923
/// \p Index argument to DestBB.
3923-
SILValue getArgForDestBB(SILBasicBlock *DestBB, unsigned ArgIndex) const;
3924+
SILValue getArgForDestBB(const SILBasicBlock *DestBB,
3925+
unsigned ArgIndex) const;
39243926

39253927
void swapSuccessors();
39263928

lib/SIL/SILArgument.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ SILModule &SILArgument::getModule() const {
6060
return getFunction()->getModule();
6161
}
6262

63-
static SILValue getIncomingValueForPred(SILBasicBlock *BB, SILBasicBlock *Pred,
63+
static SILValue getIncomingValueForPred(const SILBasicBlock *BB,
64+
const SILBasicBlock *Pred,
6465
unsigned Index) {
65-
TermInst *TI = Pred->getTerminator();
66+
const TermInst *TI = Pred->getTerminator();
6667

6768
switch (TI->getTermKind()) {
6869
// TODO: This list is conservative. I think we can probably handle more of
@@ -77,17 +78,25 @@ static SILValue getIncomingValueForPred(SILBasicBlock *BB, SILBasicBlock *Pred,
7778
case TermKind::DynamicMethodBranchInst:
7879
return SILValue();
7980
case TermKind::BranchInst:
80-
return cast<BranchInst>(TI)->getArg(Index);
81+
return cast<const BranchInst>(TI)->getArg(Index);
8182
case TermKind::CondBranchInst:
82-
return cast<CondBranchInst>(TI)->getArgForDestBB(BB, Index);
83+
return cast<const CondBranchInst>(TI)->getArgForDestBB(BB, Index);
8384
case TermKind::CheckedCastBranchInst:
84-
return cast<CheckedCastBranchInst>(TI)->getOperand();
85+
return cast<const CheckedCastBranchInst>(TI)->getOperand();
8586
case TermKind::SwitchEnumInst:
86-
return cast<SwitchEnumInst>(TI)->getOperand();
87+
return cast<const SwitchEnumInst>(TI)->getOperand();
8788
}
8889
llvm_unreachable("Unhandled TermKind?!");
8990
}
9091

92+
SILValue SILArgument::getSingleIncomingValue() const {
93+
const SILBasicBlock *Parent = getParent();
94+
const SILBasicBlock *PredBB = Parent->getSinglePredecessor();
95+
if (!PredBB)
96+
return SILValue();
97+
return getIncomingValueForPred(Parent, PredBB, getIndex());
98+
}
99+
91100
bool SILArgument::getIncomingValues(llvm::SmallVectorImpl<SILValue> &OutArray) {
92101
SILBasicBlock *Parent = getParent();
93102

lib/SIL/SILInstructions.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -774,12 +774,12 @@ OperandValueArrayRef CondBranchInst::getFalseArgs() const {
774774
return Operands.asValueArray().slice(1 + NumTrueArgs, NumFalseArgs);
775775
}
776776

777-
SILValue CondBranchInst::getArgForDestBB(SILBasicBlock *DestBB,
778-
SILArgument *Arg) const {
777+
SILValue CondBranchInst::getArgForDestBB(const SILBasicBlock *DestBB,
778+
const SILArgument *Arg) const {
779779
return getArgForDestBB(DestBB, Arg->getIndex());
780780
}
781781

782-
SILValue CondBranchInst::getArgForDestBB(SILBasicBlock *DestBB,
782+
SILValue CondBranchInst::getArgForDestBB(const SILBasicBlock *DestBB,
783783
unsigned ArgIndex) const {
784784
// If TrueBB and FalseBB equal, we cannot find an arg for this DestBB so
785785
// return an empty SILValue.

lib/SIL/SILValue.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ static SILValue stripSinglePredecessorArgs(SILValue V) {
7575
TermInst *PredTI = Pred->getTerminator();
7676

7777
// And attempt to find our matching argument.
78+
//
79+
// *NOTE* We can only strip things here if we know that there is no semantic
80+
// change in terms of upcasts/downcasts/enum extraction since this is used
81+
// by other routines here. This means that we can only look through
82+
// cond_br/br.
83+
//
84+
// For instance, routines that use stripUpcasts() do not want to strip off a
85+
// downcast that results from checked_cast_br.
7886
if (auto *BI = dyn_cast<BranchInst>(PredTI)) {
7987
V = BI->getArg(A->getIndex());
8088
continue;

lib/SILOptimizer/Analysis/RCIdentityAnalysis.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ static SILValue stripRCIdentityPreservingInsts(SILValue V) {
9898
if (SILValue NewValue = TI->getUniqueNonTrivialElt())
9999
return NewValue;
100100

101+
// Any SILArgument with a single predecessor from a "phi" perspective is
102+
// dead. In such a case, the SILArgument must be rc-identical.
103+
//
104+
// This is the easy case. The difficult case is when you have an argument with
105+
// /multiple/ predecessors.
106+
//
107+
// We do not need to insert this SILArgument into the visited SILArgument set
108+
// since we will only visit it twice if we go around a back edge due to a
109+
// different SILArgument that is actually being used for its phi node like
110+
// purposes.
111+
if (auto *A = dyn_cast<SILArgument>(V))
112+
if (SILValue Result = A->getSingleIncomingValue())
113+
return Result;
114+
101115
return SILValue();
102116
}
103117

test/SILOptimizer/rcidentity.sil

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,35 @@ bb0(%0 : $Builtin.NativeObject, %1 : $Builtin.Word):
108108
%5 = tuple(%1 : $Builtin.Word, %4 : $(Builtin.Word, Builtin.NativeObject, Builtin.NativeObject), %1 : $Builtin.Word)
109109
return undef : $()
110110
}
111+
112+
// All of the SSA values in the given function besides %6 can be resolved to
113+
// (%0, %1). Because %6 has multiple SSA values and there is nothing tricky we
114+
// can do here, just bail.
115+
//
116+
// CHECK-LABEL: @test_single_pred_rc_id@
117+
// CHECK: RESULT #0: 0 = 0
118+
// CHECK: RESULT #1: 1 = 1
119+
// CHECK: RESULT #2: 2 = 0
120+
// CHECK: RESULT #3: 3 = 1
121+
// CHECK: RESULT #4: 4 = 1
122+
// CHECK: RESULT #5: 5 = 0
123+
// CHECK: RESULT #6: 6 = 6
124+
sil @test_single_pred_rc_id : $@convention(thin) (Builtin.NativeObject, Builtin.NativeObject) -> () {
125+
bb0(%0 : $Builtin.NativeObject, %1 : $Builtin.NativeObject):
126+
br bb1(%0 : $Builtin.NativeObject, %1 : $Builtin.NativeObject)
127+
128+
bb1(%2 : $Builtin.NativeObject, %3 : $Builtin.NativeObject):
129+
cond_br undef, bb2(%3 : $Builtin.NativeObject), bb3(%2 : $Builtin.NativeObject)
130+
131+
bb2(%4 : $Builtin.NativeObject):
132+
br bb4(%4 : $Builtin.NativeObject)
133+
134+
bb3(%5 : $Builtin.NativeObject):
135+
br bb4(%5 : $Builtin.NativeObject)
136+
137+
bb4(%6 : $Builtin.NativeObject):
138+
cond_br undef, bb4(%6 : $Builtin.NativeObject), bb5
139+
140+
bb5:
141+
return undef : $()
142+
}

0 commit comments

Comments
 (0)