Skip to content

Commit 8bb6738

Browse files
committed
Consistenly use RCIdentity to get the RCRoot of the operand.
We were using a stripCast in some places and getRCIdentityRoot in others. stripCasts is not identical to getRCIdentityRoot. In particular, it does not look through struct_extract, tuple_extract, unchecked_enum_data. Created a struct and tuple test cases for make sure things are optimized as they should be. We have test case for unchecked_enum_data before.
1 parent be79691 commit 8bb6738

File tree

4 files changed

+105
-10
lines changed

4 files changed

+105
-10
lines changed

lib/SILOptimizer/ARC/RCStateTransitionVisitors.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ BottomUpDataflowRCStateVisitor<ARCState>::visitStrongDecrement(ValueBase *V) {
6868
return DataflowResult(Op);
6969

7070
BottomUpRefCountState &State = DataflowState.getBottomUpRefCountState(Op);
71-
bool NestingDetected = State.initWithMutatorInst(SetFactory.get(I));
71+
bool NestingDetected = State.initWithMutatorInst(SetFactory.get(I), RCFI);
7272

7373
// If we are running with 'frozen' owned arg releases, check if we have a
7474
// frozen use in the side table. If so, this release must be known safe.
@@ -203,7 +203,7 @@ TopDownDataflowRCStateVisitor<ARCState>::visitStrongIncrement(ValueBase *V) {
203203
// count state and continue...
204204
SILValue Op = RCFI->getRCIdentityRoot(I->getOperand(0));
205205
auto &State = DataflowState.getTopDownRefCountState(Op);
206-
bool NestingDetected = State.initWithMutatorInst(SetFactory.get(I));
206+
bool NestingDetected = State.initWithMutatorInst(SetFactory.get(I), RCFI);
207207

208208
DEBUG(llvm::dbgs() << " REF COUNT INCREMENT! Known Safe: "
209209
<< (State.isKnownSafe() ? "yes" : "no") << "\n");

lib/SILOptimizer/ARC/RefCountState.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,15 @@ MergeTopDownLatticeStates(TopDownRefCountState::LatticeState L1,
8181
/// Initializes/reinitialized the state for I. If we reinitialize we return
8282
/// true.
8383
bool BottomUpRefCountState::initWithMutatorInst(
84-
ImmutablePointerSet<SILInstruction> *I) {
84+
ImmutablePointerSet<SILInstruction> *I,
85+
RCIdentityFunctionInfo *RCFI) {
8586
assert(I->size() == 1);
8687
SILInstruction *Inst = *I->begin();
8788
assert((isa<StrongReleaseInst>(Inst) || isa<ReleaseValueInst>(Inst)) &&
8889
"strong_release and release_value are only supported.");
8990
(void) Inst;
9091

91-
bool NestingDetected = SuperTy::initWithMutatorInst(I);
92+
bool NestingDetected = SuperTy::initWithMutatorInst(I, RCFI);
9293

9394
// If we know that there is another decrement on the same pointer that has
9495
// not been matched up to an increment, then the pointer must have a
@@ -545,14 +546,15 @@ void BottomUpRefCountState::updateForPredTerminators(
545546
/// Initializes/reinitialized the state for I. If we reinitialize we return
546547
/// true.
547548
bool TopDownRefCountState::initWithMutatorInst(
548-
ImmutablePointerSet<SILInstruction> *I) {
549+
ImmutablePointerSet<SILInstruction> *I,
550+
RCIdentityFunctionInfo *RCFI) {
549551
assert(I->size() == 1);
550552
SILInstruction *Inst = *I->begin();
551553
(void)Inst;
552554
assert((isa<StrongRetainInst>(Inst) || isa<RetainValueInst>(Inst)) &&
553555
"strong_retain and retain_value are only supported.");
554556

555-
bool NestingDetected = SuperTy::initWithMutatorInst(I);
557+
bool NestingDetected = SuperTy::initWithMutatorInst(I, RCFI);
556558

557559
// This retain is known safe if the operand we are tracking was already
558560
// known incremented previously. This occurs when you have nested

lib/SILOptimizer/ARC/RefCountState.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/SIL/SILBasicBlock.h"
2323
#include "swift/SIL/InstructionUtils.h"
2424
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
25+
#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h"
2526
#include <algorithm>
2627

2728
namespace swift {
@@ -73,7 +74,8 @@ class RefCountState {
7374

7475
/// Initializes/reinitialized the state for I. If we reinitialize we return
7576
/// true.
76-
bool initWithMutatorInst(ImmutablePointerSet<SILInstruction> *I) {
77+
bool initWithMutatorInst(ImmutablePointerSet<SILInstruction> *I,
78+
RCIdentityFunctionInfo *RCFI) {
7779
assert(I->size() == 1);
7880

7981
// Are we already tracking a ref count modification?
@@ -86,7 +88,7 @@ class RefCountState {
8688
KnownSafe = false;
8789

8890
// Initialize value.
89-
RCRoot = stripCasts((*I->begin())->getOperand(0));
91+
RCRoot = RCFI->getRCIdentityRoot((*I->begin())->getOperand(0));
9092

9193
// Clear our insertion point list.
9294
InsertPts = ImmutablePointerSetFactory<SILInstruction>::getEmptySet();
@@ -204,7 +206,8 @@ class BottomUpRefCountState : public RefCountState {
204206

205207
/// Initializes/reinitialized the state for I. If we reinitialize we return
206208
/// true.
207-
bool initWithMutatorInst(ImmutablePointerSet<SILInstruction> *I);
209+
bool initWithMutatorInst(ImmutablePointerSet<SILInstruction> *I,
210+
RCIdentityFunctionInfo *RCFI);
208211

209212
/// Update this reference count's state given the instruction \p I. \p
210213
/// InsertPt is the point furthest up the CFG where we can move the currently
@@ -349,7 +352,8 @@ class TopDownRefCountState : public RefCountState {
349352

350353
/// Initializes/reinitialized the state for I. If we reinitialize we return
351354
/// true.
352-
bool initWithMutatorInst(ImmutablePointerSet<SILInstruction> *I);
355+
bool initWithMutatorInst(ImmutablePointerSet<SILInstruction> *I,
356+
RCIdentityFunctionInfo *RCFI);
353357

354358
/// Initialize the state given the consumed argument Arg.
355359
void initWithArg(SILArgument *Arg);

test/SILOptimizer/arcsequenceopts.sil

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ sil @user : $@convention(thin) (@box Builtin.Int32) -> ()
1212

1313
sil @owned_user : $@convention(thin) (@owned @box Builtin.Int32) -> ()
1414

15+
struct Int {
16+
var value : Builtin.Int64
17+
}
18+
1519
struct S {
1620
var x : Builtin.NativeObject
1721
}
@@ -46,11 +50,23 @@ class C {
4650
var w : FakeOptional<Builtin.NativeObject>
4751
}
4852

53+
sil @cls_use : $@convention(thin) (@owned Cls) -> ()
54+
4955
class Container {
5056
@sil_stored var c : Cls
5157
init()
5258
}
5359

60+
struct SContainer {
61+
@sil_stored var c : Cls
62+
init()
63+
}
64+
65+
struct SContainer2 {
66+
@sil_stored var b : Cls
67+
@sil_stored var c : Cls
68+
init()
69+
}
5470

5571
class RetainUser { }
5672

@@ -2067,3 +2083,76 @@ bb2(%4 : $ErrorType):
20672083
strong_release %0 : $Builtin.NativeObject
20682084
throw %4 : $ErrorType
20692085
}
2086+
2087+
// CHECK-LABEL: sil @retain_release_struct_with_single_nontrivial
2088+
// CHECK-NOT: strong_retain
2089+
// CHECK-NOT: strong_release
2090+
// CHECK: return
2091+
sil @retain_release_struct_with_single_nontrivial : $@convention(thin) (SContainer) -> () {
2092+
bb0(%0 : $SContainer):
2093+
retain_value %0 : $SContainer
2094+
%1 = struct_extract %0 : $SContainer, #SContainer.c
2095+
strong_release %1 : $Cls
2096+
%r = tuple()
2097+
return %r : $()
2098+
}
2099+
2100+
// CHECK-LABEL: sil @retain_release_struct_with_multiple_nontrivials
2101+
// CHECK: retain_value
2102+
// CHECK: strong_release
2103+
// CHECK: return
2104+
sil @retain_release_struct_with_multiple_nontrivials : $@convention(thin) (SContainer2) -> () {
2105+
bb0(%0 : $SContainer2):
2106+
retain_value %0 : $SContainer2
2107+
%1 = struct_extract %0 : $SContainer2, #SContainer2.c
2108+
strong_release %1 : $Cls
2109+
%r = tuple()
2110+
return %r : $()
2111+
}
2112+
2113+
// Make sure the RR pair is not removed here as a result of the decrement and use.
2114+
//
2115+
// CHECK-LABEL: sil @retain_release_struct_with_single_nontrivial_with_use_and_decrement
2116+
// CHECK: retain_value
2117+
// CHECK: release_value
2118+
sil @retain_release_struct_with_single_nontrivial_with_use_and_decrement : $@convention(thin) (SContainer) -> () {
2119+
bb0(%0 : $SContainer):
2120+
retain_value %0 : $SContainer
2121+
%1 = struct_extract %0 : $SContainer, #SContainer.c
2122+
%2 = function_ref @cls_use : $@convention(thin) (@owned Cls) -> ()
2123+
apply %2(%1) : $@convention(thin) (@owned Cls) -> ()
2124+
apply %2(%1) : $@convention(thin) (@owned Cls) -> ()
2125+
release_value %1 : $Cls
2126+
%r = tuple()
2127+
return %r : $()
2128+
}
2129+
2130+
// Make sure %0 and %1 are identified as rc-identical and the RR can be removed.
2131+
//
2132+
// CHECK-LABEL: sil @retain_release_tuple_with_single_nontrivial
2133+
// CHECK-NOT: strong_retain
2134+
// CHECK-NOT: strong_release
2135+
sil @retain_release_tuple_with_single_nontrivial : $@convention(thin) ((Cls, Int)) -> () {
2136+
bb0(%0 : $(Cls, Int)):
2137+
%1 = tuple_extract %0 : $(Cls, Int), 0
2138+
retain_value %0 : $(Cls, Int)
2139+
strong_release %1 : $Cls
2140+
%r = tuple()
2141+
return %r : $()
2142+
}
2143+
2144+
// Make sure %0 and %1 are not rc-identical and RR are not removed.
2145+
//
2146+
// CHECK-LABEL: sil @retain_release_tuple_with_multiple_nontrivials
2147+
// CHECK: retain_value
2148+
// CHECK: strong_release
2149+
sil @retain_release_tuple_with_multiple_nontrivials : $@convention(thin) ((Cls, Cls)) -> () {
2150+
bb0(%0 : $(Cls, Cls)):
2151+
%1 = tuple_extract %0 : $(Cls, Cls), 0
2152+
retain_value %0 : $(Cls, Cls)
2153+
strong_release %1 : $Cls
2154+
%r = tuple()
2155+
return %r : $()
2156+
}
2157+
2158+

0 commit comments

Comments
 (0)