diff options
Diffstat (limited to 'tests/codegen-llvm/debuginfo-dse.rs')
| -rw-r--r-- | tests/codegen-llvm/debuginfo-dse.rs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/tests/codegen-llvm/debuginfo-dse.rs b/tests/codegen-llvm/debuginfo-dse.rs new file mode 100644 index 00000000000..1fcb5fcfc54 --- /dev/null +++ b/tests/codegen-llvm/debuginfo-dse.rs @@ -0,0 +1,160 @@ +//@ compile-flags: -Copt-level=3 -g -Zverify-llvm-ir +//@ revisions: CODEGEN OPTIMIZED +//@[CODEGEN] compile-flags: -Cno-prepopulate-passes +// ignore-tidy-linelength + +#![crate_type = "lib"] + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Foo(i32, i64, i32); + +#[no_mangle] +fn r#ref(ref_foo: &Foo) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @ref + // CHECK-SAME: (ptr {{.*}} [[ARG_ref_foo:%.*]]) + // OPTIMIZED: #dbg_value(ptr [[ARG_ref_foo]], [[VAR_ref_foo:![0-9]+]], !DIExpression() + // CHECK: #dbg_value(ptr poison, [[VAR_invalid_ref_of_ref_foo:![0-9]+]], !DIExpression() + // CHECK: #dbg_value(ptr [[ARG_ref_foo]], [[VAR_ref_v0:![0-9]+]], !DIExpression() + // CHECK: #dbg_value(ptr [[ARG_ref_foo]], [[VAR_ref_v1:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 8, DW_OP_stack_value) + // CHECK: #dbg_value(ptr [[ARG_ref_foo]], [[VAR_ref_v2:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16, DW_OP_stack_value) + let invalid_ref_of_ref_foo = &ref_foo; + let ref_v0 = &ref_foo.0; + let ref_v1 = &ref_foo.1; + let ref_v2 = &ref_foo.2; + ref_foo.0 +} + +#[no_mangle] +pub fn dead_first(dead_first_foo: &Foo) -> &i32 { + // CHECK-LABEL: def {{.*}} ptr @dead_first + // CHECK-SAME: (ptr {{.*}} [[ARG_dead_first_foo:%.*]]) + // CODEGEN: #dbg_declare(ptr %dead_first_foo.dbg.spill, [[ARG_dead_first_foo:![0-9]+]], !DIExpression() + // OPTIMIZED: #dbg_value(ptr %dead_first_foo, [[ARG_dead_first_foo:![0-9]+]], !DIExpression() + // CHECK: #dbg_value(ptr %dead_first_foo, [[VAR_dead_first_v0:![0-9]+]], !DIExpression() + // CHECK: %dead_first_v0 = getelementptr{{.*}} i8, ptr %dead_first_foo, i64 16 + // CODEGEN: #dbg_declare(ptr %dead_first_v0.dbg.spill, [[VAR_dead_first_v0]], !DIExpression() + // OPTIMIZED: #dbg_value(ptr %dead_first_v0, [[VAR_dead_first_v0]], !DIExpression() + let mut dead_first_v0 = &dead_first_foo.0; + dead_first_v0 = &dead_first_foo.2; + dead_first_v0 +} + +#[no_mangle] +fn ptr(ptr_foo: Foo) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @ptr + // CHECK-SAME: (ptr {{.*}} [[ARG_ptr_foo:%.*]]) + // CHECK: #dbg_value(ptr [[ARG_ptr_foo]], [[ref_ptr_foo:![0-9]+]], !DIExpression() + // CHECK: #dbg_value(ptr [[ARG_ptr_foo]], [[VAR_ptr_v0:![0-9]+]], !DIExpression() + // CHECK: #dbg_value(ptr [[ARG_ptr_foo]], [[VAR_ptr_v1:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 8, DW_OP_stack_value) + // CHECK: #dbg_value(ptr [[ARG_ptr_foo]], [[VAR_ptr_v2:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16, DW_OP_stack_value) + let ref_ptr_foo = &ptr_foo; + let ptr_v0 = &ptr_foo.0; + let ptr_v1 = &ptr_foo.1; + let ptr_v2 = &ptr_foo.2; + ptr_foo.2 +} + +#[no_mangle] +fn no_ptr(val: i32) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @no_ptr + // CODEGEN: #dbg_value(ptr poison, [[VAR_val_ref:![0-9]+]], !DIExpression() + let val_ref = &val; + val +} + +#[no_mangle] +pub fn fragment(fragment_v1: Foo, mut fragment_v2: Foo) -> Foo { + // CHECK-LABEL: define void @fragment + // CHECK-SAME: (ptr {{.*}}, ptr {{.*}} [[ARG_fragment_v1:%.*]], ptr {{.*}} [[ARG_fragment_v2:%.*]]) + // CHECK: #dbg_declare(ptr [[ARG_fragment_v1]] + // CHECK-NEXT: #dbg_declare(ptr [[ARG_fragment_v2]] + // CHECK-NEXT: #dbg_value(ptr [[ARG_fragment_v2]], [[VAR_fragment_f:![0-9]+]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) + // CHECK-NEXT: #dbg_value(ptr [[ARG_fragment_v1]], [[VAR_fragment_f:![0-9]+]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) + let fragment_f = || { + fragment_v2 = fragment_v1; + }; + fragment_v2 = fragment_v1; + fragment_v2 +} + +#[no_mangle] +pub fn tuple(foo: (i32, &Foo)) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @tuple + // CHECK-SAME: (i32 {{.*}}, ptr {{.*}} [[ARG_tuple_foo_1:%.*]]) + // CHECK: #dbg_value(ptr [[ARG_tuple_foo_1]], [[VAR_tuple_dead:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16, DW_OP_stack_value) + let tuple_dead = &foo.1.2; + foo.1.0 +} + +pub struct ZST; + +#[no_mangle] +pub fn zst(zst: ZST, v: &i32) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @zst + // CHECK: #dbg_value(ptr poison, [[VAR_zst_ref:![0-9]+]], !DIExpression() + let zst_ref = &zst; + *v +} + +#[no_mangle] +fn index(slice: &[i32; 4], idx: usize) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @index + // CHECK: bb1: + // CHECK-NEXT: #dbg_value(ptr poison, [[VAR_index_from_var:![0-9]+]], !DIExpression() + // CODEGEN: bb3: + // CHECK-NEXT: #dbg_value(ptr %slice, [[VAR_const_index_from_start:![0-9]+]], !DIExpression() + // CHECK-NEXT: #dbg_value(ptr poison, [[VAR_const_index_from_end:![0-9]+]], !DIExpression() + let index_from_var = &slice[idx]; + let [ref const_index_from_start, .., ref const_index_from_end] = slice[..] else { + return 0; + }; + slice[0] +} + +unsafe extern "Rust" { + safe fn opaque_inner(_: *const core::ffi::c_void); +} + +#[inline(never)] +pub fn opaque_use<T>(p: &T) { + opaque_inner(&raw const p as *const _); +} + +#[no_mangle] +pub fn non_arg_ref(scalar: i32, foo: Foo, a: &i32) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @non_arg_ref + // CHECK: #dbg_value(ptr %non_arg_ref_scalar, [[VAR_non_arg_ref_scalar_ref:![0-9]+]], !DIExpression() + // CHECK-NEXT: #dbg_value(ptr %non_arg_ref_foo, [[VAR_non_arg_ref_foo_ref:![0-9]+]], !DIExpression() + // CHECK-NEXT: #dbg_value(ptr %non_arg_ref_foo, [[VAR_non_arg_ref_foo_ref_2:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16, DW_OP_stack_value) + let non_arg_ref_scalar = scalar; + let non_arg_ref_foo = foo; + opaque_use(&non_arg_ref_scalar); + opaque_use(&non_arg_ref_foo); + let non_arg_ref_scalar_ref = &non_arg_ref_scalar; + let non_arg_ref_foo_ref = &non_arg_ref_foo; + let non_arg_ref_foo_ref_2 = &non_arg_ref_foo.2; + *a +} + +// CHECK-DAG: [[VAR_invalid_ref_of_ref_foo]] = !DILocalVariable(name: "invalid_ref_of_ref_foo" +// OPTIMIZED-DAG: [[VAR_ref_foo]] = !DILocalVariable(name: "ref_foo" +// CHECK-DAG: [[VAR_ref_v0]] = !DILocalVariable(name: "ref_v0" +// CHECK-DAG: [[VAR_ref_v1]] = !DILocalVariable(name: "ref_v1" +// CHECK-DAG: [[VAR_ref_v2]] = !DILocalVariable(name: "ref_v2" +// CHECK-DAG: [[ref_ptr_foo]] = !DILocalVariable(name: "ref_ptr_foo" +// CHECK-DAG: [[VAR_ptr_v0]] = !DILocalVariable(name: "ptr_v0" +// CHECK-DAG: [[VAR_ptr_v1]] = !DILocalVariable(name: "ptr_v1" +// CHECK-DAG: [[VAR_ptr_v2]] = !DILocalVariable(name: "ptr_v2" +// CODEGEN-DAG: [[VAR_val_ref]] = !DILocalVariable(name: "val_ref" +// CHECK-DAG: [[VAR_fragment_f]] = !DILocalVariable(name: "fragment_f" +// CHECK-DAG: [[VAR_tuple_dead]] = !DILocalVariable(name: "tuple_dead" +// CHECK-DAG: [[ARG_dead_first_foo]] = !DILocalVariable(name: "dead_first_foo" +// CHECK-DAG: [[VAR_dead_first_v0]] = !DILocalVariable(name: "dead_first_v0" +// CHECK-DAG: [[VAR_index_from_var]] = !DILocalVariable(name: "index_from_var" +// CHECK-DAG: [[VAR_const_index_from_start]] = !DILocalVariable(name: "const_index_from_start" +// CHECK-DAG: [[VAR_const_index_from_end]] = !DILocalVariable(name: "const_index_from_end" +// CHECK-DAG: [[VAR_zst_ref]] = !DILocalVariable(name: "zst_ref" +// CHECK-DAG: [[VAR_non_arg_ref_scalar_ref]] = !DILocalVariable(name: "non_arg_ref_scalar_ref" +// CHECK-DAG: [[VAR_non_arg_ref_foo_ref]] = !DILocalVariable(name: "non_arg_ref_foo_ref" +// CHECK-DAG: [[VAR_non_arg_ref_foo_ref_2]] = !DILocalVariable(name: "non_arg_ref_foo_ref_2" |
