Skip to content

Commit bf58b03

Browse files
authored
Merge pull request #73387 from Snowy1803/allocbox-fix
[DebugInfo] Fix loss of variables at -Onone
2 parents 73ed03c + c02f663 commit bf58b03

File tree

7 files changed

+99
-27
lines changed

7 files changed

+99
-27
lines changed

docs/DebuggingTheCompiler.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ If one builds swift using ninja and wants to dump the SIL of the
260260
stdlib using some of the SIL dumping options from the previous
261261
section, one can use the following one-liner:
262262

263-
ninja -t commands | grep swiftc | grep Swift.o | grep " -c "
263+
ninja -t commands | grep swiftc | grep 'Swift\.o'
264264

265265
This should give one a single command line that one can use for
266266
Swift.o, perfect for applying the previous sections options to.

docs/HowToUpdateDebugInfo.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ merge drop and copy locations, since all the same considerations apply. Helpers
1616
like `SILBuilderWithScope` make it easy to copy source locations when expanding
1717
SIL instructions.
1818

19+
> [!Warning]
20+
> Don't use `SILBuilderWithScope` when replacing a single instruction of type
21+
> `AllocStackInst` or `DebugValueInst`. These meta instructions are skipped,
22+
> so the wrong scope will be inferred.
23+
1924
## Variables
2025

