Skip to content

Commit 9d2af79

Browse files
committed
Simplify SILPHIArgument::getIncomingValue.
The client of this interface naturally expects to get back the incoming phi value. Ignoring dominance and SIL ownership, the incoming phi value and the block argument should be substitutable. This method was actually returning the incoming operand for checked_cast and switch_enum terminators, which is deeply misleading and has been the source of bugs. If the client wants to peek though casts, and enums, it should do so explicitly. getSingleTerminatorOperand[s]() will do just that.
1 parent 5f34199 commit 9d2af79

15 files changed

+239
-172
lines changed

include/swift/SIL/SILArgument.h

Lines changed: 116 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -77,41 +77,51 @@ class SILArgument : public ValueBase {
7777
llvm_unreachable("SILArgument not argument of its parent BB");
7878
}
7979

80-
/// Returns the incoming SILValue from the \p BBIndex predecessor of this
81-
/// argument's parent BB. If the routine fails, it returns an empty SILValue.
82-
/// Note that for some predecessor terminators the incoming value is not
83-
/// exactly the argument value. E.g. the incoming value for a switch_enum
84-
/// payload argument is the enum itself (the operand of the switch_enum).
85-
SILValue getIncomingValue(unsigned BBIndex);
86-
87-
/// Returns the incoming SILValue for this argument from BB. If the routine
88-
/// fails, it returns an empty SILValue.
89-
/// Note that for some predecessor terminators the incoming value is not
90-
/// exactly the argument value. E.g. the incoming value for a switch_enum
91-
/// payload argument is the enum itself (the operand of the switch_enum).
92-
SILValue getIncomingValue(SILBasicBlock *BB);
93-
94-
/// Returns true if we were able to find incoming values for each predecessor
95-
/// of this arguments basic block. The found values are stored in OutArray.
96-
/// Note that for some predecessor terminators the incoming value is not
97-
/// exactly the argument value. E.g. the incoming value for a switch_enum
98-
/// payload argument is the enum itself (the operand of the switch_enum).
99-
bool getIncomingValues(llvm::SmallVectorImpl<SILValue> &OutArray);
100-
101-
/// Returns true if we were able to find incoming values for each predecessor
102-
/// of this arguments basic block. The found values are stored in OutArray.
103-
/// Note that for some predecessor terminators the incoming value is not
104-
/// exactly the argument value. E.g. the incoming value for a switch_enum
105-
/// payload argument is the enum itself (the operand of the switch_enum).
106-
bool getIncomingValues(
80+
/// Return true if this block argument is actually a phi argument as
81+
/// opposed to a cast or projection.
82+
bool isPhiArgument();
83+
84+
/// If this argument is a phi, return the incoming phi value for the given
85+
/// predecessor BB. If this argument is not a phi, return an invalid SILValue.
86+
SILValue getIncomingPhiValue(SILBasicBlock *predBB);
87+
88+
/// If this argument is a phi, populate `OutArray` with the incoming phi
89+
/// values for each predecessor BB. If this argument is not a phi, return
90+
/// false.
91+
bool getIncomingPhiValues(llvm::SmallVectorImpl<SILValue> &ReturnedPhiValues);
92+
93+
/// If this argument is a phi, populate `OutArray` with each predecessor block
94+
/// and its incoming phi value. If this argument is not a phi, return false.
95+
bool getIncomingPhiValues(
96+
llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>>
97+
&ReturnedPredAndPhiValuePairs);
98+
99+
/// Returns true if we were able to find a single terminator operand value for
100+
/// each predecessor of this arguments basic block. The found values are
101+
/// stored in OutArray.
102+
///
103+
/// Note: this peeks through any projections or cast implied by the
104+
/// terminator. e.g. the incoming value for a switch_enum payload argument is
105+
/// the enum itself (the operand of the switch_enum).
106+
bool getSingleTerminatorOperands(llvm::SmallVectorImpl<SILValue> &OutArray);
107+
108+
/// Returns true if we were able to find single terminator operand values for
109+
/// each predecessor of this arguments basic block. The found values are
110+
/// stored in OutArray alongside their predecessor block.
111+
///
112+
/// Note: this peeks through any projections or cast implied by the
113+
/// terminator. e.g. the incoming value for a switch_enum payload argument is
114+
/// the enum itself (the operand of the switch_enum).
115+
bool getSingleTerminatorOperands(
107116
llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>> &OutArray);
108117

109-
/// If this SILArgument's parent block has one predecessor, return the
110-
/// incoming value from that predecessor. Returns SILValue() otherwise.
111-
/// Note that for some predecessor terminators the incoming value is not
112-
/// exactly the argument value. E.g. the incoming value for a switch_enum
113-
/// payload argument is the enum itself (the operand of the switch_enum).
114-
SILValue getSingleIncomingValue() const;
118+
/// If this SILArgument's parent block has a single predecessor whose
119+
/// terminator has a single operand, return the incoming operand of the
120+
/// predecessor's terminator. Returns SILValue() otherwise. Note that for
121+
/// some predecessor terminators the incoming value is not exactly the
122+
/// argument value. E.g. the incoming value for a switch_enum payload argument
123+
/// is the enum itself (the operand of the switch_enum).
124+
SILValue getSingleTerminatorOperand() const;
115125

116126
protected:
117127
SILArgument(ValueKind SubClassKind, SILBasicBlock *ParentBB, SILType Ty,
@@ -138,41 +148,59 @@ class SILArgument : public ValueBase {
138148

139149
class SILPHIArgument : public SILArgument {
140150
public:
141-
/// Returns the incoming SILValue from the \p BBIndex predecessor of this
142-
/// argument's parent BB. If the routine fails, it returns an empty SILValue.
143-
/// Note that for some predecessor terminators the incoming value is not
144-
/// exactly the argument value. E.g. the incoming value for a switch_enum
145-
/// payload argument is the enum itself (the operand of the switch_enum).
146-
SILValue getIncomingValue(unsigned BBIndex);
147-
148-
/// Returns the incoming SILValue for this argument from BB. If the routine
149-
/// fails, it returns an empty SILValue.
150-
/// Note that for some predecessor terminators the incoming value is not
151-
/// exactly the argument value. E.g. the incoming value for a switch_enum
152-
/// payload argument is the enum itself (the operand of the switch_enum).
153-
SILValue getIncomingValue(SILBasicBlock *BB);
154-
155-
/// Returns true if we were able to find incoming values for each predecessor
156-
/// of this arguments basic block. The found values are stored in OutArray.
157-
/// Note that for some predecessor terminators the incoming value is not
158-
/// exactly the argument value. E.g. the incoming value for a switch_enum
159-
/// payload argument is the enum itself (the operand of the switch_enum).
160-
bool getIncomingValues(llvm::SmallVectorImpl<SILValue> &OutArray);
161-
162-
/// Returns true if we were able to find incoming values for each predecessor
163-
/// of this arguments basic block. The found values are stored in OutArray.
164-
/// Note that for some predecessor terminators the incoming value is not
165-
/// exactly the argument value. E.g. the incoming value for a switch_enum
166-
/// payload argument is the enum itself (the operand of the switch_enum).
167-
bool getIncomingValues(
151+
/// Return true if this is block argument is actually a phi argument as
152+
/// opposed to a cast or projection.
153+
bool isPhiArgument();
154+
155+
/// If this argument is a phi, return the incoming phi value for the given
156+
/// predecessor BB. If this argument is not a phi, return an invalid SILValue.
157+
///
158+
/// FIXME: Once SILPHIArgument actually implies that it is a phi argument,
159+
/// this will be guaranteed to return a valid SILValue.
160+
SILValue getIncomingPhiValue(SILBasicBlock *BB);
161+
162+
/// If this argument is a phi, populate `OutArray` with the incoming phi
163+
/// values for each predecessor BB. If this argument is not a phi, return
164+
/// false.
165+
///
166+
/// FIXME: Once SILPHIArgument actually implies that it is a phi argument,
167+
/// this will always succeed.
168+
bool getIncomingPhiValues(llvm::SmallVectorImpl<SILValue> &OutArray);
169+
170+
/// If this argument is a phi, populate `OutArray` with each predecessor block
171+
/// and its incoming phi value. If this argument is not a phi, return false.
172+
///
173+
/// FIXME: Once SILPHIArgument actually implies that it is a phi argument,
174+
/// this will always succeed.
175+
bool getIncomingPhiValues(
168176
llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>> &OutArray);
169177

170-
/// If this SILArgument's parent block has one predecessor, return the
171-
/// incoming value from that predecessor. Returns SILValue() otherwise.
172-
/// Note that for some predecessor terminators the incoming value is not
173-
/// exactly the argument value. E.g. the incoming value for a switch_enum
174-
/// payload argument is the enum itself (the operand of the switch_enum).
175-
SILValue getSingleIncomingValue() const;
178+
/// Returns true if we were able to find a single terminator operand value for
179+
/// each predecessor of this arguments basic block. The found values are
180+
/// stored in OutArray.
181+
///
182+
/// Note: this peeks through any projections or cast implied by the
183+
/// terminator. e.g. the incoming value for a switch_enum payload argument is
184+
/// the enum itself (the operand of the switch_enum).
185+
bool getSingleTerminatorOperands(llvm::SmallVectorImpl<SILValue> &OutArray);
186+
187+
/// Returns true if we were able to find single terminator operand values for
188+
/// each predecessor of this arguments basic block. The found values are
189+
/// stored in OutArray alongside their predecessor block.
190+
///
191+
/// Note: this peeks through any projections or cast implied by the
192+
/// terminator. e.g. the incoming value for a switch_enum payload argument is
193+
/// the enum itself (the operand of the switch_enum).
194+
bool getSingleTerminatorOperands(
195+
llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>> &OutArray);
196+
197+
/// If this SILArgument's parent block has a single predecessor whose
198+
/// terminator has a single operand, return the incoming operand of the
199+
/// predecessor's terminator. Returns SILValue() otherwise. Note that for
200+
/// some predecessor terminators the incoming value is not exactly the
201+
/// argument value. E.g. the incoming value for a switch_enum payload argument
202+
/// is the enum itself (the operand of the switch_enum).
203+
SILValue getSingleTerminatorOperand() const;
176204

177205
static bool classof(const SILInstruction *) = delete;
178206
static bool classof(const SILUndef *) = delete;
@@ -254,36 +282,45 @@ class SILFunctionArgument : public SILArgument {
254282
// Out of line Definitions for SILArgument to avoid Forward Decl issues
255283
//===----------------------------------------------------------------------===//
256284

257-
inline SILValue SILArgument::getIncomingValue(unsigned BBIndex) {
258-
if (isa<SILFunctionArgument>(this))
259-
return SILValue();
260-
return cast<SILPHIArgument>(this)->getIncomingValue(BBIndex);
285+
inline bool SILArgument::isPhiArgument() {
286+
if (auto *phiArg = dyn_cast<SILPHIArgument>(this))
287+
return phiArg->isPhiArgument();
288+
289+
return false;
261290
}
262291

263-
inline SILValue SILArgument::getIncomingValue(SILBasicBlock *BB) {
292+
inline SILValue SILArgument::getIncomingPhiValue(SILBasicBlock *BB) {
264293
if (isa<SILFunctionArgument>(this))
265294
return SILValue();
266-
return cast<SILPHIArgument>(this)->getIncomingValue(BB);
295+
return cast<SILPHIArgument>(this)->getIncomingPhiValue(BB);
267296
}
268297

269298
inline bool
270-
SILArgument::getIncomingValues(llvm::SmallVectorImpl<SILValue> &OutArray) {
299+
SILArgument::getIncomingPhiValues(llvm::SmallVectorImpl<SILValue> &OutArray) {
271300
if (isa<SILFunctionArgument>(this))
272301
return false;
273-
return cast<SILPHIArgument>(this)->getIncomingValues(OutArray);
302+
return cast<SILPHIArgument>(this)->getIncomingPhiValues(OutArray);
274303
}
275304

276-
inline bool SILArgument::getIncomingValues(
305+
inline bool SILArgument::getIncomingPhiValues(
277306
llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>> &OutArray) {
278307
if (isa<SILFunctionArgument>(this))
279308
return false;
280-
return cast<SILPHIArgument>(this)->getIncomingValues(OutArray);
309+
return cast<SILPHIArgument>(this)->getIncomingPhiValues(OutArray);
281310
}
282311

283-
inline SILValue SILArgument::getSingleIncomingValue() const {
312+
inline bool SILArgument::getSingleTerminatorOperands(
313+
llvm::SmallVectorImpl<SILValue> &OutArray) {
284314
if (isa<SILFunctionArgument>(this))
285-
return SILValue();
286-
return cast<SILPHIArgument>(this)->getSingleIncomingValue();
315+
return false;
316+
return cast<SILPHIArgument>(this)->getSingleTerminatorOperands(OutArray);
317+
}
318+
319+
inline bool SILArgument::getSingleTerminatorOperands(
320+
llvm::SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>> &OutArray) {
321+
if (isa<SILFunctionArgument>(this))
322+
return false;
323+
return cast<SILPHIArgument>(this)->getSingleTerminatorOperands(OutArray);
287324
}
288325

289326
} // end swift namespace

lib/SIL/InstructionUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ void swift::findClosuresForFunctionValue(
465465
// This should be done before calling findClosureStoredIntoBlock.
466466
if (auto *arg = dyn_cast<SILPHIArgument>(V)) {
467467
SmallVector<std::pair<SILBasicBlock *, SILValue>, 2> blockArgs;
468-
arg->getIncomingValues(blockArgs);
468+
arg->getIncomingPhiValues(blockArgs);
469469
for (auto &blockAndArg : blockArgs)
470470
worklistInsert(blockAndArg.second);
471471

0 commit comments

Comments
 (0)