Skip to content

Commit 83b01d8

Browse files
committed
Improve the SILPhiArgument API
This subclass of SILArgument should be eliminated--it's not always a phi, and whether it is a "phi argument" has nothing whatsoever to do with the opcode. That is a property of a value's uses, not a property of the value. Until then, provide a logical and useful API within the type. This often avoids the need to explicitly cast to a SILPhiArgument type and avoids a lot of boilerplate in code that deals with phis. Note: PhiOperand and PhiValue are improved abstractions on top of this API. But the SILArgument-level API is still an important bridge between SILArgument and other phi abstractions.
1 parent 05224aa commit 83b01d8

File tree

11 files changed

+64
-32
lines changed

11 files changed

+64
-32
lines changed

include/swift/SIL/MemAccessUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,7 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
16891689

16901690
case ValueKind::SILPhiArgument: {
16911691
auto *phiArg = cast<SILPhiArgument>(sourceAddr);
1692-
if (phiArg->isPhiArgument()) {
1692+
if (phiArg->isPhi()) {
16931693
return asImpl().visitPhi(phiArg);
16941694
}
16951695

include/swift/SIL/SILArgument.h

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace swift {
2222

2323
class SILBasicBlock;
2424
class SILModule;
25+
class SILPhiArgument;
2526
class SILUndef;
2627
class TermInst;
2728

@@ -115,9 +116,15 @@ class SILArgument : public ValueBase {
115116

116117
unsigned getIndex() const;
117118

118-
/// Return true if this block argument is actually a phi argument as
119-
/// opposed to a cast or projection.
120-
bool isPhiArgument() const;
119+
/// Return non-null if \p value is a phi.
120+
static SILPhiArgument *isPhi(SILValue value);
121+
122+
/// Return non-null if \p value is a terminator result.
123+
static SILPhiArgument *isTerminatorResult(SILValue value);
124+
125+
/// Return true if this block argument is a phi as opposed to a terminator
126+
/// result.
127+
bool isPhi() const;
121128

122129
/// Return true if this block argument is a terminator result.
123130
bool isTerminatorResult() const;
@@ -217,12 +224,12 @@ class SILPhiArgument : public SILArgument {
217224
: SILArgument(ValueKind::SILPhiArgument, type, ownershipKind, decl) {}
218225

219226
public:
220-
/// Return true if this is block argument is actually a phi argument as
221-
/// opposed to a cast or projection.
222-
bool isPhiArgument() const;
227+
/// Return true if this is block argument is a phi, as opposed to a terminator
228+
/// result.
229+
bool isPhi() const;
223230

224231
/// Return true if this block argument is a terminator result.
225-
bool isTerminatorResult() const { return !isPhiArgument(); }
232+
bool isTerminatorResult() const { return !isPhi(); }
226233

227234
/// If this argument is a phi, return the incoming phi value for the given
228235
/// predecessor BB. If this argument is not a phi, return an invalid SILValue.
@@ -365,16 +372,34 @@ class SILFunctionArgument : public SILArgument {
365372
// Out of line Definitions for SILArgument to avoid Forward Decl issues
366373
//===----------------------------------------------------------------------===//
367374

368-
inline bool SILArgument::isPhiArgument() const {
375+
/// Return non-null if \p value is a real phi argument.
376+
inline SILPhiArgument *SILArgument::isPhi(SILValue value) {
377+
if (auto *arg = dyn_cast<SILPhiArgument>(value)) {
378+
if (arg->isPhi())
379+
return arg;
380+
}
381+
return nullptr;
382+
}
383+
384+
inline bool SILArgument::isPhi() const {
369385
switch (getKind()) {
370386
case SILArgumentKind::SILPhiArgument:
371-
return cast<SILPhiArgument>(this)->isPhiArgument();
387+
return cast<SILPhiArgument>(this)->isPhi();
372388
case SILArgumentKind::SILFunctionArgument:
373389
return false;
374390
}
375391
llvm_unreachable("Covered switch is not covered?!");
376392
}
377393

394+
/// Return non-null if \p value is a terminator result.
395+
inline SILPhiArgument *SILArgument::isTerminatorResult(SILValue value) {
396+
if (auto *arg = dyn_cast<SILPhiArgument>(value)) {
397+
if (arg->isTerminatorResult())
398+
return arg;
399+
}
400+
return nullptr;
401+
}
402+
378403
inline bool SILArgument::isNoImplicitCopy() const {
379404
if (auto *fArg = dyn_cast<SILFunctionArgument>(this))
380405
return fArg->isNoImplicitCopy();

include/swift/SIL/SILBasicBlock.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ struct PhiValue {
581581

582582
PhiValue(SILValue value) {
583583
auto *blockArg = dyn_cast<SILPhiArgument>(value);
584-
if (!blockArg || !blockArg->isPhiArgument())
584+
if (!blockArg || !blockArg->isPhi())
585585
return;
586586

587587
phiBlock = blockArg->getParent();
@@ -600,6 +600,11 @@ struct PhiValue {
600600
return cast<SILPhiArgument>(phiBlock->getArgument(argIndex));
601601
}
602602

603+
Operand *getOperand(SILBasicBlock *predecessor) {
604+
auto *branch = cast<BranchInst>(predecessor->getTerminator());
605+
return &branch->getAllOperands()[argIndex];
606+
}
607+
603608
operator SILValue() const { return getValue(); }
604609
SILValue operator*() const { return getValue(); }
605610
SILValue operator->() const { return getValue(); }

lib/SIL/IR/SILArgument.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ SILParameterInfo SILFunctionArgument::getKnownParameterInfo() const {
8282
// expensive to call this helper instead of simply specifying phis with an
8383
// opcode. It results in repeated CFG traversals and repeated, unnecessary
8484
// switching over terminator opcodes.
85-
bool SILPhiArgument::isPhiArgument() const {
85+
bool SILPhiArgument::isPhi() const {
8686
// No predecessors indicates an unreachable block.
8787
if (getParent()->pred_empty())
8888
return false;
@@ -128,7 +128,7 @@ static SILValue getIncomingPhiValueForPred(const SILBasicBlock *parentBlock,
128128
}
129129

130130
SILValue SILPhiArgument::getIncomingPhiValue(SILBasicBlock *predBlock) const {
131-
if (!isPhiArgument())
131+
if (!isPhi())
132132
return SILValue();
133133

134134
const auto *parentBlock = getParent();
@@ -145,7 +145,7 @@ SILValue SILPhiArgument::getIncomingPhiValue(SILBasicBlock *predBlock) const {
145145

146146
bool SILPhiArgument::getIncomingPhiValues(
147147
SmallVectorImpl<SILValue> &returnedPhiValues) const {
148-
if (!isPhiArgument())
148+
if (!isPhi())
149149
return false;
150150

151151
const auto *parentBlock = getParent();
@@ -162,14 +162,14 @@ bool SILPhiArgument::getIncomingPhiValues(
162162
}
163163

164164
Operand *SILPhiArgument::getIncomingPhiOperand(SILBasicBlock *predBlock) const {
165-
if (!isPhiArgument())
165+
if (!isPhi())
166166
return nullptr;
167167
return getIncomingPhiOperandForPred(getParent(), predBlock, getIndex());
168168
}
169169

170170
bool SILPhiArgument::getIncomingPhiOperands(
171171
SmallVectorImpl<Operand *> &returnedPhiOperands) const {
172-
if (!isPhiArgument())
172+
if (!isPhi())
173173
return false;
174174

175175
const auto *parentBlock = getParent();
@@ -187,7 +187,7 @@ bool SILPhiArgument::getIncomingPhiOperands(
187187

188188
bool SILPhiArgument::visitIncomingPhiOperands(
189189
function_ref<bool(Operand *)> visitor) const {
190-
if (!isPhiArgument())
190+
if (!isPhi())
191191
return false;
192192

193193
const auto *parentBlock = getParent();
@@ -210,7 +210,7 @@ bool SILPhiArgument::visitIncomingPhiOperands(
210210
bool SILPhiArgument::getIncomingPhiValues(
211211
SmallVectorImpl<std::pair<SILBasicBlock *, SILValue>>
212212
&returnedPredBBAndPhiValuePairs) const {
213-
if (!isPhiArgument())
213+
if (!isPhi())
214214
return false;
215215

216216
const auto *parentBlock = getParent();
@@ -318,8 +318,10 @@ TermInst *SILPhiArgument::getSingleTerminator() const {
318318

319319
TermInst *SILPhiArgument::getTerminatorForResult() const {
320320
if (auto *termInst = getSingleTerminator()) {
321-
if (!isa<BranchInst>(termInst) && !isa<CondBranchInst>(termInst))
321+
if (!swift::isa<BranchInst>(termInst)
322+
&& !swift::isa<CondBranchInst>(termInst)) {
322323
return termInst;
324+
}
323325
}
324326
return nullptr;
325327
}

lib/SIL/IR/SILBasicBlock.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ bool SILBasicBlock::hasPhi() const {
401401
// It is sufficient to check whether the first argument is a phi. A block
402402
// can't have both phis and terminator results.
403403
auto *argument = getArguments()[0];
404-
return argument->isPhiArgument();
404+
return argument->isPhi();
405405
}
406406

407407
const SILDebugScope *SILBasicBlock::getScopeOfFirstNonMetaInstruction() {

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ class FindReferenceRoot {
789789
ref = svi->getOperand(0);
790790
};
791791
auto *phi = dyn_cast<SILPhiArgument>(ref);
792-
if (!phi || !phi->isPhiArgument()) {
792+
if (!phi || !phi->isPhi()) {
793793
return ref;
794794
}
795795
// Handle phis...
@@ -1533,7 +1533,7 @@ class AccessPathDefUseTraversal {
15331533
void initializeDFS(SILValue root) {
15341534
// If root is a phi, record it so that its uses aren't visited twice.
15351535
if (auto *phi = dyn_cast<SILPhiArgument>(root)) {
1536-
if (phi->isPhiArgument())
1536+
if (phi->isPhi())
15371537
visitedPhis.insert(phi);
15381538
}
15391539
pushUsers(root,

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
10031003
// Verify that the `isPhiArgument` property is sound:
10041004
// - Phi arguments come from branches.
10051005
// - Non-phi arguments have a single predecessor.
1006-
assert(arg->isPhiArgument() && "precondition");
1006+
assert(arg->isPhi() && "precondition");
10071007
for (SILBasicBlock *predBB : arg->getParent()->getPredecessorBlocks()) {
10081008
auto *TI = predBB->getTerminator();
10091009
if (F.hasOwnership()) {
@@ -1015,7 +1015,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
10151015
"All phi argument inputs must be from branches.");
10161016
}
10171017
}
1018-
if (arg->isPhiArgument() && prohibitAddressPhis()) {
1018+
if (arg->isPhi() && prohibitAddressPhis()) {
10191019
// As a property of well-formed SIL, we disallow address-type
10201020
// phis. Supporting them would prevent reliably reasoning about the
10211021
// underlying storage of memory access. This reasoning is important for
@@ -1033,7 +1033,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
10331033
checkLegalType(arg->getFunction(), arg, nullptr);
10341034
checkValueBaseOwnership(arg);
10351035
if (auto *phiArg = dyn_cast<SILPhiArgument>(arg)) {
1036-
if (phiArg->isPhiArgument())
1036+
if (phiArg->isPhi())
10371037
visitSILPhiArgument(phiArg);
10381038
else {
10391039
// A non-phi BlockArgument must have a single predecessor unless it is

lib/SILOptimizer/Transforms/DeadCodeElimination.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,8 +575,8 @@ bool DCE::removeDead() {
575575
continue;
576576
}
577577

578-
if (!arg->isPhiArgument()) {
579-
// We cannot delete a non phi arg. If it was @owned, insert a
578+
if (!arg->isPhi()) {
579+
// We cannot delete a non phi. If it was @owned, insert a
580580
// destroy_value, because its consuming user has already been marked
581581
// dead and will be deleted.
582582
// We do not have to end lifetime of a @guaranteed non phi arg.

lib/SILOptimizer/Transforms/PhiArgumentOptimizations.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ static bool hasOnlyNoneOwnershipIncomingValues(SILPhiArgument *phi) {
106106
if (incomingValue.getOwnershipKind() == OwnershipKind::None)
107107
continue;
108108
if (auto *incomingPhi = dyn_cast<SILPhiArgument>(incomingValue)) {
109-
if (incomingPhi->isPhiArgument()) {
109+
if (incomingPhi->isPhi()) {
110110
worklist.insert(incomingPhi);
111111
continue;
112112
}
@@ -153,7 +153,7 @@ bool RedundantPhiEliminationPass::optimizeArgs(SILBasicBlock *block) {
153153

154154
SILArgument *arg1 = block->getArgument(arg1Idx);
155155
SILArgument *arg2 = block->getArgument(arg2Idx);
156-
if (!arg1->isPhiArgument() || !arg2->isPhiArgument())
156+
if (!arg1->isPhi() || !arg2->isPhi())
157157
continue;
158158

159159
if (valuesAreEqual(arg1, arg2)) {
@@ -343,7 +343,7 @@ void PhiExpansionPass::run() {
343343
bool changed = false;
344344
for (SILBasicBlock &block : *getFunction()) {
345345
for (auto argAndIdx : enumerate(block.getArguments())) {
346-
if (!argAndIdx.value()->isPhiArgument())
346+
if (!argAndIdx.value()->isPhi())
347347
continue;
348348

349349
unsigned idx = argAndIdx.index();

lib/SILOptimizer/Transforms/SimplifyCFG.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,7 @@ TrampolineDest::TrampolineDest(SILBasicBlock *sourceBB,
13241324
for (SILValue branchArg : targetBranch->getArgs()) {
13251325
if (branchArg->getParentBlock() == targetBB) {
13261326
auto *phi = dyn_cast<SILPhiArgument>(branchArg);
1327-
if (!phi || !phi->isPhiArgument()) {
1327+
if (!phi || !phi->isPhi()) {
13281328
return;
13291329
}
13301330
branchArg = phi->getIncomingPhiValue(sourceBB);

0 commit comments

Comments
 (0)