Files
swift-mirror/test/DebugInfo/sil_combine.sil
Aidan Hall a95d2979f9 [DebugInfo] Salvage more in -O builds
Specifically, improved debug info retention in:
* tryReplaceRedundantInstructionPair,
* splitAggregateLoad,
* TempLValueElimination,
* Mem2Reg,
* ConstantFolding.

The changes to Mem2Reg allow debug info to be retained in the case tested by
self-nostorage.swift in -O builds, so we have just enabled -O in that file
instead of writing a new test for it.

We attempted to add a case to salvageDebugInfo for unchecked_enum_data, but it
caused crashes in Linux CI that we were not able to reproduce.
2025-11-28 17:42:18 +00:00

97 lines
3.3 KiB
Plaintext

// RUN: %target-sil-opt -sil-print-types -sil-verify-all -sil-combine %s | %FileCheck %s
// RUN: %target-swift-frontend -g -O -emit-ir -primary-file %s | %FileCheck --check-prefix=CHECK-IR %s
sil_stage canonical
import Builtin
import Swift
// CHECK-LABEL: sil {{.*}} @test_nested_index_addr
// CHECK-IR-LABEL: define {{.*}} @test_nested_index_addr
sil hidden @test_nested_index_addr : $@convention(thin) (Builtin.RawPointer) -> Builtin.RawPointer {
bb0(%0 : $Builtin.RawPointer):
%offset1 = integer_literal $Builtin.Word, 3
%offset2 = integer_literal $Builtin.Word, 7
// CHECK: %[[ADDR:.+]] = pointer_to_address %0
%addr = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*UInt8
%addr1 = index_addr %addr : $*UInt8, %offset1 : $Builtin.Word
// CHECK: debug_value %[[ADDR]] : $*UInt8, let, name "hello"
// CHECK-SAME: expr op_constu:3:op_plus:op_deref
// CHECK-IR: #dbg_value(ptr %0, ![[DBG_VAR:[0-9]+]],
// CHECK-IR-SAME: !DIExpression(DW_OP_plus_uconst, 3, DW_OP_deref)
debug_value %addr1 : $*UInt8, let, name "hello", expr op_deref
%addr2 = index_addr %addr1 : $*UInt8, %offset2 : $Builtin.Word
%ptr = address_to_pointer %addr2 : $*UInt8 to $Builtin.RawPointer
return %ptr : $Builtin.RawPointer
}
public struct S {}
public struct C {
var x: MP
}
enum MP {
case A(S)
case B(S)
}
// CHECK-LABEL: sil @expand_alloc_stack_of_enum_without_take
// CHECK: [[A:%[0-9]+]] = alloc_stack $S
// CHECK-NOT: name "a"
// CHECK-NEXT: debug_value undef : $*MP, let, name "a", expr op_fragment:#C.x
// CHECK-NEXT: debug_value undef : $*MP, let, name "b"
// CHECK: bb1:
// CHECK-NEXT: store %0 to [[A]]
// CHECK: bb2:
// CHECK-NEXT: store %0 to [[A]]
// CHECK: bb3:
// CHECK: destroy_addr [[A]]
// CHECK: } // end sil function 'expand_alloc_stack_of_enum_without_take'
sil @expand_alloc_stack_of_enum_without_take : $@convention(method) (S) -> () {
bb0(%0 : $S):
%1 = alloc_stack $MP, let, name "a", expr op_fragment:#C.x
debug_value %1 : $*MP, let, name "b", expr op_deref
cond_br undef, bb1, bb2
bb1:
%2 = init_enum_data_addr %1 : $*MP, #MP.A!enumelt
store %0 to %2 : $*S
inject_enum_addr %1 : $*MP, #MP.A!enumelt
br bb3
bb2:
%3 = init_enum_data_addr %1 : $*MP, #MP.A!enumelt
store %0 to %3 : $*S
inject_enum_addr %1 : $*MP, #MP.A!enumelt
br bb3
bb3:
destroy_addr %1 : $*MP
dealloc_stack %1 : $*MP
%11 = tuple ()
return %11 : $()
}
// CHECK-IR: ![[DBG_VAR]] = !DILocalVariable(name: "hello"
struct T {
@_hasStorage let x: Builtin.Int32 { get }
init(x: Builtin.Int32)
}
// This test verifies that splitAggregateLoad in CanonicalizeInstruction.cpp
// salvages debug info attached to the loaded aggregate in optimized builds.
//
// CHECK-LABEL: sil @split_aggregate_load : $@convention(thin) (@in T) -> Builtin.Int32 {
// CHECK: bb0([[ARG:%[0-9]+]] : $*T):
// CHECK-NEXT: [[ELEM_ADDR:%[0-9]+]] = struct_element_addr [[ARG]] : $*T, #T.x
// CHECK-NEXT: [[ELEM:%[0-9]+]] = load [[ELEM_ADDR]]
// CHECK-NEXT: debug_value [[ARG]] : $*T, let, name "var", expr op_deref
// CHECK-NEXT: return [[ELEM]] : $Builtin.Int32
// CHECK-LABEL: } // end sil function 'split_aggregate_load'
sil @split_aggregate_load : $@convention(thin) (@in T) -> Builtin.Int32 {
bb0(%0 : $*T):
%1 = load %0
debug_value %1, let, name "var"
%2 = struct_extract %1, #T.x
return %2
}