Summary: | GCC inserts redundant "test" instruction due to incorrect clobber | ||
---|---|---|---|
Product: | gcc | Reporter: | Jason Garrett-Glaser <darkshikari> |
Component: | target | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | enhancement | CC: | astrange+gcc, gcc-bugs, jeffreyalaw |
Priority: | P3 | Keywords: | missed-optimization |
Version: | 4.6.0 | ||
Target Milestone: | --- | ||
Host: | Target: | i?86-*-* x86_64-*-* | |
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2011-12-30 00:00:00 |
Description
Jason Garrett-Glaser
2010-06-09 04:19:54 UTC
The problem is combine. This: int test2( int *b ) { int b_ = *b; b_--; if( b_ == 0 ) { *b = b_; return foo(); } *b = b_; return 0; } works: _test2: LFB1: movl (%rdi), %eax decl %eax je L7 <- uses decl movl %eax, (%rdi) xorl %eax, %eax ret .align 4,0x90 L7: movl $0, (%rdi) xorl %eax, %eax jmp _foo The original turns (*b)-- into load/dec/store/cmp - combine tries to combine dec/store which fails, but doesn't try dec/cmp. Still happens with the new combine work (not that I really expected it to change). Confirmed. Combine does: Trying 7 -> 8: Trying 9 -> 10: But never 7 -> 9 which is needed for this to work. This is for: int foo(); int t; int test( int b ) { (b)--; t = b; if( b == 0 ) return foo(); return 0; } --- CUT -- Where 7, 8, 9, and 10 are: (insn 7 3 8 2 (parallel [ (set (reg/v:SI 60 [ b ]) (plus:SI (reg/v:SI 62 [ b ]) (const_int -1 [0xffffffffffffffff]))) (clobber (reg:CC 17 flags)) ]) t.c:6 253 {*addsi_1} (expr_list:REG_DEAD (reg/v:SI 62 [ b ]) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil)))) (insn 8 7 9 2 (set (mem/c/i:SI (symbol_ref:DI ("t") <var_decl 0x7fedc8e8c140 t>) [2 t+0 S4 A32]) (reg/v:SI 60 [ b ])) t.c:7 64 {*movsi_internal} (nil)) (insn 9 8 10 2 (set (reg:CCZ 17 flags) (compare:CCZ (reg/v:SI 60 [ b ]) (const_int 0 [0]))) t.c:8 2 {*cmpsi_ccno_1} (expr_list:REG_DEAD (reg/v:SI 60 [ b ]) (nil))) (jump_insn 10 9 11 2 (set (pc) (if_then_else (ne (reg:CCZ 17 flags) (const_int 0 [0])) (label_ref 16) (pc))) t.c:8 599 {*jcc_1} (expr_list:REG_DEAD (reg:CCZ 17 flags) (expr_list:REG_BR_PROB (const_int 6102 [0x17d6]) (nil))) -> 16) Compare-elimination does the right thing and eliminates the redundant test on the trunk. Given the age of the BZ I didn't track it down any further than that. |