Hi, This patch allows propagation of loop invariants for i386 if propagated value is a constant to be used in address operand. Bootstrapped and tested on x86_64-unknown-linux-gnu. OK for trunk or stage 1?
Thanks, Ilya -- gcc/ 2015-03-10 Ilya Enkovich <ilya.enkov...@intel.com> PR target/65103 * gcc/target.def (try_fwprop_invariant): New. * gcc/doc/tm.texi.in (TARGET_TRY_FWPROP_INVARIANT): New. * gcc/doc/tm.texi: Regenerate. * gcc/fwprop.c (forward_propagate_into): Propagate loop invariants if a target says so. * gcc/hooks.h (hook_bool_rtx_bool_false): New. * gcc/hooks.c (hook_bool_rtx_bool_false): New. * gcc/config/i386/i386.c (ix86_try_fwprop_invariant): New. (TARGET_TRY_FWPROP_INVARIANT): New. gcc/testsuite/ 2015-03-10 Ilya Enkovich <ilya.enkov...@intel.com> PR target/65103 * gcc.target/i386/pr65103-2.c: New. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 06eacd0..b3971b8 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -12977,6 +12977,16 @@ ix86_address_cost (rtx x, machine_mode, addr_space_t, bool) return cost; } + +static bool +ix86_try_fwprop_invariant (rtx def_set, bool address_use) +{ + if (address_use && GET_CODE (SET_SRC (def_set)) == CONST) + return true; + + return false; +} + /* Allow {LABEL | SYMBOL}_REF - SYMBOL_REF-FOR-PICBASE for Mach-O as this is used for to form addresses to local data when -fPIC is in @@ -52208,6 +52218,9 @@ ix86_initialize_bounds (tree var, tree lb, tree ub, tree *stmts) #undef TARGET_ABSOLUTE_BIGGEST_ALIGNMENT #define TARGET_ABSOLUTE_BIGGEST_ALIGNMENT 512 +#undef TARGET_TRY_FWPROP_INVARIANT +#define TARGET_TRY_FWPROP_INVARIANT ix86_try_fwprop_invariant + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-i386.h" diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 6c5bfab..59602c4 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -6421,6 +6421,12 @@ should probably only be given to addresses with different numbers of registers on machines with lots of registers. @end deftypefn +@deftypefn {Target Hook} bool TARGET_TRY_FWPROP_INVARIANT (rtx @var{def_set}, bool @var{address_use}) +This hooks tells if it may worth to propagate loop invariant +@var{def_set} into the loop. @var{address_use} is 1 if values is +used in an address operand. +@end deftypefn + @node Scheduling @section Adjusting the Instruction Scheduler diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 8d6dfbc..56e73df 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -4722,6 +4722,8 @@ Define this macro if a non-short-circuit operation produced by @hook TARGET_ADDRESS_COST +@hook TARGET_TRY_FWPROP_INVARIANT + @node Scheduling @section Adjusting the Instruction Scheduler diff --git a/gcc/fwprop.c b/gcc/fwprop.c index fc64ec9..d006200 100644 --- a/gcc/fwprop.c +++ b/gcc/fwprop.c @@ -1365,8 +1365,17 @@ forward_propagate_into (df_ref use) if (DF_REF_IS_ARTIFICIAL (def)) return false; + def_insn = DF_REF_INSN (def); + if (multiple_sets (def_insn)) + return false; + def_set = single_set (def_insn); + if (!def_set) + return false; + /* Do not propagate loop invariant definitions inside the loop. */ - if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father) + if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father + && !targetm.try_fwprop_invariant (def_set, + DF_REF_TYPE (use) != DF_REF_REG_USE)) return false; /* Check if the use is still present in the insn! */ @@ -1379,13 +1388,6 @@ forward_propagate_into (df_ref use) if (!reg_mentioned_p (DF_REF_REG (use), parent)) return false; - def_insn = DF_REF_INSN (def); - if (multiple_sets (def_insn)) - return false; - def_set = single_set (def_insn); - if (!def_set) - return false; - /* Only try one kind of propagation. If two are possible, we'll do it on the following iterations. */ if (forward_propagate_and_simplify (use, def_insn, def_set) diff --git a/gcc/hooks.c b/gcc/hooks.c index 824aeb0..1f32701 100644 --- a/gcc/hooks.c +++ b/gcc/hooks.c @@ -302,6 +302,12 @@ hook_bool_tree_tree_false (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED) } bool +hook_bool_rtx_bool_false (rtx, bool) +{ + return false; +} + +bool hook_bool_tree_tree_true (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED) { return true; diff --git a/gcc/hooks.h b/gcc/hooks.h index 8c929e8..9c32489 100644 --- a/gcc/hooks.h +++ b/gcc/hooks.h @@ -59,6 +59,7 @@ extern bool hook_bool_rtx_insn_int_false (rtx_insn *, int); extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *); extern bool hook_bool_rtx_int_int_int_intp_bool_false (rtx, int, int, int, int *, bool); +extern bool hook_bool_rtx_bool_false (rtx, bool); extern bool hook_bool_tree_tree_false (tree, tree); extern bool hook_bool_tree_tree_true (tree, tree); extern bool hook_bool_tree_bool_false (tree, bool); diff --git a/gcc/target.def b/gcc/target.def index a00181a..5334437 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -3465,6 +3465,16 @@ registers on machines with lots of registers.", int, (rtx address, machine_mode mode, addr_space_t as, bool speed), default_address_cost) +/* Return 1 if we fwprop should consider propagating loop invariant + definition DEF_SET inside the loop. ADDRESS_USE is 1 if value is + used in address operand. */ +DEFHOOK +(try_fwprop_invariant, + "This hooks tells if it may worth to propagate loop invariant\n\ +@var{def_set} into the loop. @var{address_use} is 1 if values is\n\ +used in an address operand.", + bool, (rtx def_set, bool address_use), hook_bool_rtx_bool_false) + /* Return where to allocate pseudo for a given hard register initial value. */ DEFHOOK (allocate_initial_value, diff --git a/gcc/testsuite/gcc.target/i386/pr65103-2.c b/gcc/testsuite/gcc.target/i386/pr65103-2.c new file mode 100644 index 0000000..1af01ad --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr65103-2.c @@ -0,0 +1,23 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-m32 -O2 -fPIE" } */ +/* { dg-final { scan-assembler-not "GOTOFF," } } */ + +typedef struct S +{ + int a; + int b; +} S; +struct S gs; + +extern int compute ( struct S * ); + +int test( void ) +{ + int t = -1; + while (t) + { + gs.a++; + t = compute (&gs); + } + return 0; +}