12
12
13
13
#define DEBUG_TYPE " sil-opt-remark-gen"
14
14
15
+ #include " swift/SIL/MemAccessUtils.h"
15
16
#include " swift/SIL/OptimizationRemark.h"
16
17
#include " swift/SIL/SILFunction.h"
17
18
#include " swift/SIL/SILInstruction.h"
23
24
24
25
using namespace swift ;
25
26
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
+
26
103
// ===----------------------------------------------------------------------===//
27
104
// Opt Remark Generator Visitor
28
105
// ===----------------------------------------------------------------------===//
@@ -35,6 +112,10 @@ struct OptRemarkGeneratorInstructionVisitor
35
112
RCIdentityFunctionInfo &rcfi;
36
113
OptRemark::Emitter ORE;
37
114
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
+
38
119
OptRemarkGeneratorInstructionVisitor (SILFunction &fn,
39
120
RCIdentityFunctionInfo &rcfi)
40
121
: mod(fn.getModule()), rcfi(rcfi), ORE(DEBUG_TYPE, fn) {}
@@ -54,7 +135,7 @@ void OptRemarkGeneratorInstructionVisitor::visitStrongRetainInst(
54
135
using namespace OptRemark ;
55
136
SILValue root = rcfi.getRCIdentityRoot (sri->getOperand ());
56
137
SmallVector<Argument, 8 > inferredArgs;
57
- bool foundArgs = Argument::inferArgumentsForValue (
138
+ bool foundArgs = valueToDeclInferrer. infer (
58
139
ArgumentKeyKind::Note, " on value:" , root, [&](Argument arg) {
59
140
inferredArgs.push_back (arg);
60
141
return true ;
@@ -84,7 +165,7 @@ void OptRemarkGeneratorInstructionVisitor::visitStrongReleaseInst(
84
165
// Releases end a lifetime scope so we infer scan backward.
85
166
SILValue root = rcfi.getRCIdentityRoot (sri->getOperand ());
86
167
SmallVector<Argument, 8 > inferredArgs;
87
- bool foundArgs = Argument::inferArgumentsForValue (
168
+ bool foundArgs = valueToDeclInferrer. infer (
88
169
ArgumentKeyKind::Note, " on value:" , root, [&](Argument arg) {
89
170
inferredArgs.push_back (arg);
90
171
return true ;
@@ -111,7 +192,7 @@ void OptRemarkGeneratorInstructionVisitor::visitRetainValueInst(
111
192
using namespace OptRemark ;
112
193
SILValue root = rcfi.getRCIdentityRoot (rvi->getOperand ());
113
194
SmallVector<Argument, 8 > inferredArgs;
114
- bool foundArgs = Argument::inferArgumentsForValue (
195
+ bool foundArgs = valueToDeclInferrer. infer (
115
196
ArgumentKeyKind::Note, " on value:" , root, [&](Argument arg) {
116
197
inferredArgs.push_back (arg);
117
198
return true ;
@@ -140,7 +221,7 @@ void OptRemarkGeneratorInstructionVisitor::visitReleaseValueInst(
140
221
using namespace OptRemark ;
141
222
SILValue root = rcfi.getRCIdentityRoot (rvi->getOperand ());
142
223
SmallVector<Argument, 8 > inferredArgs;
143
- bool foundArgs = Argument::inferArgumentsForValue (
224
+ bool foundArgs = valueToDeclInferrer. infer (
144
225
ArgumentKeyKind::Note, " on value:" , root, [&](Argument arg) {
145
226
inferredArgs.push_back (arg);
146
227
return true ;
0 commit comments