Skip to content

Commit 1cb333a

Browse files
committed
[DebugInfo] Salvage more during SIL optimization passes
This reverts commit b1eb70b. The original PR (#85244) was reverted (#85836) due to rdar://165667449 This version fixes the aforementioned issue, and (potentially) improves overall debug info retention by salvaging info in erase(instructionIncludingDebugUses:), rather than inserting many explicit salvageDebugInfo calls throughout the code to make the test cases pass. Bridging: Make salvageDebugInfo a method of MutatingContext This feels more consistent than making it a method of Instruction. DebugInfo: Salvage from trivially dead instructions This handles the case we were checking in constantFoldBuiltin, so we do not need to salvage debug info there any more.
1 parent 0a8a3bc commit 1cb333a

File tree

11 files changed

+148
-6
lines changed

11 files changed

+148
-6
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/TempLValueElimination.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ private func tryEliminate(copy: CopyLikeInstruction, _ context: FunctionPassCont
180180
use.set(to: copy.destinationAddress, context)
181181
}
182182
}
183+
184+
// Salvage the debug variable attribute, if present.
185+
if let debugVariable = allocStack.debugVariable {
186+
let builder = Builder(before: firstUseOfAllocStack, location: allocStack.location, context)
187+
builder.createDebugValue(value: copy.destinationAddress, debugVariable: debugVariable)
188+
}
183189
context.erase(instruction: allocStack)
184190
context.erase(instructionIncludingAllUsers: copy.loadingInstruction)
185191
}

