Skip to content

Commit 2f3670f

Browse files
committed
[opt-remark] Move Argument::inferArgumentFromValue into OptRemarkGenerator.
I noticed that I kept on needing to hack on this as I added stuff to OptRemarkGenerator and felt the need to tie it even closer to OptRemarkGenerator. As I began to think about it, this is really something specific to that algorithm, so it really doesn't make sense to have it as part of the general SIL library. This is a NFC refactoring.
1 parent a2d648f commit 2f3670f

File tree

3 files changed

+85
-53
lines changed

3 files changed

+85
-53
lines changed

include/swift/SIL/OptimizationRemark.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,6 @@ struct Argument {
119119
: Argument(ArgumentKey(ArgumentKeyKind::Default, key), msg, decl) {}
120120
Argument(ArgumentKey key, StringRef msg, const ValueDecl *decl)
121121
: key(key), val(msg), loc(decl->getLoc()) {}
122-
123-
/// Given a value, call \p funcPassedInferredArgs for each associated
124-
/// ValueDecl that is associated with \p value. All created Arguments are
125-
/// passed the same StringRef. To stop iteration, return false in \p
126-
/// funcPassedInferedArgs.
127-
///
128-
/// NOTE: the function may be called multiple times if the optimizer joined
129-
/// two live ranges and thus when iterating over value's users we see multiple
130-
/// debug_value operations.
131-
static bool
132-
inferArgumentsForValue(ArgumentKeyKind keyKind, StringRef message,
133-
SILValue value,
134-
function_ref<bool(Argument)> funcPassedInferedArgs);
135122
};
136123

137124
/// Shorthand to insert named-value pairs.

lib/SIL/Utils/OptimizationRemark.cpp

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -77,42 +77,6 @@ Argument::Argument(StringRef key, CanType ty)
7777
ty.print(stream);
7878
}
7979

