Index: llvm/lib/Transforms/Scalar/SROA.cpp =================================================================== --- llvm/lib/Transforms/Scalar/SROA.cpp +++ llvm/lib/Transforms/Scalar/SROA.cpp @@ -4463,6 +4463,10 @@ // Delete all the dead users of this alloca before splitting and rewriting it. for (Instruction *DeadUser : AS.getDeadUsers()) { + + // Try to preserve debug information attached to the instruction. + salvageDebugInfo(*DeadUser); + // Free up everything used by this instruction. for (Use &DeadOp : DeadUser->operands()) clobberUse(DeadOp); @@ -4512,6 +4516,8 @@ Instruction *I = DeadInsts.pop_back_val(); LLVM_DEBUG(dbgs() << "Deleting dead instruction: " << *I << "\n"); + // Try to preserve debug information attached to the dead instruction. + salvageDebugInfo(*I); // If the instruction is an alloca, find the possible dbg.declare connected // to it, and remove it too. We must do this before calling RAUW or we will // not be able to find it. Index: llvm/test/DebugInfo/dwarfdump-implicit_pointer_sroa.c =================================================================== --- /dev/null +++ llvm/test/DebugInfo/dwarfdump-implicit_pointer_sroa.c @@ -0,0 +1,47 @@ +// RUN: clang %s -O2 -gdwarf-5 -o %t.o +// RUN: llvm-dwarfdump %t.o | FileCheck %s + +// CHECK-LABEL: DW_AT_name ("arr2") + +// 1. Test if more than 2 member location list is printed (for pointer pointing to aggregate) +// CHECK-LABEL: DW_AT_location ( +// CHECK-NEXT: : DW_OP_lit0, DW_OP_stack_value +// CHECK-NEXT: : DW_OP_implicit_pointer [[DIE:0x.+]] +0 +// CHECK-NEXT: : DW_OP_implicit_pointer [[DIE]] +4) +// CHECK-NEXT: DW_AT_name ("ptr1") + +// 2. Test if location lists are merged to two (for pointer pointing to aggregate) +// CHECK-LABEL: DW_AT_location ( +// CHECK-NEXT: : DW_OP_lit0, DW_OP_stack_value +// CHECK-NEXT: : DW_OP_implicit_pointer [[DIE]] +0 +// CHECK-NEXT: DW_AT_name ("ptr3") +// +// 3. Test if one member location list is not omited (for pointer pointing to aggregate) +// CHECK-LABEL: DW_AT_location ( +// CHECK-NEXT: : DW_OP_implicit_pointer {{0x.+}} +0 +// CHECK-NEXT: DW_AT_name ("ptr2") + +static const char *b = "opq"; +volatile int v; +int main() { + int arr1[2] = {1, 2}; + int arr2[2] = {6, 7}; + int *ptr1 = 0; + int *ptr2; + int *ptr3 = 0; + + v++; + ptr1 = arr1; + ptr2 = arr2; + ptr3 = arr1; + (*ptr1)++; + (*ptr2)++; + (*ptr3)++; + v++; + ptr1++; + (*ptr1)++; + (*ptr2)++; + (*ptr3)++; + v++; + return arr1[0] + arr1[1] + arr2[0] + arr2[1] - 5; +} Index: llvm/test/DebugInfo/dwarfdump-implicit_pointer_sroa_inline.c =================================================================== --- /dev/null +++ llvm/test/DebugInfo/dwarfdump-implicit_pointer_sroa_inline.c @@ -0,0 +1,28 @@ +// RUN: clang %s -O2 -gdwarf-5 -o %t.o +// RUN: llvm-dwarfdump %t.o | FileCheck %s + +// CHECK: DW_TAG_inlined_subroutine + +// Test if More than 2 member location list is printed (for pointer pointing to aggregate) +// CHECK: DW_TAG_formal_parameter +// CHECK-NEXT: DW_AT_location +// CHECK-NEXT: : DW_OP_implicit_pointer [[DIE:0x.+]] +0 +// CHECK-NEXT: : DW_OP_implicit_pointer [[DIE]] +4) +// CHECK-NEXT: DW_AT_abstract_origin ({{0x.+}} "ptr") + +static const char *b = "opq"; +volatile int v; +static inline void foo(int *ptr) { + (*ptr)++; + v++; + ptr++; + (*ptr)++; + v++; +} + +int main() { + int arr[2] = {1, 2}; + v++; + foo(arr); + return arr[0] + arr[1] - 5; +} Index: llvm/test/DebugInfo/implicit_pointer_sroa.c =================================================================== --- /dev/null +++ llvm/test/DebugInfo/implicit_pointer_sroa.c @@ -0,0 +1,32 @@ +// RUN: clang %s -O2 -gdwarf-5 -S -emit-llvm -o %t.ll +// RUN: FileCheck %s --input-file=%t.ll + +// CHECK: !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0, 0) +// CHECK: !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0, 0) +// CHECK: !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0, 0) +// CHECK: !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0, 4) + +static const char *b = "opq"; +volatile int v; +int main() { + int arr1[2] = {1, 2}; + int arr2[2] = {6, 7}; + int *ptr1 = 0; + int *ptr2; + int *ptr3 = 0; + + v++; + ptr1 = arr1; + ptr2 = arr2; + ptr3 = arr1; + (*ptr1)++; + (*ptr2)++; + (*ptr3)++; + v++; + ptr1++; + (*ptr1)++; + (*ptr2)++; + (*ptr3)++; + v++; + return arr1[0] + arr1[1] + arr2[0] + arr2[1] - 5; +} Index: llvm/test/DebugInfo/implicit_pointer_sroa_inline.c =================================================================== --- /dev/null +++ llvm/test/DebugInfo/implicit_pointer_sroa_inline.c @@ -0,0 +1,22 @@ +// RUN: clang %s -O2 -gdwarf-5 -S -emit-llvm -o %t.ll +// RUN: FileCheck %s --input-file=%t.ll + +// CHECK: !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0, 0) +// CHECK: !DIExpression(DW_OP_LLVM_implicit_pointer, DW_OP_LLVM_arg0, 4) + +static const char *b = "opq"; +volatile int v; +static inline void foo(int *ptr) { + (*ptr)++; + v++; + ptr++; + (*ptr)++; + v++; +} + +int main() { + int arr[2] = {1, 2}; + v++; + foo(arr); + return arr[0] + arr[1] - 5; +}