Skip to content

Commit 8c44d36

Browse files
committed
[SIL] Add utility to transitively visit operands.
The new utility looks through operands whose values are themselves SILPhiArguments and visits those arguments' operands.
1 parent ab6faa9 commit 8c44d36

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

include/swift/SIL/SILArgument.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@ class SILPhiArgument : public SILArgument {
273273
/// If visitor returns false, iteration is stopped and we return false.
274274
bool visitIncomingPhiOperands(function_ref<bool(Operand *)> visitor) const;
275275

276+
/// Visit incoming phi operands and the argument into which they are incoming;
277+
/// if an operand's value is itself a phi, visit that phi's operands.
278+
///
279+
/// Returns false when called on a non-phi and when the visitor returns false.
280+
bool visitTransitiveIncomingPhiOperands(
281+
function_ref<bool(SILPhiArgument *, Operand *)> visitor);
282+
276283
/// Returns true if we were able to find a single terminator operand value for
277284
/// each predecessor of this arguments basic block. The found values are
278285
/// stored in OutArray.

lib/SIL/IR/SILArgument.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "llvm/ADT/STLExtras.h"
14-
#include "swift/SIL/SILBasicBlock.h"
1513
#include "swift/SIL/SILArgument.h"
14+
#include "swift/Basic/GraphNodeWorklist.h"
15+
#include "swift/SIL/SILBasicBlock.h"
1616
#include "swift/SIL/SILFunction.h"
1717
#include "swift/SIL/SILInstruction.h"
1818
#include "swift/SIL/SILModule.h"
19+
#include "llvm/ADT/STLExtras.h"
1920

2021
using namespace swift;
2122

@@ -226,6 +227,31 @@ bool SILPhiArgument::getIncomingPhiValues(
226227
return true;
227228
}
228229

230+
bool SILPhiArgument::visitTransitiveIncomingPhiOperands(
231+
function_ref<bool(SILPhiArgument *, Operand *)> visitor) {
232+
if (!isPhi())
233+
return false;
234+
235+
GraphNodeWorklist<SILPhiArgument *, 4> worklist;
236+
worklist.initialize(this);
237+
238+
while (auto *argument = worklist.pop()) {
239+
llvm::SmallVector<Operand *> operands;
240+
argument->getIncomingPhiOperands(operands);
241+
242+
for (auto *operand : operands) {
243+
SILPhiArgument *forwarded;
244+
if ((forwarded = dyn_cast<SILPhiArgument>(operand->get())) &&
245+
forwarded->isPhi()) {
246+
worklist.insert(forwarded);
247+
}
248+
if (!visitor(argument, operand))
249+
return false;
250+
}
251+
}
252+
return true;
253+
}
254+
229255
static SILValue
230256
getSingleTerminatorOperandForPred(const SILBasicBlock *parentBlock,
231257
const SILBasicBlock *predBlock,

0 commit comments

Comments
 (0)