80-
bool Argument::inferArgumentsForValue(
81-
ArgumentKeyKind keyKind, StringRef msg, SILValue value,
82-
function_ref<bool(Argument)> funcPassedInferedArgs) {
83-
84-
while (true) {
85-
// If we have an argument, just use that.
86-
if (auto *arg = dyn_cast<SILArgument>(value))
87-
if (auto *decl = arg->getDecl())
88-
return funcPassedInferedArgs(
89-
Argument({keyKind, "InferredValue"}, msg, decl));
90-
91-
// Otherwise, look for debug_values.
92-
for (auto *use : getDebugUses(value))
93-
if (auto *dvi = dyn_cast<DebugValueInst>(use->getUser()))
94-
if (auto *decl = dvi->getDecl())
95-
if (!funcPassedInferedArgs(
96-
Argument({keyKind, "InferredValue"}, msg, decl)))
97-
return false;
98-
99-
// If we have a load, look through it and continue. We may have a global or
100-
// a function argument.
101-
if (auto *li = dyn_cast<LoadInst>(value)) {
102-
value = stripAccessMarkers(li->getOperand());
103-
continue;
104-
}
105-
106-
if (auto *ga = dyn_cast<GlobalAddrInst>(value))
107-
if (auto *decl = ga->getReferencedGlobal()->getDecl())
108-
if (!funcPassedInferedArgs(
109-
Argument({keyKind, "InferredValue"}, msg, decl)))
110-
return false;
111-
112-
return true;
113-
}
114-
}
115-
11680
template <typename DerivedT>
11781
std::string Remark<DerivedT>::getMsg() const {
11882
std::string str;

lib/SILOptimizer/Transforms/OptRemarkGenerator.cpp

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#define DEBUG_TYPE "sil-opt-remark-gen"
1414

15+
#include "swift/SIL/MemAccessUtils.h"
1516
#include "swift/SIL/OptimizationRemark.h"
1617
#include "swift/SIL/SILFunction.h"
1718
#include "swift/SIL/SILInstruction.h"
@@ -23,6 +24,82 @@
2324

2425
using namespace swift;
2526

27+
//===----------------------------------------------------------------------===//
28+
// Utility
29+
//===----------------------------------------------------------------------===//
30+
31+
namespace {
32+
33+
/// Given a value, call \p funcPassedInferredArgs for each associated
34+
/// ValueDecl that is associated with \p value. All created Arguments are
35+
/// passed the same StringRef. To stop iteration, return false in \p
36+
/// funcPassedInferedArgs.
37+
///
38+
/// NOTE: the function may be called multiple times if the optimizer joined
39+
/// two live ranges and thus when iterating over value's users we see multiple
40+
/// debug_value operations.
41+
struct ValueToDeclInferrer {
42+
using Argument = OptRemark::Argument;
43+
using ArgumentKeyKind = OptRemark::ArgumentKeyKind;
44+
45+
bool infer(ArgumentKeyKind keyKind, StringRef msg, SILValue value,
46+
function_ref<bool(Argument)> funcPassedInferedArgs);
47+
};
48+
49+
} // anonymous namespace
50+
51+
bool ValueToDeclInferrer::infer(
52+
ArgumentKeyKind keyKind, StringRef msg, SILValue value,
53+
function_ref<bool(Argument)> funcPassedInferedArgs) {
54+
55+
// This is a linear IR traversal using a 'falling while loop'. That means
56+
// every time through the loop we are trying to handle a case before we hit
57+
// the bottom of the while loop where we always return true (since we did not
58+
// hit a could not compute case). Reassign value and continue to go to the
59+
// next step.
60+
while (true) {
61+
// First check for "identified values" like arguments and global_addr.
62+
if (auto *arg = dyn_cast<SILArgument>(value))
63+
if (auto *decl = arg->getDecl())
64+
return funcPassedInferedArgs(
65+
Argument({keyKind, "InferredValue"}, msg, decl));
66+
67+
if (auto *ga = dyn_cast<GlobalAddrInst>(value))
68+
if (auto *decl = ga->getReferencedGlobal()->getDecl())
69+
if (!funcPassedInferedArgs(
70+
Argument({keyKind, "InferredValue"}, msg, decl)))
71+
return false;
72+
73+
// Then visit our users and see if we can find a debug_value that provides
74+
// us with a decl we can use to construct an argument.
75+
for (auto *use : value->getUses()) {
76+
// Skip type dependent uses.
77+
if (use->isTypeDependent())
78+
continue;
79+
80+
if (auto *dvi = dyn_cast<DebugValueInst>(use->getUser())) {
81+
if (auto *decl = dvi->getDecl())
82+
if (!funcPassedInferedArgs(
83+
Argument({keyKind, "InferredValue"}, msg, decl)))
84+
return false;
85+
}
86+
}
87+
88+
// At this point, we could not infer any argument. See if we can look
89+
// through loads, geps to construct a ProjectionPath.
90+
91+
// Finally, see if we can look through a load...
92+
if (auto *li = dyn_cast<LoadInst>(value)) {
93+
value = stripAccessMarkers(li->getOperand());
94+
continue;
95+
}
96+
97+
// If we reached this point, we finished falling through the loop and return
98+
// true.
99+
return true;
100+
}
101+
}
102+
26103
//===----------------------------------------------------------------------===//
27104
// Opt Remark Generator Visitor
28105
//===----------------------------------------------------------------------===//
@@ -35,6 +112,10 @@ struct OptRemarkGeneratorInstructionVisitor
35112
RCIdentityFunctionInfo &rcfi;
36113
OptRemark::Emitter ORE;
37114

115+
/// A class that we use to infer the decl that is associated with a
116+
/// miscellaneous SIL value. This is just a heuristic that is to taste.
117+
ValueToDeclInferrer valueToDeclInferrer;
118+
38119
OptRemarkGeneratorInstructionVisitor(SILFunction &fn,
39120
RCIdentityFunctionInfo &rcfi)
40121
: mod(fn.getModule()), rcfi(rcfi), ORE(DEBUG_TYPE, fn) {}
@@ -54,7 +135,7 @@ void OptRemarkGeneratorInstructionVisitor::visitStrongRetainInst(
54135
using namespace OptRemark;
55136
SILValue root = rcfi.getRCIdentityRoot(sri->getOperand());
56137
SmallVector<Argument, 8> inferredArgs;
57-
bool foundArgs = Argument::inferArgumentsForValue(
138+
bool foundArgs = valueToDeclInferrer.infer(
58139
ArgumentKeyKind::Note, "on value:", root, [&](Argument arg) {
59140
inferredArgs.push_back(arg);
60141
return true;
@@ -84,7 +165,7 @@ void OptRemarkGeneratorInstructionVisitor::visitStrongReleaseInst(
84165
// Releases end a lifetime scope so we infer scan backward.
85166
SILValue root = rcfi.getRCIdentityRoot(sri->getOperand());
86167
SmallVector<Argument, 8> inferredArgs;
87-
bool foundArgs = Argument::inferArgumentsForValue(
168+
bool foundArgs = valueToDeclInferrer.infer(
88169
ArgumentKeyKind::Note, "on value:", root, [&](Argument arg) {
89170
inferredArgs.push_back(arg);
90171
return true;
@@ -111,7 +192,7 @@ void OptRemarkGeneratorInstructionVisitor::visitRetainValueInst(
111192
using namespace OptRemark;
112193
SILValue root = rcfi.getRCIdentityRoot(rvi->getOperand());
113194
SmallVector<Argument, 8> inferredArgs;
114-
bool foundArgs = Argument::inferArgumentsForValue(
195+
bool foundArgs = valueToDeclInferrer.infer(
115196
ArgumentKeyKind::Note, "on value:", root, [&](Argument arg) {
116197
inferredArgs.push_back(arg);
117198
return true;
@@ -140,7 +221,7 @@ void OptRemarkGeneratorInstructionVisitor::visitReleaseValueInst(
140221
using namespace OptRemark;
141222
SILValue root = rcfi.getRCIdentityRoot(rvi->getOperand());
142223
SmallVector<Argument, 8> inferredArgs;
143-
bool foundArgs = Argument::inferArgumentsForValue(
224+
bool foundArgs = valueToDeclInferrer.infer(
144225
ArgumentKeyKind::Note, "on value:", root, [&](Argument arg) {
145226
inferredArgs.push_back(arg);
146227
return true;

0 commit comments

Comments
 (0)