Message ID | 20211229103520.GV2646553@tucnak |
---|---|
State | New |
Headers | show |
Series | emit-rtl: Fix a -fcompare-debug issue due to var-tracking [PR103808] | expand |
On 12/29/2021 3:35 AM, Jakub Jelinek wrote: > Hi! > > We get a -fcompare-debug FAIL on the following testcase. The problem is > that during cprop we get when a TImode pseudo holding x is being > constructed: > (debug_insn 111 59 103 7 (var_location:TI D#2 (clobber (const_int 0 [0]))) -1 > (nil)) > (insn 103 111 110 7 (clobber (reg/v:TI 89 [ x ])) "pr103808.c":8:9 -1 > (nil)) > (debug_insn 110 103 104 7 (var_location:TI D#2 (subreg:TI (reg:DI 111 [ x ]) 0)) -1 > (nil)) > (insn 104 110 109 7 (set (subreg:DI (reg/v:TI 89 [ x ]) 0) > (reg:DI 111 [ x ])) "pr103808.c":8:9 80 {*movdi_internal} > (expr_list:REG_DEAD (reg:DI 111 [ x ]) > (nil))) > Now, during RA that paradoxical subreg in a debug insn obviously can't > affect where pseudo 111 is allocated and RA puts it into the bp register, > so we have: > (debug_insn 110 111 109 4 (var_location:TI D#2 (reg:TI 6 bp [orig:111 x ] [111])) -1 > (nil)) > Now, during var-tracking when we for: > (debug_insn 25 23 26 3 (var_location:TI x (concatn/v:TI [ > (reg:DI 6 bp [orig:111 x ] [111]) > (subreg:DI (debug_expr:TI D#2) 8) > ])) "pr103808.c":8:9 -1 > (nil)) > try to simplify the highpart subreg of bp, gen_rtx_REG_offset is called in: > if (HARD_REGISTER_NUM_P (final_regno)) > { > rtx x = gen_rtx_REG_offset (op, outermode, final_regno, > subreg_memory_offset (outermode, > innermode, byte)); > and that unfortunately sets REG_ATTRS on stack_pointer_rtx, because > gen_rtx_REG_offset uses gen_rtx_REG which for Pmode STACK_POINTER_REGNUM > returns stack_pointer_rtx rather than newly created register. > The clobbering of REG_ATTRS on the shared stack_pointer_rtx then shows up > in the dumps as (reg/f:DI 7 sp [ x+8 ]) instead of (reg/f:DI 7 sp) > that shows up without var-tracking. > Clobbering of REG_ATTRS on the shared *_pointer_rtx looks just wrong. > So, IMHO either simplify_gen_subreg -> gen_rtx_REG_offset should call > gen_raw_REG to make sure we get a new non-shared REG we can set REG_ATTRS > on, or we should make sure that we don't overwrite the REG_ATTRS on the > shared REGs (but then simplify_gen_subreg shouldn't try to overwrite > ORIGINAL_REGNO on those either). > For non-DEBUG_INSNs, I'd hope this never happens, the RA shouldn't allocate > multi-word regs overlapping with stack pointer, hard frame pointer etc. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2021-12-28 Jakub Jelinek <jakub@redhat.com> > > PR debug/103808 > * emit-rtl.c (gen_rtx_REG_offset): Use gen_raw_REG instead of > gen_rtx_REG. > > * gcc.dg/pr103808.c: New test. A comment on why we use gen_raw_REG seems appropriate. OK with that change. jeff
--- gcc/emit-rtl.c.jj 2021-09-14 10:29:03.797811501 +0200 +++ gcc/emit-rtl.c 2021-12-28 19:38:34.670129846 +0100 @@ -1261,7 +1261,7 @@ rtx gen_rtx_REG_offset (rtx reg, machine_mode mode, unsigned int regno, poly_int64 offset) { - rtx new_rtx = gen_rtx_REG (mode, regno); + rtx new_rtx = gen_raw_REG (mode, regno); update_reg_offset (new_rtx, reg, offset); return new_rtx; --- gcc/testsuite/gcc.dg/pr103808.c.jj 2021-12-28 19:40:22.446637355 +0100 +++ gcc/testsuite/gcc.dg/pr103808.c 2021-12-28 19:40:04.750882404 +0100 @@ -0,0 +1,23 @@ +/* PR debug/103808 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-fcompare-debug -O2 -ftrapv" } */ + +void +foo (__int128 x, int y) +{ + for (;;) + { + __int128 a, b; + + x |= !!y; + a = x + 1; + b = y ? ++y : ++x; + y = a < b; + asm ("" : "+r" (y)); + if (x >> 2) + y *= 2; + + if (y == b) + __builtin_unreachable (); + } +}