Skip to content

Commit b745691

Browse files
committed
SIL refactoring: Move some functions out of SILValue and Operand
SILValue.h/.cpp just defines the SIL base classes. Referring to specific instructions is a (small) kind of layering violation. Also I want to keep SILValue small so that it is really just a type alias of ValueBase*. NFC.
1 parent 1383612 commit b745691

21 files changed

+332
-300
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===--- InstructionUtils.h - Utilities for SIL instructions ----*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_SIL_INSTRUCTIONUTILS_H
14+
#define SWIFT_SIL_INSTRUCTIONUTILS_H
15+
16+
#include "swift/SIL/SILInstruction.h"
17+
18+
namespace swift {
19+
20+
/// Strip off casts/indexing insts/address projections from V until there is
21+
/// nothing left to strip.
22+
SILValue getUnderlyingObject(SILValue V);
23+
24+
SILValue stripSinglePredecessorArgs(SILValue V);
25+
26+
/// Return the underlying SILValue after stripping off all casts from the
27+
/// current SILValue.
28+
SILValue stripCasts(SILValue V);
29+
30+
/// Return the underlying SILValue after stripping off all upcasts from the
31+
/// current SILValue.
32+
SILValue stripUpCasts(SILValue V);
33+
34+
/// Return the underlying SILValue after stripping off all
35+
/// upcasts and downcasts.
36+
SILValue stripClassCasts(SILValue V);
37+
38+
/// Return the underlying SILValue after stripping off all casts and
39+
/// address projection instructions.
40+
///
41+
/// An address projection instruction is one of one of ref_element_addr,
42+
/// struct_element_addr, tuple_element_addr.
43+
SILValue stripAddressProjections(SILValue V);
44+
45+
/// Return the underlying SILValue after stripping off all aggregate projection
46+
/// instructions.
47+
///
48+
/// An aggregate projection instruction is either a struct_extract or a
49+
/// tuple_extract instruction.
50+
SILValue stripValueProjections(SILValue V);
51+
52+
/// Return the underlying SILValue after stripping off all indexing
53+
/// instructions.
54+
///
55+
/// An indexing inst is either index_addr or index_raw_pointer.
56+
SILValue stripIndexingInsts(SILValue V);
57+
58+
/// Returns the underlying value after stripping off a builtin expect
59+
/// intrinsic call.
60+
SILValue stripExpectIntrinsic(SILValue V);
61+
62+
} // end namespace swift
63+
64+
#endif

