https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66614
Bug ID: 66614 Summary: LRA might fail to eliminate dead code Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: bernd.edlinger at hotmail dot de Target Milestone: --- Hi, I have GCC compiled with this local patch in rtx_addr_can_trap_p_1 that should print a warning, when invalid frame offsets are encounterd: Index: rtlanal.c =================================================================== --- rtlanal.c (revision 224708) +++ rtlanal.c (working copy) @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ #include "addresses.h" #include "rtl-iter.h" +#include "tree-pass.h" /* Forward declarations */ static void set_of_1 (rtx, const_rtx, void *); @@ -430,7 +431,20 @@ rtx_addr_can_trap_p_1 (const_rtx x, HOST_WIDE_INT if (FRAME_GROWS_DOWNWARD) { if (adj_offset < frame_offset || adj_offset + size - 1 >= 0) - return 1; + { + HOST_WIDE_INT high_bound = STARTING_FRAME_OFFSET; + HOST_WIDE_INT low_bound = high_bound - get_frame_size (); + fprintf (stderr, "*** %s can trap: function=%s, pass=%s" + ", offset=%" PRId64 ", size=%" PRId64 + ", low_bound=%" PRId64 ", high_bound=%" PRId64 "\n", + x == frame_pointer_rtx ? "frame" + : x == hard_frame_pointer_rtx ? "fp" + : x == stack_pointer_rtx ? "sp" : "argp", + IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), + current_pass->name, + offset, size, low_bound, high_bound); + return 1; + } } else { That should not happen in ordinary code, like GCC itself. BUT it does happen really often, when I boot-strap GCC it happens almost 3.000 times alone in pass 2. All these events happen in the reload pass. As an example I debugged at builtins.c which emits 4 suspicious intructions: *** frame can trap: function=fold_builtin_cbrt, pass=reload, offset=56, size=8, low_bound=-64, high_bound=0 *** frame can trap: function=fold_builtin_cbrt, pass=reload, offset=48, size=8, low_bound=-64, high_bound=0 *** frame can trap: function=fold_builtin_cbrt, pass=reload, offset=40, size=8, low_bound=-64, high_bound=0 *** frame can trap: function=fold_builtin_cbrt, pass=reload, offset=32, size=8, low_bound=-64, high_bound=0 I get this call stack: #0 rtx_addr_can_trap_p_1 (x=0x7ffff6ecb348, offset=56, size=8, mode=DImode, unaligned_mems=false) at ../../gcc-trunk/gcc/rtlanal.c:446 #1 0x0000000000fc3fff in rtx_addr_can_trap_p_1 (x=0x7ffff40d9bb8, offset=0, size=8, mode=DImode, unaligned_mems=false) at ../../gcc-trunk/gcc/rtlanal.c:481 #2 0x0000000000fc845b in may_trap_p_1 (x=0x7ffff40d9bd0, flags=0) at ../../gcc-trunk/gcc/rtlanal.c:2542 #3 0x0000000000fc86b0 in may_trap_p_1 (x=0x7ffff2d07a08, flags=0) at ../../gcc-trunk/gcc/rtlanal.c:2620 #4 0x0000000000fc8763 in may_trap_p (x=0x7ffff2d07a08) at ../../gcc-trunk/gcc/rtlanal.c:2639 #5 0x0000000000e9e851 in process_bb_lives (bb=0x7ffff2c66478, curr_point=@0x7fffffffd904: 123, dead_insn_p=true) at ../../gcc-trunk/gcc/lra-lives.c:697 #6 0x0000000000ea0740 in lra_create_live_ranges_1 (all_p=true, dead_insn_p=true) at ../../gcc-trunk/gcc/lra-lives.c:1261 #7 0x0000000000ea0a22 in lra_create_live_ranges (all_p=true, dead_insn_p=true) at ../../gcc-trunk/gcc/lra-lives.c:1326 #8 0x0000000000e7d7f9 in lra (f=0x0) at ../../gcc-trunk/gcc/lra.c:2308 #9 0x0000000000e272cb in do_reload () at ../../gcc-trunk/gcc/ira.c:5400 #10 0x0000000000e27679 in (anonymous namespace)::pass_reload::execute (this=0x2685070) at ../../gcc-trunk/gcc/ira.c:5571 #11 0x0000000000f3c397 in execute_one_pass (pass=0x2685070) at ../../gcc-trunk/gcc/passes.c:2356 #12 0x0000000000f3c5e1 in execute_pass_list_1 (pass=0x2685070) at ../../gcc-trunk/gcc/passes.c:2409 #13 0x0000000000f3c612 in execute_pass_list_1 (pass=0x2683ff0) at ../../gcc-trunk/gcc/passes.c:2410 #14 0x0000000000f3c64f in execute_pass_list (fn=0x7ffff389ae70, pass=0x2680db0) at ../../gcc-trunk/gcc/passes.c:2420 #15 0x0000000000b10878 in cgraph_node::expand (this=0x7ffff3898310) at ../../gcc-trunk/gcc/cgraphunit.c:1934 #16 0x0000000000b10ea9 in expand_all_functions () at ../../gcc-trunk/gcc/cgraphunit.c:2070 #17 0x0000000000b119c0 in symbol_table::compile (this=0x7ffff6ecf0a8) at ../../gcc-trunk/gcc/cgraphunit.c:2423 #18 0x0000000000b11bd4 in symbol_table::finalize_compilation_unit (this=0x7ffff6ecf0a8) at ../../gcc-trunk/gcc/cgraphunit.c:2510 #19 0x000000000103c552 in compile_file () at ../../gcc-trunk/gcc/toplev.c:577 #20 0x000000000103ea92 in do_compile () at ../../gcc-trunk/gcc/toplev.c:2067 #21 0x000000000103ecde in toplev::main (this=0x7fffffffdc70, argc=33, argv=0x7fffffffdd78) at ../../gcc-trunk/gcc/toplev.c:2168 #22 0x00000000018e5a83 in main (argc=33, argv=0x7fffffffdd78) at ../../gcc-trunk/gcc/main.c:39 at frame #5, curr_insn->u2.insn_uid = 374 at builtins.c.235r.ira this insn looks like this: (insn 374 373 375 56 (set (reg:DI 233) (mem:DI (plus:DI (reg/f:DI 20 frame) (const_int -40 [0xffffffffffffffd8])) [1 S8 A64])) ../../gcc-trunk/gcc/builtins.c:7898 85 {*movdi_internal} (expr_list:REG_EQUIV (mem:DI (plus:DI (reg/f:DI 20 frame) (const_int -40 [0xffffffffffffffd8])) [1 S8 A64]) (nil))) at builtins.c.236r.reload this insn looks like this: (insn 374 373 375 56 (set (reg:DI 4 si [233]) (mem:DI (plus:DI (reg/f:DI 7 sp) (const_int 56 [0x38])) [1 S8 A64])) ../../gcc-trunk/gcc/builtins.c:7898 85 {*movdi_internal} (expr_list:REG_EQUIV (mem:DI (plus:DI (reg/f:DI 20 frame) (const_int -40 [0xffffffffffffffd8])) [1 S8 A64]) (nil))) So this looks exactly like rtx_addr_can_trap_p_1 is called up on a bogus RTX that is a mixture between the old and new RTX, i.e. a frame_pointer_rtx plus a STACK_POINTER relative offset. If may_trap_p (PATTERN (curr_inst)) returns 1 here, when this instruction is actually perfectly safe, that may result in lra being unable to eliminate a dead instruction, just because it uses a bogus offset. This happens by design, as lra uses for some reason two steps to eliminate the frame registers, first the offset alone is changed from frame-relative to sp-relative, and then only the base register is changed from frame to sp, not changing the offset at this time. These intermediate values are never seen in any rtl dumps.