This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix for reload-failure


Hi,

see the below testcase:
---------- snip -----------
/* compile with -O2 -fpic  */
static void fade_amt_to_vols(double fade_amt) {}
static void recalculate_ideal_ratios ()
{
  int i, len;
  len = 100;
  for (i=0; i<len; i++)
    {
      double cur_fade_amt = (double)(len - 1 - i) / (double)len;
      fade_amt_to_vols (cur_fade_amt);
    }
}
---------- snap -----------

This, when compiled with HEAD or 3.3 (with -O2 -fPIC) on i686-linux breaks
with the already known:
internal compiler error: in verify_initial_elim_offsets, at reload1.c:3361

In this way it's similar to some already fixed PRs.  What happens here is,
that before reload() the PIC-reg is not live, because the only call calls
a static function and there are no other reasons for it being live.  But
the pseudo holding '(double)len' is REG_EQUAL to the constant
'(double)100' and doesn't get a hardreg.  Reload notices this, and creates
for the insn in question two reloads.  Because it's a constant and the
insn accepts a memory-slot, it forces the constant to memory
(force_const_mem()).  The two reloads first load the address of the .LC0,
and then the actual value out of that address.

Now, when the actual insns for the reloads are emitted, some subfunctions
of emit_move_insn() (in particular legitimize_pic_address() in i386.c)
notices, that the address of the constant "(symbol_ref/u:SI ("*.LC0"))" is
not actually a valid PIC address, so it makes it simply valid, and because
it's written in the way it is, it also changes regs_ever_live[] for the
PIC-reg (which now indeed is required) to 1.

This leads to the fact, that suddenly during the emission of reload code
the set of callee-saved regs changes, which is checked, hence the abort.

The underlying reason for all this is, that force_const_to_mem() returns a
possibly non-valid address, which later (when actual reloads are
emitted) is made valid which possibly changes the set of live regs.  The
simplest fix (to validize_mem() the mem-slot we get from
force_const_mem()) doesn't work.  That's because validize_mem() might emit
some code (and even can load parts of the address to a new pseudo, and
whatnot), and during collecting reloads, that's not expected.

Therefore I created a target hook, which reload calls on the address it
get's and makes it possible for the target to change the regs_ever_live[]
set already while collecting, without emitting code, though.  I.e. it
applies the effect the actual emission of validating the address would
have on reload, to reload, without actually validizing it.

