Skip to content

Commit 0bed967

Browse files
committed
[semantic-arc-opts] Create an explicit composition type for "ownership phi operands".
This is letting me refactor the implementation of every place that I work with branches as "ownership phi operands" to instead work with OwnershipPhiOperand. In a future commit, I am going to use this to add support for optimizing structs and tuples that have multiple owned incoming values. <rdar://problem/63950481>
1 parent d3a5be4 commit 0bed967

File tree

4 files changed

+246
-55
lines changed

4 files changed

+246
-55
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,12 @@ struct OwnedValueIntroducer {
598598
}
599599

600600
/// Returns true if this owned introducer is able to be converted into a
601-
/// guaranteed form if none of its uses are consuming uses (looking through
602-
/// forwarding uses).
601+
/// guaranteed form if none of its direct uses are consuming uses (looking
602+
/// through forwarding uses).
603+
///
604+
/// NOTE: Since the direct uses must be non-consuming, this means that any
605+
/// "ownership phis" (e.x. branch, struct) must return false here since we can
606+
/// not analyze them without analyzing their operands/incoming values.
603607
bool isConvertableToGuaranteed() const {
604608
switch (kind) {
605609
case OwnedValueIntroducerKind::Copy:
@@ -619,6 +623,28 @@ struct OwnedValueIntroducer {
619623
llvm_unreachable("Covered switch isn't covered?!");
620624
}
621625

626+
/// Returns true if this introducer when converted to guaranteed is expected
627+
/// to have guaranteed operands that are consumed by the instruction.
628+
///
629+
/// E.x.: phi, struct.
630+
bool hasConsumingGuaranteedOperands() const {
631+
switch (kind) {
632+
case OwnedValueIntroducerKind::Phi:
633+
return true;
634+
case OwnedValueIntroducerKind::Copy:
635+
case OwnedValueIntroducerKind::LoadCopy:
636+
case OwnedValueIntroducerKind::Apply:
637+
case OwnedValueIntroducerKind::BeginApply:
638+
case OwnedValueIntroducerKind::TryApply:
639+
case OwnedValueIntroducerKind::LoadTake:
640+
case OwnedValueIntroducerKind::FunctionArgument:
641+
case OwnedValueIntroducerKind::PartialApplyInit:
642+
case OwnedValueIntroducerKind::AllocBoxInit:
643+
case OwnedValueIntroducerKind::AllocRefInit:
644+
return false;
645+
}
646+
}
647+
622648
bool operator==(const OwnedValueIntroducer &other) const {
623649
return value == other.value;
624650
}

include/swift/SIL/SILArgument.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@ class SILArgument : public ValueBase {
148148
bool
149149
getIncomingPhiOperands(SmallVectorImpl<Operand *> &returnedPhiOperands) const;
150150

151+
/// If this argument is a true phi, for each operand in each predecessor block
152+
/// associated with an incoming value, call visitor(op). Visitor must return
153+
/// true for iteration to continue. False to stop it.
154+
///
155+
/// Returns false if this is not a true phi or that a visitor signaled error
156+
/// by returning false.
157+
bool visitIncomingPhiOperands(function_ref<bool(Operand *)> visitor) const;
158+
151159
/// Returns true if we were able to find a single terminator operand value for
152160
/// each predecessor of this arguments basic block. The found values are
153161
/// stored in OutArray.
@@ -248,6 +256,13 @@ class SILPhiArgument : public SILArgument {
248256
bool
249257
getIncomingPhiOperands(SmallVectorImpl<Operand *> &returnedPhiOperands) const;
250258

259+
/// If this argument is a phi, call visitor for each passing the operand for
260+
/// each incoming phi values for each predecessor BB. If this argument is not
261+
/// a phi, return false.
262+
///
263+
/// If visitor returns false, iteration is stopped and we return false.
264+
bool visitIncomingPhiOperands(function_ref<bool(Operand *)> visitor) const;
265+
251266
/// Returns true if we were able to find a single terminator operand value for
252267
/// each predecessor of this arguments basic block. The found values are
253268
/// stored in OutArray.
@@ -442,6 +457,17 @@ inline bool SILArgument::getIncomingPhiOperands(
442457
llvm_unreachable("Covered switch is not covered?!");
443458
}
444459

460+
inline bool SILArgument::visitIncomingPhiOperands(
461+
function_ref<bool(Operand *)> visitor) const {
462+
switch (getKind()) {
463+
case SILArgumentKind::SILPhiArgument:
464+
return cast<SILPhiArgument>(this)->visitIncomingPhiOperands(visitor);
465+
case SILArgumentKind::SILFunctionArgument:
466+
return false;
467+
}
468+
llvm_unreachable("Covered switch is not covered?!");
469+
}
470+
445471
} // end swift namespace
446472

447473
#endif

lib/SIL/IR/SILArgument.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,28 @@ bool SILPhiArgument::getIncomingPhiOperands(
169169
return true;
170170
}
171171

172+
bool SILPhiArgument::visitIncomingPhiOperands(
173+
function_ref<bool(Operand *)> visitor) const {
174+
if (!isPhiArgument())
175+
return false;
176+
177+
const auto *parentBlock = getParent();
178+
assert(!parentBlock->pred_empty());
179+
180+
unsigned argIndex = getIndex();
181+
for (auto *predBlock : getParent()->getPredecessorBlocks()) {
182+
Operand *incomingOperand =
183+
getIncomingPhiOperandForPred(parentBlock, predBlock, argIndex);
184+
assert(incomingOperand);
185+
186+
// Call the visitor, bailing if the callee signals error.
187+
if (!visitor(incomingOperand)) {
188+
return false;
189+
}
190+
}
191+
return true;
192+
}
193+
172194
bool SILPhiArgument::getIncomingPhiValues(
173195
SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>>
174196
&returnedPredBBAndPhiValuePairs) const {

0 commit comments

Comments
 (0)