Skip to content

[semantic-arc-opts] Create an explicit composition type for "ownership phi operands". #32172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions include/swift/SIL/OwnershipUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -598,8 +598,12 @@ struct OwnedValueIntroducer {
}

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

/// Returns true if this introducer when converted to guaranteed is expected
/// to have guaranteed operands that are consumed by the instruction.
///
/// E.x.: phi, struct.
bool hasConsumingGuaranteedOperands() const {
switch (kind) {
case OwnedValueIntroducerKind::Phi:
return true;
case OwnedValueIntroducerKind::Copy:
case OwnedValueIntroducerKind::LoadCopy:
case OwnedValueIntroducerKind::Apply:
case OwnedValueIntroducerKind::BeginApply:
case OwnedValueIntroducerKind::TryApply:
case OwnedValueIntroducerKind::LoadTake:
case OwnedValueIntroducerKind::FunctionArgument:
case OwnedValueIntroducerKind::PartialApplyInit:
case OwnedValueIntroducerKind::AllocBoxInit:
case OwnedValueIntroducerKind::AllocRefInit:
return false;
}
}

bool operator==(const OwnedValueIntroducer &other) const {
return value == other.value;
}
Expand Down
26 changes: 26 additions & 0 deletions include/swift/SIL/SILArgument.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ class SILArgument : public ValueBase {
bool
getIncomingPhiOperands(SmallVectorImpl<Operand *> &returnedPhiOperands) const;

/// If this argument is a true phi, for each operand in each predecessor block
/// associated with an incoming value, call visitor(op). Visitor must return
/// true for iteration to continue. False to stop it.
///
/// Returns false if this is not a true phi or that a visitor signaled error
/// by returning false.
bool visitIncomingPhiOperands(function_ref<bool(Operand *)> visitor) const;

/// Returns true if we were able to find a single terminator operand value for
/// each predecessor of this arguments basic block. The found values are
/// stored in OutArray.
Expand Down Expand Up @@ -248,6 +256,13 @@ class SILPhiArgument : public SILArgument {
bool
getIncomingPhiOperands(SmallVectorImpl<Operand *> &returnedPhiOperands) const;

/// If this argument is a phi, call visitor for each passing the operand for
/// each incoming phi values for each predecessor BB. If this argument is not
/// a phi, return false.
///
/// If visitor returns false, iteration is stopped and we return false.
bool visitIncomingPhiOperands(function_ref<bool(Operand *)> visitor) const;

/// Returns true if we were able to find a single terminator operand value for
/// each predecessor of this arguments basic block. The found values are
/// stored in OutArray.
Expand Down Expand Up @@ -442,6 +457,17 @@ inline bool SILArgument::getIncomingPhiOperands(
llvm_unreachable("Covered switch is not covered?!");
}

inline bool SILArgument::visitIncomingPhiOperands(
function_ref<bool(Operand *)> visitor) const {
switch (getKind()) {
case SILArgumentKind::SILPhiArgument:
return cast<SILPhiArgument>(this)->visitIncomingPhiOperands(visitor);
case SILArgumentKind::SILFunctionArgument:
return false;
}
llvm_unreachable("Covered switch is not covered?!");
}

} // end swift namespace

#endif
22 changes: 22 additions & 0 deletions lib/SIL/IR/SILArgument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,28 @@ bool SILPhiArgument::getIncomingPhiOperands(
return true;
}

bool SILPhiArgument::visitIncomingPhiOperands(
function_ref<bool(Operand *)> visitor) const {
if (!isPhiArgument())
return false;

const auto *parentBlock = getParent();
assert(!parentBlock->pred_empty());

unsigned argIndex = getIndex();
for (auto *predBlock : getParent()->getPredecessorBlocks()) {
Operand *incomingOperand =
getIncomingPhiOperandForPred(parentBlock, predBlock, argIndex);
assert(incomingOperand);

// Call the visitor, bailing if the callee signals error.
if (!visitor(incomingOperand)) {
return false;
}
}
return true;
}

bool SILPhiArgument::getIncomingPhiValues(
SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>>
&returnedPredBBAndPhiValuePairs) const {
Expand Down
Loading