llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.61k stars 11.35k forks source link

[debuginfo][optimizations] A specific combination of function optimization passes triggers debug information of local variables missing #88863

Open edumoot opened 4 months ago

edumoot commented 4 months ago

LLVM 18.1.2 (commit 261aae0c) LLVM 17.0.6 (commit, 6009fe18)

Reproduce with:

clang -g -O0 case.c -Xclang -disable-O0-optnone -emit-llvm -c -o case.bc
opt -passes='function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<no-header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;vectorize-forced-only;>,loop-load-elim,instcombine<max-iterations=1000;no-use-loop-info>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,vector-combine,instcombine<max-iterations=1000;no-use-loop-info>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,instcombine<max-iterations=1000;no-use-loop-info>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>)' case.bc  -o case.opt.bc
llc --relocation-model=pic case.opt.bc -o case.s
clang case.s -o case.out

Results:

We cannot get debug information of local variables on line 16 and on line 24.

(lldb) file case.out
Current executable set to '/home/ad/Downloads/lldb/reproduce_bugs/case.out' (x86_64).
(lldb) b case.c:16
Breakpoint 1: where = case.out`calculateValue + 4 at case.c:16:21, address = 0x0000000000001144
(lldb) r
Process 34498 launched: '/home/ad/Downloads/lldb/reproduce_bugs/case.out' (x86_64)
Process 34498 stopped
* thread #1, name = 'case.out', stop reason = breakpoint 1.1
    frame #0: 0x0000555555555144 case.out`calculateValue at case.c:16:21
   13   static long  calculateValue(void)
   14   { 
   15       struct Data localData1 = {21,235,1,4294967292,5,2};
-> 16       for (globalVar1 = 0; (globalVar1 < (-21)); globalVar1 = globalVar1 - 5)
   17       { 
   18           struct Data localData2 = {40,32,97,0,7,44};
   19           globalData2 = globalData1;
(lldb) fr v
(lldb) s
Process 34498 stopped
* thread #1, name = 'case.out', stop reason = step in
    frame #0: 0x000055555555514f case.out`calculateValue at case.c:24:1
   21           return localData2.field2;
   22       }
   23       return localData1.field4;
-> 24   }
   25   
   26   int main (void)
   27   {
(lldb) fr v
(lldb) 

and the same problem exists in GDB.

Breakpoint 2, calculateValue () at case.c:16
16      for (globalVar1 = 0; (globalVar1 < (-21)); globalVar1 = globalVar1 - 5)
(gdb) info locals
No locals.
(gdb) s
24  }
(gdb) info locals
No locals.

cat case.c

struct Data {
   signed field1 : 13;
   signed field2 : 16;
   unsigned char  field3;
   unsigned long  field4;
   unsigned short  field5;
   long  field6;
};
static long globalVar1 = 0xC4185A1FL;
static const struct Data globalData1 = {18,-198,26,0,-26,3};
static struct Data globalData2 = {62,15,5,6,8L,3};

static long  calculateValue(void)
{ 
    struct Data localData1 = {21,235,1,4294967292,5,2};
    for (globalVar1 = 0; (globalVar1 < (-21)); globalVar1 = globalVar1 - 5)
    { 
        struct Data localData2 = {40,32,97,0,7,44};
        globalData2 = globalData1;
        localData2 = localData1;
        return localData2.field2;
    }
    return localData1.field4;
}

int main (void)
{
    return calculateValue();
}
edumoot commented 4 months ago

We can not find a piece of information as the following, compared with the debug information generated through 'clang -g -O0 case.c -o case.out':

0x000000b9:     DW_TAG_variable
                  DW_AT_location    (DW_OP_fbreg -72)
                  DW_AT_name    ("localData1")
                  DW_AT_decl_file   ("/home/ad/Downloads/lldb/reproduce_bugs/case.c")
                  DW_AT_decl_line   (15)
                  DW_AT_type    (0x0000003d "Data")

0x000000c5:     DW_TAG_lexical_block
                  DW_AT_low_pc  (0x0000000000001199)
                  DW_AT_high_pc (0x000000000000122e)

