https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91347
Bug ID: 91347 Summary: [7,8,9 Regression] pointer_string in linux vsprintf.c is miscompiled when sibling calls are optimized Product: gcc Version: 8.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: danglin at gcc dot gnu.org CC: deller at gmx dot de, svens at stackframe dot org Target Milestone: --- Host: hppa-unknown-linux-gnu Target: hppa-unknown-linux-gnu Build: hppa-unknown-linux-gnu Created attachment 46669 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=46669&action=edit Preproccessed source Sven Schnelle wrote: I wasn't able to write a reproducer so far, but the problem is in lib/vsprintf.c pointer_string(): char *pointer_string(char *buf, char *end, const void *ptr, struct printf_spec spec) { spec.base = 16; spec.flags |= SMALL; if (spec.field_width == -1) { spec.field_width = 2 * sizeof(ptr); spec.flags |= ZEROPAD; } return number(buf, end, (unsigned long int)ptr, spec); } this generates: 00003a34 <pointer_string>: { 3a34: 4b dc 3f 91 ldw -38(sp),ret0 3a38: 6b c2 3f d9 stw rp,-14(sp) 3a3c: d3 9c 1f e8 extrw,s ret0,31,24,ret0 if (spec.field_width == -1) { 3a40: 93 80 37 ff cmpiclr,<> -1,ret0,r0 3a44: 34 1c 00 10 ldi 8,ret0 return number(buf, end, (unsigned long int)ptr, spec); 3a48: 4b d3 3f 91 ldw -38(sp),r19 3a4c: 34 17 00 00 ldi 0,r23 } 3a50: 4b c2 3f d9 ldw -14(sp),rp return number(buf, end, (unsigned long int)ptr, spec); 3a54: d6 7c 0c 08 depw ret0,31,24,r19 3a58: 6b d3 3f 91 stw r19,-38(sp) 3a5c: e8 1e 0d bd b,l 1140 <number>,r0 3a60: 08 00 02 40 nop 3a64: 08 00 02 40 nop I don't see where spec.base get's assigned, and even the source code line is omitted in the objdump -S output. The problem can be duplicated by compiling with -O2 or -Os. The type of spec is: struct printf_spec { unsigned int type:8; signed int field_width:24; unsigned int flags:8; unsigned int base:8; signed int precision:16; } __attribute__((__packed__)); Reviewing the RTL dumps, I see that the assignment of spec.base is dropped in the dse1 pass. In vsprintf.i.258r.cse2, we have: (insn 19 15 20 2 (set (reg:QI 113) (const_int 16 [0x10])) "/home/svens/linux-kernel/parisc-linux/src/lib/vsprintf.c":675 65 {*pa.md:3045} (nil)) (insn 20 19 63 2 (set (mem/j/c:QI (plus:SI (reg/f:SI 107) (const_int 5 [0x5])) [241 spec.base+0 S1 A8]) (reg:QI 113)) "/home/svens/linux-kernel/parisc-linux/src/lib/vsprintf.c":675 65 {*pa.md:3045} (expr_list:REG_DEAD (reg:QI 113) (expr_list:REG_DEAD (reg/f:SI 107) (nil)))) This changes in vsprintf.i.259r.dse1 to: (insn 19 15 21 2 (set (reg:QI 113) (const_int 16 [0x10])) "/home/svens/linux-kernel/parisc-linux/src/lib/vs printf.c":675 65 {*pa.md:3045} (nil)) (jump_insn 21 19 22 2 (set (pc) (if_then_else (eq (reg:SI 98 [ spec$field_width ]) (const_int -1 [0xffffffffffffffff])) (label_ref 27) (pc))) "/home/svens/linux-kernel/parisc-linux/src/lib/vsprintf.c":67 7 30 {*pa.md:1413} (int_list:REG_BR_PROB 365072228 (nil)) -> 27) The DSE processing for insn 20 is: **scanning insn=20 mem: (plus:SI (reg/f:SI 107) (const_int 5 [0x5])) after canon_rtx address: (plus:SI (reg/f:SI 3 %r3) (const_int -51 [0xffffffffffffffcd])) gid=0 offset=-51 processing const base store gid=0[-51..-50) mems_found = 1, cannot_delete = false starting to process insn 20 v: 1, 2 i = -51, index = 1 deferring deletion of insn with uid = 20. Gcc-6 doesn't drop the spec.base assignment. Dropping the assignment causes calls to pointer_string to be output in decimal.