@@ -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"
@@ -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
@@ -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
@@ -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)
@@ -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;
@@ -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);
@@ -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,
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-require-effective-target pie } */
+/* { dg-options "-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;
+}