0x000000cb:       DW_TAG_variable
                    DW_AT_location  (DW_OP_fbreg -40)
                    DW_AT_name  ("localData2")
                    DW_AT_decl_file ("/home/ad/Downloads/lldb/reproduce_bugs/case.c")
                    DW_AT_decl_line (18)
                    DW_AT_type  (0x0000003d "Data")

Debug information of local variables, like 'localData1', is missing from the binary after we apply this optimization sequence:

function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<no-header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;vectorize-forced-only;>,loop-load-elim,instcombine<max-iterations=1000;no-use-loop-info>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,vector-combine,instcombine<max-iterations=1000;no-use-loop-info>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,instcombine<max-iterations=1000;no-use-loop-info>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>)
llvmbot commented 4 months ago

@llvm/issue-subscribers-debuginfo

Author: Yachao Zhu (edumoot)

LLVM 18.1.2 (commit [261aae0c](https://github.com/llvm/llvm-project/commit/26a1d6601d727a96f4301d0d8647b5a42760ae0c)) LLVM 17.0.6 (commit, [6009fe18](https://github.com/llvm/llvm-project/commit/6009708b4367171ccdbf4b5905cb6a803753fe18)) Reproduce with: ```compiling pipeline clang -g -O0 case.c -Xclang -disable-O0-optnone -emit-llvm -c -o case.bc opt -passes='function<eager-inv>(float2int,lower-constant-intrinsics,loop(loop-rotate<no-header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;vectorize-forced-only;>,loop-load-elim,instcombine<max-iterations=1000;no-use-loop-info>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;sink-common-insts;speculate-blocks;simplify-cond-branch>,vector-combine,instcombine<max-iterations=1000;no-use-loop-info>,loop-unroll<O2>,transform-warning,sroa<preserve-cfg>,instcombine<max-iterations=1000;no-use-loop-info>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-sink-common-insts;speculate-blocks;simplify-cond-branch>)' case.bc -o case.opt.bc llc --relocation-model=pic case.opt.bc -o case.s clang case.s -o case.out ``` Results: We cannot get debug information of local variables on line 16 and on line 24. ``` (lldb) file case.out Current executable set to '/home/ad/Downloads/lldb/reproduce_bugs/case.out' (x86_64). (lldb) b case.c:16 Breakpoint 1: where = case.out`calculateValue + 4 at case.c:16:21, address = 0x0000000000001144 (lldb) r Process 34498 launched: '/home/ad/Downloads/lldb/reproduce_bugs/case.out' (x86_64) Process 34498 stopped * thread #1, name = 'case.out', stop reason = breakpoint 1.1 frame #0: 0x0000555555555144 case.out`calculateValue at case.c:16:21 13 static long calculateValue(void) 14 { 15 struct Data localData1 = {21,235,1,4294967292,5,2}; -> 16 for (globalVar1 = 0; (globalVar1 < (-21)); globalVar1 = globalVar1 - 5) 17 { 18 struct Data localData2 = {40,32,97,0,7,44}; 19 globalData2 = globalData1; (lldb) fr v (lldb) s Process 34498 stopped * thread #1, name = 'case.out', stop reason = step in frame #0: 0x000055555555514f case.out`calculateValue at case.c:24:1 21 return localData2.field2; 22 } 23 return localData1.field4; -> 24 } 25 26 int main (void) 27 { (lldb) fr v (lldb) ``` and the same problem exists in GDB. ``` Breakpoint 2, calculateValue () at case.c:16 16 for (globalVar1 = 0; (globalVar1 < (-21)); globalVar1 = globalVar1 - 5) (gdb) info locals No locals. (gdb) s 24 } (gdb) info locals No locals. ``` `cat case.c` ``` struct Data { signed field1 : 13; signed field2 : 16; unsigned char field3; unsigned long field4; unsigned short field5; long field6; }; static long globalVar1 = 0xC4185A1FL; static const struct Data globalData1 = {18,-198,26,0,-26,3}; static struct Data globalData2 = {62,15,5,6,8L,3}; static long calculateValue(void) { struct Data localData1 = {21,235,1,4294967292,5,2}; for (globalVar1 = 0; (globalVar1 < (-21)); globalVar1 = globalVar1 - 5) { struct Data localData2 = {40,32,97,0,7,44}; globalData2 = globalData1; localData2 = localData1; return localData2.field2; } return localData1.field4; } int main (void) { return calculateValue(); } ```