Whatever, with the below patch (against HEAD) the failure is away.  It
survives bootstrap without regressions on i686-linux.  3.3 needs the same,
and it already survived bootstrap there (but regression tests are still
running).  OK somewhere?  (I'll checkin also the testcase if yes).

Btw. I grepped for setting regs_ever_live[] in the other target's code,
and found quite some which happen to set it also.  They might show similar
behaviour.


Ciao,
Michael.
-- 
        * hooks.c, hooks.h (hook_void_rtx): New.
        * target-def.h (TARGET_ADDR_EFFECT_ON_RELOAD): New.
        * target.h (addr_effects_on_reload): New.
        * reload.c (topleve): Include target.h.
        (find_reloads): Call above hook.
        * Makefile.in (reload.o): Depend on $(TARGET_H).
        * i386/i386.c (ix86_addr_effects_on_reload): New.
        (toplevel): Define TARGET_ADDR_EFFECT_ON_RELOAD to it.

Index: hooks.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/hooks.c,v
retrieving revision 1.12
diff -u -p -r1.12 hooks.c
--- hooks.c	3 Feb 2003 19:40:57 -0000	1.12
+++ hooks.c	7 Feb 2003 21:03:35 -0000
@@ -117,6 +117,12 @@ hook_void_tree_treeptr (a, b)
 {
 }

+void
+hook_void_rtx (x)
+     rtx x ATTRIBUTE_UNUSED;
+{
+}
+
 bool
 hook_bool_tree_false (a)
      tree a ATTRIBUTE_UNUSED;
Index: hooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/hooks.h,v
retrieving revision 1.12
diff -u -p -r1.12 hooks.h
--- hooks.h	3 Feb 2003 19:40:57 -0000	1.12
+++ hooks.h	7 Feb 2003 21:03:35 -0000
@@ -36,6 +36,7 @@ void hook_void_void PARAMS ((void));
 void hook_void_FILEptr_constcharptr PARAMS ((FILE *, const char *));
 void hook_void_tree PARAMS ((tree));
 void hook_void_tree_treeptr PARAMS ((tree, tree *));
+void hook_void_rtx PARAMS ((rtx));

 int hook_int_tree_tree_1 PARAMS ((tree, tree));
 int hook_int_rtx_0 PARAMS ((rtx));
Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.43
diff -u -p -r1.43 target-def.h
--- target-def.h	3 Feb 2003 19:40:57 -0000	1.43
+++ target-def.h	7 Feb 2003 21:03:35 -0000
@@ -267,6 +267,7 @@ Foundation, 59 Temple Place - Suite 330,
 #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_tree_false
 #define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_tree_false
 #define TARGET_RTX_COSTS hook_bool_rtx_int_int_intp_false
+#define TARGET_ADDR_EFFECT_ON_RELOAD hook_void_rtx

 #ifndef TARGET_IN_SMALL_DATA_P
 #define TARGET_IN_SMALL_DATA_P hook_bool_tree_false
@@ -303,6 +304,7 @@ Foundation, 59 Temple Place - Suite 330,
   TARGET_VALID_POINTER_MODE,                    \
   TARGET_RTX_COSTS,				\
   TARGET_ADDRESS_COST,				\
+  TARGET_ADDR_EFFECT_ON_RELOAD,			\
   TARGET_HAVE_NAMED_SECTIONS,			\
   TARGET_HAVE_CTORS_DTORS,			\
   TARGET_HAVE_TLS,				\
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.49
diff -u -p -r1.49 target.h
--- target.h	3 Feb 2003 19:40:57 -0000	1.49
+++ target.h	7 Feb 2003 21:03:35 -0000
@@ -328,6 +328,10 @@ struct gcc_target
      invalid addresses.  */
   int (* address_cost) PARAMS ((rtx x));

+  /* Apply any effects on reload, which emitting an insn using
+     the memory address ADDR would have.  */
+  void (* addr_effects_on_reload) PARAMS ((rtx));
+
   /* Leave the boolean fields at the end.  */

   /* True if arbitrary sections are supported.  */
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.209
diff -u -p -r1.209 reload.c
--- reload.c	4 Feb 2003 22:47:23 -0000	1.209
+++ reload.c	7 Feb 2003 21:03:35 -0000
@@ -104,6 +104,7 @@ a register with any other reload.  */
 #include "output.h"
 #include "function.h"
 #include "toplev.h"
+#include "target.h"

 #ifndef REGISTER_MOVE_COST
 #define REGISTER_MOVE_COST(m, x, y) 2
@@ -3755,9 +3756,11 @@ find_reloads (insn, replace, ind_levels,
 	    || no_input_reloads)
 	&& operand_mode[i] != VOIDmode)
       {
+        rtx const_mem = force_const_mem (operand_mode[i],
+					 recog_data.operand[i]);
+	(*targetm.addr_effects_on_reload) (XEXP (const_mem, 0));
 	substed_operand[i] = recog_data.operand[i]
-	  = find_reloads_toplev (force_const_mem (operand_mode[i],
-						  recog_data.operand[i]),
+	  = find_reloads_toplev (const_mem,
 				 i, address_type[i], ind_levels, 0, insn,
 				 NULL);
 	if (alternative_allows_memconst (recog_data.constraints[i],
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.988
diff -u -p -r1.988 Makefile.in
--- Makefile.in	6 Feb 2003 01:47:53 -0000	1.988
+++ Makefile.in	7 Feb 2003 21:03:35 -0000
@@ -1635,7 +1635,7 @@ ra-rewrite.o : ra-rewrite.c $(CONFIG_H)
    output.h except.h ra.h reload.h insn-config.h
 reload.o : reload.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) flags.h output.h \
    $(EXPR_H) $(OPTABS_H) reload.h $(RECOG_H) hard-reg-set.h insn-config.h \
-   $(REGS_H) function.h real.h toplev.h $(TM_P_H)
+   $(REGS_H) function.h real.h toplev.h $(TM_P_H) $(TARGET_H)
 reload1.o : reload1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) real.h flags.h \
    $(EXPR_H) $(OPTABS_H) reload.h $(REGS_H) hard-reg-set.h insn-config.h \
    $(BASIC_BLOCK_H) $(RECOG_H) output.h function.h toplev.h cselib.h $(TM_P_H) \
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.529
diff -u -p -r1.529 i386.c
--- config/i386/i386.c	6 Feb 2003 10:39:44 -0000	1.529
+++ config/i386/i386.c	7 Feb 2003 21:03:35 -0000
@@ -833,6 +833,7 @@ static void x86_output_mi_thunk PARAMS (
 static bool x86_can_output_mi_thunk PARAMS ((tree, HOST_WIDE_INT,
 					     HOST_WIDE_INT, tree));
 bool ix86_expand_carry_flag_compare PARAMS ((enum rtx_code, rtx, rtx, rtx*));
+static void ix86_addr_effects_on_reload PARAMS ((rtx));

 struct ix86_address
 {
@@ -1008,6 +1009,9 @@ static enum x86_64_reg_class merge_class
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST ix86_address_cost

+#undef TARGET_ADDR_EFFECT_ON_RELOAD
+#define TARGET_ADDR_EFFECT_ON_RELOAD ix86_addr_effects_on_reload
+
 struct gcc_target targetm = TARGET_INITIALIZER;

 /* Sometimes certain combinations of command options do not make
@@ -5853,6 +5857,53 @@ ix86_GOT_alias_set ()
   if (set == -1)
     set = new_alias_set ();
   return set;
+}
+
+static void
+ix86_addr_effects_on_reload (addr)
+     rtx addr;
+{
+#if TARGET_MACHO
+  /* XXX do something??? */
+#endif
+
+  if (!flag_pic || TARGET_64BIT || !reload_in_progress)
+    return;
+  if (local_symbolic_operand (addr, Pmode)
+      || GET_CODE (addr) == SYMBOL_REF)
+    /* This symbol may be referenced via a displacement from the PIC
+       base address (@GOTOFF).  */
+    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+  else
+    {
+      if (GET_CODE (addr) == CONST)
+	{
+	  addr = XEXP (addr, 0);
+
+	  /* We must match stuff we generate before.  Assume the only
+	     unspecs that can get here are ours.  Not that we could do
+	     anything with them anyway...  */
+	  if (GET_CODE (addr) == UNSPEC
+	      || (GET_CODE (addr) == PLUS
+		  && GET_CODE (XEXP (addr, 0)) == UNSPEC))
+	    return;
+	}
+      if (GET_CODE (addr) == PLUS)
+	{
+	  rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
+
+	  /* Check first to see if this is a constant offset from a @GOTOFF
+	     symbol reference.  */
+	  if (local_symbolic_operand (op0, Pmode)
+	      && GET_CODE (op1) == CONST_INT)
+	    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+	  else
+	    {
+	      ix86_addr_effects_on_reload (XEXP (addr, 0));
+	      ix86_addr_effects_on_reload (XEXP (addr, 1));
+	    }
+	}
+    }
 }

 /* Return a legitimate reference for ORIG (an address) using the


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]