include/swift/SIL/SILValue.h

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -194,42 +194,6 @@ class SILValue {
194194
/// (see comment in DebugUtils.h).
195195
inline bool hasOneUse() const { return Value->hasOneUse(); }
196196

197-
/// Return the underlying SILValue after stripping off all casts from the
198-
/// current SILValue.
199-
SILValue stripCasts();
200-
201-
/// Return the underlying SILValue after stripping off all upcasts from the
202-
/// current SILValue.
203-
SILValue stripUpCasts();
204-
205-
/// Return the underlying SILValue after stripping off all
206-
/// upcasts and downcasts.
207-
SILValue stripClassCasts();
208-
209-
/// Return the underlying SILValue after stripping off all casts and
210-
/// address projection instructions.
211-
///
212-
/// An address projection instruction is one of one of ref_element_addr,
213-
/// struct_element_addr, tuple_element_addr.
214-
SILValue stripAddressProjections();
215-
216-
/// Return the underlying SILValue after stripping off all aggregate projection
217-
/// instructions.
218-
///
219-
/// An aggregate projection instruction is either a struct_extract or a
220-
/// tuple_extract instruction.
221-
SILValue stripValueProjections();
222-
223-
/// Return the underlying SILValue after stripping off all indexing
224-
/// instructions.
225-
///
226-
/// An indexing inst is either index_addr or index_raw_pointer.
227-
SILValue stripIndexingInsts();
228-
229-
/// Returns the underlying value after stripping off a builtin expect
230-
/// intrinsic call.
231-
SILValue stripExpectIntrinsic();
232-
233197
void dump() const;
234198
void print(raw_ostream &os) const;
235199

@@ -336,13 +300,6 @@ class Operand {
336300
/// using instruction.
337301
unsigned getOperandNumber() const;
338302

339-
/// Hoist the address projection rooted in this operand to \p InsertBefore.
340-
/// Requires the projected value to dominate the insertion point.
341-
///
342-
/// Will look through single basic block predecessor arguments.
343-
void hoistAddressProjections(SILInstruction *InsertBefore,
344-
DominanceInfo *DomTree);
345-
346303
private:
347304
void removeFromCurrent() {
348305
if (!Back) return;

include/swift/SILOptimizer/Analysis/ValueTracking.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ namespace swift {
2323

2424
class SILValue;
2525

26-
/// Strip off casts/indexing insts/address projections from V until there is
27-
/// nothing left to strip.
28-
SILValue getUnderlyingObject(SILValue V);
29-
3026
/// Returns true if \p V is a function argument which may not alias to
3127
/// any other pointer in the function.
3228
/// The \p assumeInoutIsNotAliasing specifies in no-aliasing is assumed for

include/swift/SILOptimizer/Utils/Local.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,13 @@ void replaceLoadSequence(SILInstruction *I,
648648
/// be reached by calling the function represented by Decl?
649649
bool calleesAreStaticallyKnowable(SILModule &M, SILDeclRef Decl);
650650

651+
/// Hoist the address projection rooted in \p Op to \p InsertBefore.
652+
/// Requires the projected value to dominate the insertion point.
653+
///
654+
/// Will look through single basic block predecessor arguments.
655+
void hoistAddressProjections(Operand &Op, SILInstruction *InsertBefore,
656+
DominanceInfo *DomTree);
657+
651658
} // end namespace swift
652659

653660
#endif

lib/SIL/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ add_swift_library(swiftSIL
44
Dominance.cpp
55
DynamicCasts.cpp
66
PrettyStackTrace.cpp
7+
InstructionUtils.cpp
78
SIL.cpp
89
SILArgument.cpp
910
SILBasicBlock.cpp

lib/SIL/InstructionUtils.cpp

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
//===--- InstructionUtils.cpp - Utilities for SIL instructions ------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#define DEBUG_TYPE "sil-inst-utils"
14+
#include "swift/SIL/InstructionUtils.h"
15+
#include "swift/SIL/SILArgument.h"
16+
#include "swift/SIL/SILBasicBlock.h"
17+
#include "swift/SIL/Projection.h"
18+
19+
using namespace swift;
20+
21+
/// Strip off casts/indexing insts/address projections from V until there is
22+
/// nothing left to strip.
23+
/// FIXME: Why don't we strip projections after stripping indexes?
24+
SILValue swift::getUnderlyingObject(SILValue V) {
25+
while (true) {
26+
SILValue V2 = stripIndexingInsts(stripAddressProjections(stripCasts(V)));
27+
if (V2 == V)
28+
return V2;
29+
V = V2;
30+
}
31+
}
32+
33+
static bool isRCIdentityPreservingCast(ValueKind Kind) {
34+
switch (Kind) {
35+
case ValueKind::UpcastInst:
36+
case ValueKind::UncheckedRefCastInst:
37+
case ValueKind::UncheckedRefCastAddrInst:
38+
case ValueKind::UnconditionalCheckedCastInst:
39+
case ValueKind::RefToBridgeObjectInst:
40+
case ValueKind::BridgeObjectToRefInst:
41+
return true;
42+
default:
43+
return false;
44+
}
45+
}
46+
47+
/// Return the underlying SILValue after stripping off identity SILArguments if
48+
/// we belong to a BB with one predecessor.
49+
SILValue swift::stripSinglePredecessorArgs(SILValue V) {
50+
while (true) {
51+
auto *A = dyn_cast<SILArgument>(V);
52+
if (!A)
53+
return V;
54+
55+
SILBasicBlock *BB = A->getParent();
56+
57+
// First try and grab the single predecessor of our parent BB. If we don't
58+
// have one, bail.
59+
SILBasicBlock *Pred = BB->getSinglePredecessor();
60+
if (!Pred)
61+
return V;
62+
63+
// Then grab the terminator of Pred...
64+
TermInst *PredTI = Pred->getTerminator();
65+
66+
// And attempt to find our matching argument.
67+
//
68+
// *NOTE* We can only strip things here if we know that there is no semantic
69+
// change in terms of upcasts/downcasts/enum extraction since this is used
70+
// by other routines here. This means that we can only look through
71+
// cond_br/br.
72+
//
73+
// For instance, routines that use stripUpcasts() do not want to strip off a
74+
// downcast that results from checked_cast_br.
75+
if (auto *BI = dyn_cast<BranchInst>(PredTI)) {
76+
V = BI->getArg(A->getIndex());
77+
continue;
78+
}
79+
80+
if (auto *CBI = dyn_cast<CondBranchInst>(PredTI)) {
81+
if (SILValue Arg = CBI->getArgForDestBB(BB, A)) {
82+
V = Arg;
83+
continue;
84+
}
85+
}
86+
87+
return V;
88+
}
89+
}
90+
91+
SILValue swift::stripCasts(SILValue V) {
92+
while (true) {
93+
V = stripSinglePredecessorArgs(V);
94+
95+
auto K = V->getKind();
96+
if (isRCIdentityPreservingCast(K)
97+
|| K == ValueKind::UncheckedTrivialBitCastInst
98+
|| K == ValueKind::MarkDependenceInst) {
99+
V = cast<SILInstruction>(V.getDef())->getOperand(0);
100+
continue;
101+
}
102+
103+
return V;
104+
}
105+
}
106+
107+
SILValue swift::stripUpCasts(SILValue V) {
108+
assert(V.getType().isClassOrClassMetatype() &&
109+
"Expected class or class metatype!");
110+
111+
V = stripSinglePredecessorArgs(V);
112+
113+
while (isa<UpcastInst>(V))
114+
V = stripSinglePredecessorArgs(cast<UpcastInst>(V)->getOperand());
115+
116+
return V;
117+
}
118+
119+
SILValue swift::stripClassCasts(SILValue V) {
120+
while (true) {
121+
if (auto *UI = dyn_cast<UpcastInst>(V)) {
122+
V = UI->getOperand();
123+
continue;
124+
}
125+
126+
if (auto *UCCI = dyn_cast<UnconditionalCheckedCastInst>(V)) {
127+
V = UCCI->getOperand();
128+
continue;
129+
}
130+
131+
return V;
132+
}
133+
}
134+
135+
SILValue swift::stripAddressProjections(SILValue V) {
136+
while (true) {
137+
V = stripSinglePredecessorArgs(V);
138+
if (!NewProjection::isAddressProjection(V))
139+
return V;
140+
V = cast<SILInstruction>(V.getDef())->getOperand(0);
141+
}
142+
}
143+
144+
SILValue swift::stripValueProjections(SILValue V) {
145+
while (true) {
146+
V = stripSinglePredecessorArgs(V);
147+
if (!NewProjection::isObjectProjection(V))
148+
return V;
149+
V = cast<SILInstruction>(V.getDef())->getOperand(0);
150+
}
151+
}
152+
153+
SILValue swift::stripIndexingInsts(SILValue V) {
154+
while (true) {
155+
if (!isa<IndexingInst>(V.getDef()))
156+
return V;
157+
V = cast<IndexingInst>(V)->getBase();
158+
}
159+
}
160+
161+
SILValue swift::stripExpectIntrinsic(SILValue V) {
162+
auto *BI = dyn_cast<BuiltinInst>(V);
163+
if (!BI)
164+
return V;
165+
if (BI->getIntrinsicInfo().ID != llvm::Intrinsic::expect)
166+
return V;
167+
return BI->getArguments()[0];
168+
}

lib/SIL/Projection.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "swift/SIL/Projection.h"
1515
#include "swift/Basic/NullablePtr.h"
1616
#include "swift/SIL/SILBuilder.h"
17+
#include "swift/SIL/InstructionUtils.h"
1718
#include "swift/SIL/DebugUtils.h"
1819
#include "llvm/ADT/None.h"
1920
#include "llvm/Support/Debug.h"
@@ -1127,7 +1128,7 @@ ProjectionPath::getAddrProjectionPath(SILValue Start, SILValue End,
11271128
// End is a projection at all.
11281129
auto Iter = End;
11291130
if (IgnoreCasts)
1130-
Iter = Iter.stripCasts();
1131+
Iter = stripCasts(Iter);
11311132
bool NextAddrIsIndex = false;
11321133
while (Projection::isAddrProjection(Iter) && Start != Iter) {
11331134
Projection AP = *Projection::addressProjectionForValue(Iter);
@@ -1136,7 +1137,7 @@ ProjectionPath::getAddrProjectionPath(SILValue Start, SILValue End,
11361137

11371138
Iter = cast<SILInstruction>(*Iter).getOperand(0);
11381139
if (IgnoreCasts)
1139-
Iter = Iter.stripCasts();
1140+
Iter = stripCasts(Iter);
11401141
}
11411142

11421143
// Return None if we have an empty projection list or if Start == Iter.

0 commit comments

Comments
 (0)