SwiftCompilerSources/Sources/SIL/Context.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,18 @@ extension MutatingContext {
210210

211211
public func erase(instructionIncludingDebugUses inst: Instruction) {
212212
precondition(inst.results.allSatisfy { $0.uses.ignoreDebugUses.isEmpty })
213+
salvageDebugInfo(of: inst)
213214
erase(instructionIncludingAllUsers: inst)
214215
}
215216

216217
public func erase(block: BasicBlock) {
217218
_bridged.eraseBlock(block.bridged)
218219
}
219220

221+
/// Transfer debug info associated with (the result of) this instruction to a
222+
/// new `debug_value` instruction before this instruction is deleted.
223+
public func salvageDebugInfo(of instruction: Instruction) {
224+
BridgedContext.salvageDebugInfo(instruction.bridged)
225+
notifyInstructionsChanged()
226+
}
220227
}

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,7 @@ struct BridgedContext {
15551555
BRIDGED_INLINE void eraseBlock(BridgedBasicBlock block) const;
15561556
static BRIDGED_INLINE void moveInstructionBefore(BridgedInstruction inst, BridgedInstruction beforeInst);
15571557
static BRIDGED_INLINE void copyInstructionBefore(BridgedInstruction inst, BridgedInstruction beforeInst);
1558+
static BRIDGED_INLINE void salvageDebugInfo(BridgedInstruction inst);
15581559

15591560
// SSAUpdater
15601561

include/swift/SIL/SILBridgingImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "swift/SIL/SILVTable.h"
4242
#include "swift/SIL/SILWitnessTable.h"
4343
#include "swift/SILOptimizer/Utils/ConstExpr.h"
44+
#include "swift/SILOptimizer/Utils/DebugOptUtils.h"
4445
#include "swift/SIL/SILConstants.h"
4546
#include <stdbool.h>
4647
#include <stddef.h>
@@ -3217,6 +3218,10 @@ void BridgedContext::copyInstructionBefore(BridgedInstruction inst, BridgedInstr
32173218
inst.unbridged()->clone(beforeInst.unbridged());
32183219
}
32193220

3221+
void BridgedContext::salvageDebugInfo(BridgedInstruction inst) {
3222+
swift::salvageDebugInfo(inst.unbridged());
3223+
}
3224+
32203225
OptionalBridgedFunction BridgedContext::lookupStdlibFunction(BridgedStringRef name) const {
32213226
return {context->lookupStdlibFunction(name.unbridged())};
32223227
}

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,11 +1968,16 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *asi) {
19681968
if (!runningVals) {
19691969
// Loading from uninitialized memory is only acceptable if the type is
19701970
// empty--an aggregate of types without storage.
1971+
const auto initialValue =
1972+
createEmptyAndUndefValue(asi->getElementType(), inst, ctx);
19711973
runningVals = {
19721974
LiveValues::toReplace(asi,
1973-
/*replacement=*/createEmptyAndUndefValue(
1974-
asi->getElementType(), inst, ctx)),
1975+
/*replacement=*/initialValue),
19751976
/*isStorageValid=*/!doesLoadInvalidateStorage(inst)};
1977+
if (auto varInfo = asi->getVarInfo()) {
1978+
SILBuilderWithScope(inst, ctx).createDebugValue(
1979+
inst->getLoc(), initialValue, *varInfo);
1980+
}
19761981
}
19771982
auto *loadInst = dyn_cast<LoadInst>(inst);
19781983
if (loadInst &&

lib/SILOptimizer/Utils/CanonicalizeInstruction.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,9 +321,8 @@ splitAggregateLoad(LoadOperation loadInst, CanonicalizeInstruction &pass) {
321321
}
322322

323323
// Preserve the original load's debug information.
324-
if (pass.preserveDebugInfo) {
325-
swift::salvageLoadDebugInfo(loadInst);
326-
}
324+
swift::salvageLoadDebugInfo(loadInst);
325+
327326
// Remove the now unused borrows.
328327
for (auto *borrow : borrows)
329328
nextII = killInstAndIncidentalUses(borrow, nextII, pass);

test/DebugInfo/self-nostorage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -o - | %FileCheck %s
1+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -g -O -o - | %FileCheck %s
22

33
public struct S {
44
func f() {

test/DebugInfo/sil_combine.sil

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,26 @@ bb3:
7171

7272

7373
// CHECK-IR: ![[DBG_VAR]] = !DILocalVariable(name: "hello"
74+
75+
struct T {
76+
@_hasStorage let x: Builtin.Int32 { get }
77+
init(x: Builtin.Int32)
78+
}
79+
80+
// This test verifies that splitAggregateLoad in CanonicalizeInstruction.cpp
81+
// salvages debug info attached to the loaded aggregate in optimized builds.
82+
//
83+
// CHECK-LABEL: sil @split_aggregate_load : $@convention(thin) (@in T) -> Builtin.Int32 {
84+
// CHECK: bb0([[ARG:%[0-9]+]] : $*T):
85+
// CHECK-NEXT: [[ELEM_ADDR:%[0-9]+]] = struct_element_addr [[ARG]] : $*T, #T.x
86+
// CHECK-NEXT: [[ELEM:%[0-9]+]] = load [[ELEM_ADDR]]
87+
// CHECK-NEXT: debug_value [[ARG]] : $*T, let, name "var", expr op_deref
88+
// CHECK-NEXT: return [[ELEM]] : $Builtin.Int32
89+
// CHECK-LABEL: } // end sil function 'split_aggregate_load'
90+
sil @split_aggregate_load : $@convention(thin) (@in T) -> Builtin.Int32 {
91+
bb0(%0 : $*T):
92+
%1 = load %0
93+
debug_value %1, let, name "var"
94+
%2 = struct_extract %1, #T.x
95+
return %2
96+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all %s -simplification -simplify-instruction=builtin -sil-print-debuginfo | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
5+
import Swift
6+
import Builtin
7+
8+
// This verifies that debug information attached to the arguments of builtin
9+
// instructions is preserved when those instructions are constant-folded.
10+
//
11+
// CHECK-LABEL: sil @preserve_bitwise_operands : $@convention(thin) () -> Builtin.Int32 {
12+
// CHECK: bb0:
13+
// CHECK-NEXT: debug_value undef : $Builtin.Int32, let, name "x", expr op_constu:1
14+
// CHECK-NEXT: debug_value undef : $Builtin.Int32, let, name "y", expr op_constu:2
15+
// CHECK-NEXT: [[THREE:%[0-9]+]] = integer_literal $Builtin.Int32, 3
16+
// CHECK-NEXT: return [[THREE]] : $Builtin.Int32
17+
// CHECK-LABEL: } // end sil function 'preserve_bitwise_operands'
18+
sil @preserve_bitwise_operands : $@convention(thin) () -> Builtin.Int32 {
19+
bb0:
20+
%0 = integer_literal $Builtin.Int32, 1
21+
debug_value %0, let, name "x"
22+
%1 = integer_literal $Builtin.Int32, 2
23+
debug_value %1, let, name "y"
24+
%2 = builtin "or_Int32"(%0, %1) : $Builtin.Int32
25+
return %2
26+
}
27+
28+
// CHECK-LABEL: sil @preserve_add_operands : $@convention(thin) () -> Builtin.Int32 {
29+
// CHECK: bb0:
30+
// CHECK-NEXT: debug_value undef : $Builtin.Int32, let, name "x", expr op_consts:4294967295
31+
// CHECK-NEXT: debug_value undef : $Builtin.Int32, let, name "y", expr op_constu:2
32+
// CHECK-NEXT: [[ONE:%[0-9]+]] = integer_literal $Builtin.Int32, 1
33+
// CHECK-NEXT: return [[ONE]] : $Builtin.Int32
34+
// CHECK-LABEL: } // end sil function 'preserve_add_operands'
35+
sil @preserve_add_operands : $@convention(thin) () -> Builtin.Int32 {
36+
bb0:
37+
%0 = integer_literal $Builtin.Int32, -1
38+
debug_value %0, let, name "x"
39+
%1 = integer_literal $Builtin.Int32, 2
40+
debug_value %1, let, name "y"
41+
%2 = builtin "add_Int32"(%0, %1) : $Builtin.Int32
42+
return %2
43+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-sil-opt -sil-print-types -enable-sil-verify-all %s -simplification -simplify-instruction=struct_extract -sil-print-debuginfo | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
5+
import Builtin
6+
import Swift
7+
8+
struct T {
9+
var x: Builtin.Int32
10+
}
11+
12+
// This verifies that tryReplaceRedundantInstructionPair in OptUtils.swift
13+
// salvages debug info attached to the first instruction of the pair,
14+
// in this case the struct.
15+
//
16+
// CHECK-LABEL: sil @redundant_pair : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 {
17+
// CHECK: bb0([[VAR:%[0-9]+]] : $Builtin.Int32):
18+
// CHECK-NEXT: debug_value [[VAR]] : $Builtin.Int32, let, name "var", type $T, expr op_fragment:#T.x
19+
// CHECK-NEXT: return [[VAR]]
20+
// CHECK-LABEL: } // end sil function 'redundant_pair'
21+
sil @redundant_pair : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 {
22+
bb0(%0 : $Builtin.Int32):
23+
%1 = struct $T(%0)
24+
debug_value %1, let, name "var"
25+
%2 = struct_extract %1, #T.x
26+
return %2
27+
}

0 commit comments

Comments
 (0)