Skip to content

Commit c54fb33

Browse files
committed
[opt-remark] Infer the source loc retain, release even if they have non-inlined locs.
The reason why is that due to ARCCodeMotion, they could have moved enough that the SourceLoc on them is incorrect. That is why you can see in the tests that I had to update, I am moving the retain to the return statement from the body of the function since the retain was now right before the return. I also went in and cleaned up the logic here a little bit. What we do now is that we have a notion of instructions that we /always/ infer SourceLocs for (rr) and ones that if we have a valid non-inlined location we use (e.x.: allocations). This mucked a little bit with my ability to run SIL tests since the SIL tests were relying on this not happening to rr so that we would emit remarks on the rr instructions themselves. I added an option that disables the always infer behavior for this test. That being said at this point to me it seems like the SourceLoc inference stuff is really tied to OptRemarkGenerator and I am going to see if I can move it to there. But that is for a future commit on another day.
1 parent a7e8dbf commit c54fb33

File tree

5 files changed

+71
-67
lines changed

5 files changed

+71
-67
lines changed

include/swift/SIL/OptimizationRemark.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,26 @@ struct IndentDebug {
137137
unsigned width;
138138
};
139139

140-
enum class SourceLocInferenceBehavior {
141-
None,
142-
ForwardScanOnly,
143-
BackwardScanOnly,
144-
ForwardThenBackward,
145-
BackwardThenForward,
140+
enum class SourceLocInferenceBehavior : unsigned {
141+
None = 0,
142+
ForwardScan = 0x1,
143+
BackwardScan = 0x2,
144+
ForwardScan2nd = 0x4,
145+
AlwaysInfer = 0x8,
146+
147+
ForwardThenBackwards = ForwardScan | BackwardScan,
148+
BackwardsThenForwards = BackwardScan | ForwardScan2nd,
149+
ForwardScanAlwaysInfer = ForwardScan | AlwaysInfer,
150+
BackwardScanAlwaysInfer = BackwardScan | AlwaysInfer,
146151
};
147152

153+
inline SourceLocInferenceBehavior operator&(SourceLocInferenceBehavior lhs,
154+
SourceLocInferenceBehavior rhs) {
155+
auto lhsVal = std::underlying_type<SourceLocInferenceBehavior>::type(lhs);
156+
auto rhsVal = std::underlying_type<SourceLocInferenceBehavior>::type(rhs);
157+
return SourceLocInferenceBehavior(lhsVal & rhsVal);
158+
}
159+
148160
/// Infer the proper SourceLoc to use for the given SILInstruction.
149161
///
150162
/// This means that if we have a valid location for the instruction, we just

lib/SIL/Utils/OptimizationRemark.cpp

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -182,59 +182,48 @@ static SourceLoc inferOptRemarkSearchBackwards(SILInstruction &i) {
182182
return SourceLoc();
183183
}
184184

185+
static llvm::cl::opt<bool> IgnoreAlwaysInferForTesting(
186+
"sil-opt-remark-ignore-always-infer", llvm::cl::Hidden,
187+
llvm::cl::init(false),
188+
llvm::cl::desc(
189+
"Disables always infer source loc behavior for testing purposes"));
190+
191+
// Attempt to infer a SourceLoc for \p i using heuristics specified by \p
192+
// inferBehavior.
193+
//
194+
// NOTE: We distinguish in between situations where we always must infer
195+
// (retain, release) and other situations where we are ok with original source
196+
// locs if we are not inlined (alloc_ref, alloc_stack).
185197
SourceLoc swift::OptRemark::inferOptRemarkSourceLoc(
186198
SILInstruction &i, SourceLocInferenceBehavior inferBehavior) {
187-
// Do a quick check if we already have a valid loc and it isnt an inline
188-
// loc. In such a case, just return. Otherwise, we try to infer using one of
189-
// our heuristics below.
199+
// If we are only supposed to infer in inline contexts, see if we have a valid
200+
// loc and if that loc is an inlined call site.
190201
auto loc = i.getLoc();
191-
if (loc.getSourceLoc().isValid()) {
192-
// Before we do anything, if we do not have an inlined call site, just
193-
// return our loc.
194-
if (!i.getDebugScope() || !i.getDebugScope()->InlinedCallSite)
195-
return loc.getSourceLoc();
196-
}
202+
if (loc.getSourceLoc().isValid() &&
203+
!(bool(inferBehavior & SourceLocInferenceBehavior::AlwaysInfer) &&
204+
!IgnoreAlwaysInferForTesting) &&
205+
!(i.getDebugScope() && i.getDebugScope()->InlinedCallSite))
206+
return loc.getSourceLoc();
197207

198-
// Otherwise, try to handle the individual behavior cases, returning loc at
199-
// the end of each case (its invalid, so it will get ignored). If loc is not
200-
// returned, we hit an assert at the end to make it easy to identify a case
201-
// was missed.
202-
switch (inferBehavior) {
203-
case SourceLocInferenceBehavior::None:
204-
return SourceLoc();
205-
case SourceLocInferenceBehavior::ForwardScanOnly: {
208+
if (bool(inferBehavior & SourceLocInferenceBehavior::ForwardScan)) {
206209
SourceLoc newLoc = inferOptRemarkSearchForwards(i);
207210
if (newLoc.isValid())
208211
return newLoc;
209-
return SourceLoc();
210212
}
211-
case SourceLocInferenceBehavior::BackwardScanOnly: {
213+
214+
if (bool(inferBehavior & SourceLocInferenceBehavior::BackwardScan)) {
212215
SourceLoc newLoc = inferOptRemarkSearchBackwards(i);
213216
if (newLoc.isValid())
214217
return newLoc;
215-
return SourceLoc();
216218
}
217-
case SourceLocInferenceBehavior::ForwardThenBackward: {
219+
220+
if (bool(inferBehavior & SourceLocInferenceBehavior::ForwardScan2nd)) {
218221
SourceLoc newLoc = inferOptRemarkSearchForwards(i);
219222
if (newLoc.isValid())
220223
return newLoc;
221-
newLoc = inferOptRemarkSearchBackwards(i);
222-
if (newLoc.isValid())
223-
return newLoc;
224-
return SourceLoc();
225-
}
226-
case SourceLocInferenceBehavior::BackwardThenForward: {
227-
SourceLoc newLoc = inferOptRemarkSearchBackwards(i);
228-
if (newLoc.isValid())
229-
return newLoc;
230-
newLoc = inferOptRemarkSearchForwards(i);
231-
if (newLoc.isValid())
232-
return newLoc;
233-
return SourceLoc();
234-
}
235224
}
236225

237-
llvm_unreachable("Covered switch isn't covered?!");
226+
return SourceLoc();
238227
}
239228

240229
template <typename RemarkT, typename... ArgTypes>

lib/SILOptimizer/Transforms/OptRemarkGenerator.cpp

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,11 @@ void OptRemarkGeneratorInstructionVisitor::visitStrongRetainInst(
425425
(void)foundArgs;
426426

427427
// Retains begin a lifetime scope so we infer scan forward.
428-
auto remark = RemarkMissed("memory", *sri,
429-
SourceLocInferenceBehavior::ForwardScanOnly)
430-
<< "retain of type '"
431-
<< NV("ValueType", sri->getOperand()->getType()) << "'";
428+
auto remark =
429+
RemarkMissed("memory", *sri,
430+
SourceLocInferenceBehavior::ForwardScanAlwaysInfer)
431+
<< "retain of type '" << NV("ValueType", sri->getOperand()->getType())
432+
<< "'";
432433
for (auto arg : inferredArgs) {
433434
remark << arg;
434435
}
@@ -446,10 +447,11 @@ void OptRemarkGeneratorInstructionVisitor::visitStrongReleaseInst(
446447
sri->getOperand(), inferredArgs);
447448
(void)foundArgs;
448449

449-
auto remark = RemarkMissed("memory", *sri,
450-
SourceLocInferenceBehavior::BackwardScanOnly)
451-
<< "release of type '"
452-
<< NV("ValueType", sri->getOperand()->getType()) << "'";
450+
auto remark =
451+
RemarkMissed("memory", *sri,
452+
SourceLocInferenceBehavior::BackwardScanAlwaysInfer)
453+
<< "release of type '" << NV("ValueType", sri->getOperand()->getType())
454+
<< "'";
453455
for (auto arg : inferredArgs) {
454456
remark << arg;
455457
}
@@ -466,10 +468,11 @@ void OptRemarkGeneratorInstructionVisitor::visitRetainValueInst(
466468
rvi->getOperand(), inferredArgs);
467469
(void)foundArgs;
468470
// Retains begin a lifetime scope, so we infer scan forwards.
469-
auto remark = RemarkMissed("memory", *rvi,
470-
SourceLocInferenceBehavior::ForwardScanOnly)
471-
<< "retain of type '"
472-
<< NV("ValueType", rvi->getOperand()->getType()) << "'";
471+
auto remark =
472+
RemarkMissed("memory", *rvi,
473+
SourceLocInferenceBehavior::ForwardScanAlwaysInfer)
474+
<< "retain of type '" << NV("ValueType", rvi->getOperand()->getType())
475+
<< "'";
473476
for (auto arg : inferredArgs) {
474477
remark << arg;
475478
}
@@ -487,10 +490,11 @@ void OptRemarkGeneratorInstructionVisitor::visitReleaseValueInst(
487490
(void)foundArgs;
488491

489492
// Releases end a lifetime scope so we infer scan backward.
490-
auto remark = RemarkMissed("memory", *rvi,
491-
SourceLocInferenceBehavior::BackwardScanOnly)
492-
<< "release of type '"
493-
<< NV("ValueType", rvi->getOperand()->getType()) << "'";
493+
auto remark =
494+
RemarkMissed("memory", *rvi,
495+
SourceLocInferenceBehavior::BackwardScanAlwaysInfer)
496+
<< "release of type '" << NV("ValueType", rvi->getOperand()->getType())
497+
<< "'";
494498
for (auto arg : inferredArgs) {
495499
remark << arg;
496500
}
@@ -508,8 +512,7 @@ void OptRemarkGeneratorInstructionVisitor::visitAllocRefInst(
508512
valueToDeclInferrer.infer(ArgumentKeyKind::Note, ari, inferredArgs);
509513
(void)foundArgs;
510514
auto resultRemark =
511-
RemarkPassed("memory", *ari,
512-
SourceLocInferenceBehavior::ForwardScanOnly)
515+
RemarkPassed("memory", *ari, SourceLocInferenceBehavior::ForwardScan)
513516
<< "stack allocated ref of type '" << NV("ValueType", ari->getType())
514517
<< "'";
515518
for (auto &arg : inferredArgs)
@@ -526,8 +529,7 @@ void OptRemarkGeneratorInstructionVisitor::visitAllocRefInst(
526529
(void)foundArgs;
527530

528531
auto resultRemark =
529-
RemarkMissed("memory", *ari,
530-
SourceLocInferenceBehavior::ForwardScanOnly)
532+
RemarkMissed("memory", *ari, SourceLocInferenceBehavior::ForwardScan)
531533
<< "heap allocated ref of type '" << NV("ValueType", ari->getType())
532534
<< "'";
533535
for (auto &arg : inferredArgs)
@@ -546,8 +548,7 @@ void OptRemarkGeneratorInstructionVisitor::visitAllocBoxInst(
546548
(void)foundArgs;
547549

548550
auto resultRemark =
549-
RemarkMissed("memory", *abi,
550-
SourceLocInferenceBehavior::ForwardScanOnly)
551+
RemarkMissed("memory", *abi, SourceLocInferenceBehavior::ForwardScan)
551552
<< "heap allocated box of type '" << NV("ValueType", abi->getType())
552553
<< "'";
553554
for (auto &arg : inferredArgs)

test/SILOptimizer/opt-remark-generator.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -optremarkgen-declless-debugvalue-use-sildebugvar-info -sil-opt-remark-generator -sil-remarks-missed=sil-opt-remark-gen -verify %s -o /dev/null
1+
// RUN: %target-sil-opt -sil-opt-remark-ignore-always-infer -optremarkgen-declless-debugvalue-use-sildebugvar-info -sil-opt-remark-generator -sil-remarks-missed=sil-opt-remark-gen -verify %s -o /dev/null
22

33
sil_stage canonical
44

test/SILOptimizer/opt-remark-generator.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ func printKlassPairLHS(x : KlassPair) {
9090
// expected-remark @-3:16 {{release of type}}
9191
}
9292

93+
// We put the retain on the return here since it is part of the result
94+
// convention.
9395
func returnKlassPairLHS(x: KlassPair) -> Klass {
94-
return x.lhs // expected-remark @:14 {{retain of type 'Klass'}}
96+
return x.lhs // expected-remark @:5 {{retain of type 'Klass'}}
9597
// expected-note @-2:25 {{of 'x.lhs'}}
9698
}
9799

@@ -123,7 +125,7 @@ func printKlassTupleLHS(x : (Klass, Klass)) {
123125
}
124126

125127
func returnKlassTupleLHS(x: (Klass, Klass)) -> Klass {
126-
return x.0 // expected-remark @:12 {{retain of type 'Klass'}}
128+
return x.0 // expected-remark @:5 {{retain of type 'Klass'}}
127129
// expected-note @-2:26 {{of 'x'}}
128130
}
129131

0 commit comments

Comments
 (0)