Hi all, In this PR we've got code like this: register struct test2_s *g __asm__("x28");
void do_something () { test_fptr (); struct test2_s *p1 = 0; *p1 = *g; } And we get an ICE in gcc/ree.c:655 in get_sub_rtx. The problem is when we try to process the defining insn of register x28 from the insn: (set (reg/f:DI 1 x1 [orig:74 g.1_2 ] [74]) (zero_extend:DI (reg/v:SI 28 x28 [ g ]))) The dataflow reports the insn setting x28 to be: (call_insn 8 7 10 2 (parallel [ (call (mem:DI (reg/f:DI 0 x0 [orig:77 test_fptr ] [77]) [0 *test_fptr.0_1 S8 A8]) (const_int 0 [0])) (use (const_int 0 [0])) (clobber (reg:DI 30 x30)) ]) "ree.c":14 41 {*call_reg} (expr_list:REG_CALL_DECL (nil) (nil)) (expr_list (clobber (reg:DI 17 x17)) (expr_list (clobber (reg:DI 16 x16)) (nil)))) which, as you can see, doesn't actually set x28. AFAICS the reason dataflow reports call_insn 8 as defining x28 is because x28 is a global register variable and that means that every function call is considered to define it. But the ree pass can't really use any of that. It only wants some SET RTL patterns to play with. One solution is to bail out at the ICE location, in get_sub_rtx, when no SETs are found inside the parallel. But I think we shouldn't be getting this far along anyway. So this patch prevents the call_insn from being recognised as a defining insn for x28 for the purposes of ree. It makes sure that if the register we're extending is a global register that all the insns in the def chain actually set it directly as determined by set_of from rtlanal.c. This should hopefully still allow ree to optimise extensions of global registers as long as they are combined with legitimate defining insns. Bootstrapped and tested on aarch64, arm, x86_64. Ok for trunk? Thanks, Kyrill 2016-10-20 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR rtl-optimization/78038 * ree.c (get_defs): Return NULL if a defining insn for REG cannot be deduced to set REG through the RTL structure. (make_defs_and_copies_lists): Return false on a failing get_defs call. 2016-10-20 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR rtl-optimization/78038 * gcc.target/aarch64/pr78038.c: New test.
diff --git a/gcc/ree.c b/gcc/ree.c index 4ab2ad088c363caaaae8abaad375ec5a78bf13ea..374988e792e27fc342518e8e98af618bc595dbce 100644 --- a/gcc/ree.c +++ b/gcc/ree.c @@ -482,6 +482,14 @@ get_defs (rtx_insn *insn, rtx reg, vec<rtx_insn *> *dest) return NULL; if (DF_REF_INSN_INFO (ref_link->ref) == NULL) return NULL; + /* As global regs are assumed to be defined at each function call + dataflow can report a call_insn as being a definition of REG. + But we can't do anything with that in this pass so proceed only + if the instruction really sets REG in a way that can be deduced + from the RTL structure. */ + if (global_regs[REGNO (reg)] + && !set_of (reg, DF_REF_INSN (ref_link->ref))) + return NULL; } if (dest) @@ -580,7 +588,7 @@ make_defs_and_copies_lists (rtx_insn *extend_insn, const_rtx set_pat, /* Initialize the work list. */ if (!get_defs (extend_insn, src_reg, &state->work_list)) - gcc_unreachable (); + return false; is_insn_visited = XCNEWVEC (bool, max_insn_uid); diff --git a/gcc/testsuite/gcc.target/aarch64/pr78038.c b/gcc/testsuite/gcc.target/aarch64/pr78038.c new file mode 100644 index 0000000000000000000000000000000000000000..76d97d3b0ad44cd75afa1e1e45434413421c5afa --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr78038.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +/* PR rtl-optimization/78038. + Make sure ree can gracefully handle extensions of the global + variable register after a call. */ + +typedef void (*test_fptr_t) (void); +void +test_f (void) +{ +} +test_fptr_t test_fptr = test_f; + +struct test2_s +{ + int f; +}; + +register struct test2_s *g __asm__("x28"); + +void +do_something () +{ + test_fptr (); + struct test2_s *p1 = 0; + *p1 = *g; +}