2126
Each `debug_value` (and variable-carrying instruction) defines an update point
@@ -254,16 +259,34 @@ debug_value %1 : $Int, var, name "pair", type $Pair, expr op_fragment:#Pair.a //
254259
```
255260

256261
## Rules of thumb
257-
- Optimization passes may never drop a variable entirely. If a variable is
258-
entirely optimized away, an `undef` debug value should still be kept. The only
259-
exception is an unreachable function or scope, which is entirely removed.
260-
- A `debug_value` must always describe a correct value for that source variable
261-
at that source location. If a value is only correct on some paths through that
262-
instruction, it must be replaced with `undef`. Debug info never speculates.
263-
- When a SIL instruction is deleted, call salvageDebugInfo(). It will try to
264-
capture the effect of the deleted instruction in a debug expression, so the
265-
location can be preserved. You can also use an `InstructionDeleter` which will
266-
automatically call `salvageDebugInfo`.
262+
263+
### Correctness
264+
A `debug_value` must always describe a correct value for that source variable
265+
at that source location. If a value is only correct on some paths through that
266+
instruction, it must be replaced with `undef`. Debug info never speculates.
267+
268+
### Don't drop debug info
269+
270+
Optimization passes may never drop a variable entirely. If a variable is
271+
entirely optimized away, an `undef` debug value should still be kept. The only
272+
exception is when the variable is in an unreachable function or scope, where it
273+
can be removed with the rest of the instructions.
274+
275+
### Instruction Deletion
276+
277+
When a SIL instruction is deleted, call `salvageDebugInfo`. It will try to
278+
capture the effect of the deleted instruction in a debug expression, so the
279+
location can be preserved.
280+
281+
Alternatively, you can use an `InstructionDeleter`, which will automatically
282+
call `salvageDebugInfo`.
283+
284+
If the debug info cannot be salvaged by `salvageDebugInfo`, and the pass has a
285+
special knowledge of the value, the pass can directly replace the debug value
286+
with the known value.
287+
288+
If an instruction is being replaced by another, use `replaceAllUsesWith`. It
289+
will also update debug values to use the new instruction.
267290

268291
> [!Tip]
269292
> To detect when a pass drops a variable, you can use the

lib/IRGen/AllocStackHoisting.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,8 @@ void moveAllocStackToBeginningOfBlock(
157157
// of the debug_value to the original position.
158158
if (haveMovedElt) {
159159
if (auto varInfo = AS->getVarInfo()) {
160-
SILBuilderWithScope Builder(AS);
161160
// SILBuilderWithScope skips over meta instructions when picking a scope.
162-
Builder.setCurrentDebugScope(AS->getDebugScope());
161+
SILBuilder Builder(AS, AS->getDebugScope());
163162
auto *DVI = Builder.createDebugValue(AS->getLoc(), AS, *varInfo);
164163
DVI->setUsesMoveableValueDebugInfo();
165164
DebugValueToBreakBlocksAt.push_back(DVI);
@@ -198,14 +197,14 @@ void Partition::assignStackLocation(
198197
if (AssignedLoc == AllocStack) continue;
199198
eraseDeallocStacks(AllocStack);
200199
AllocStack->replaceAllUsesWith(AssignedLoc);
201-
if (hasAtLeastOneMovedElt) {
202-
if (auto VarInfo = AllocStack->getVarInfo()) {
203-
SILBuilderWithScope Builder(AllocStack);
204-
auto *DVI = Builder.createDebugValue(AllocStack->getLoc(), AssignedLoc,
205-
*VarInfo);
200+
if (auto VarInfo = AllocStack->getVarInfo()) {
201+
SILBuilder Builder(AllocStack, AllocStack->getDebugScope());
202+
auto *DVI = Builder.createDebugValueAddr(AllocStack->getLoc(),
203+
AssignedLoc, *VarInfo);
204+
if (hasAtLeastOneMovedElt) {
206205
DVI->setUsesMoveableValueDebugInfo();
207-
DebugValueToBreakBlocksAt.push_back(DVI);
208206
}
207+
DebugValueToBreakBlocksAt.push_back(DVI);
209208
}
210209
AllocStack->eraseFromParent();
211210
}

lib/IRGen/LoadableByAddress.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
3434
#include "swift/SILOptimizer/PassManager/Transforms.h"
3535
#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
36+
#include "swift/SILOptimizer/Utils/DebugOptUtils.h"
3637
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
3738
#include "swift/SILOptimizer/Utils/StackNesting.h"
3839
#include "llvm/ADT/MapVector.h"
@@ -1778,7 +1779,7 @@ static void rewriteUsesOfSscalar(StructLoweringState &pass,
17781779
createOutlinedCopyCall(copyBuilder, address, dest, pass);
17791780
storeUser->eraseFromParent();
17801781
} else if (auto *dbgInst = dyn_cast<DebugValueInst>(user)) {
1781-
SILBuilderWithScope dbgBuilder(dbgInst);
1782+
SILBuilder dbgBuilder(dbgInst, dbgInst->getDebugScope());
17821783
// Rewrite the debug_value to point to the variable in the alloca.
17831784
dbgBuilder.createDebugValueAddr(dbgInst->getLoc(), address,
17841785
*dbgInst->getVarInfo());
@@ -2151,9 +2152,8 @@ static void rewriteFunction(StructLoweringState &pass,
21512152
} else {
21522153
assert(currOperand->getType().isAddress() &&
21532154
"Expected an address type");
2154-
SILBuilderWithScope debugBuilder(instr);
21552155
// SILBuilderWithScope skips over metainstructions.
2156-
debugBuilder.setCurrentDebugScope(instr->getDebugScope());
2156+
SILBuilder debugBuilder(instr, instr->getDebugScope());
21572157
debugBuilder.createDebugValueAddr(instr->getLoc(), currOperand,
21582158
*instr->getVarInfo());
21592159
instr->getParent()->erase(instr);
@@ -3655,6 +3655,7 @@ class AssignAddressToDef : SILInstructionVisitor<AssignAddressToDef> {
36553655

36563656
builder.createCopyAddr(load->getLoc(), load->getOperand(), addr, IsTake,
36573657
IsInitialization);
3658+
swift::salvageLoadDebugInfo(load);
36583659
assignment.markForDeletion(load);
36593660
}
36603661

lib/SIL/IR/SILInstruction.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,9 +1478,8 @@ bool SILInstruction::mayTrap() const {
14781478
}
14791479

14801480
bool SILInstruction::isMetaInstruction() const {
1481-
// Every instruction that implements getVarInfo() should be in this list.
1481+
// Every instruction that doesn't generate code should be in this list.
14821482
switch (getKind()) {
1483-
case SILInstructionKind::AllocBoxInst:
14841483
case SILInstructionKind::AllocStackInst:
14851484
case SILInstructionKind::DebugValueInst:
14861485
return true;

test/DebugInfo/LoadableByAddress.sil

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: %target-sil-opt -loadable-address %s | %FileCheck %s
2+
3+
sil_stage canonical
4+
5+
import Builtin
6+
import Swift
7+
8+
struct X {
9+
var x1 : Int
10+
var x2 : Int
11+
var x3 : Int
12+
var x4: Int
13+
var x5: Int
14+
var x6: Int
15+
var x7: Int
16+
var x8: Int
17+
var x9: Int
18+
var x10: Int
19+
var x11: Int
20+
var x12: Int
21+
var x13: Int
22+
var x14: Int
23+
var x15: Int
24+
var x16: Int
25+
}
26+
27+
28+
// CHECK: sil @test1 : $@convention(thin) () -> () {
29+
// CHECK: bb0:
30+
// CHECK: %0 = alloc_stack $Optional<X>
31+
// CHECK: %1 = alloc_stack $X
32+
// CHECK: %2 = alloc_stack $X
33+
// CHECK: %3 = alloc_stack $Optional<X>
34+
// CHECK: debug_value %{{[0-9]+}} : $*X, let, name "temp"
35+
// CHECK: } // end sil function 'test1'
36+
37+
sil @test1 : $@convention(thin) () -> () {
38+
bb0:
39+
%0 = alloc_stack $X
40+
%1 = alloc_stack $Optional<X>
41+
%2 = load %0 : $*X
42+
debug_value %2 : $X, let, name "temp"
43+
%3 = enum $Optional<X>, #Optional.some!enumelt, %2 : $X
44+
store %3 to %1 : $*Optional<X>
45+
dealloc_stack %1 : $*Optional<X>
46+
dealloc_stack %0 : $*X
47+
%t = tuple ()
48+
return %t : $()
49+
}

test/SILOptimizer/allocstack_hoisting_debuginfo.sil

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,14 @@ bb4:
9898
return %9999 : $()
9999
}
100100

101-
// This case we are not moving anything so we are leaving in the default
102-
// behavior which is not breaking blocks and not inserting debug_info.
101+
// This case we are not moving anything, so we don't add the
102+
// [moveable_value_debuginfo] flag, but we still want debug info for the
103+
// second alloc_stack!
103104
//
104105
// CHECK-LABEL: sil @hoist_generic_3 :
105106
// CHECK: bb0([[ARG:%.*]] : $*T,
106107
// CHECK-NEXT: [[STACK:%.*]] = alloc_stack $T{{[ ]*}}, let, name "x"
107-
// CHECK-NOT: debug_value
108+
// CHECK: debug_value %{{.+}}, let, name "y"
108109
// CHECK: } // end sil function 'hoist_generic_3'
109110
sil @hoist_generic_3 : $@convention(thin) <T> (@in T, Builtin.Int1) -> () {
110111
bb0(%0 : $*T, %1: $Builtin.Int1):

0 commit comments

Comments
 (0)