[rtl, x86] Generalise FP constant define_splits

Richard Sandiford richard@codesourcery.com
Tue Mar 20 16:30:00 GMT 2007


i386.md has some splitters to convert FP memory loads into FP constant
loads.  These splitters rely on being able to trace the memory address
back to a particular constant pool entry.  It's possible to do this
for most x86 PIC targets because they use a GP-based GOTOFF access.
Unfortunately, VxWorks needs to use a separate GOT load instead,
so all the FP load sees is a MEM with a single-register address.

The instructions still generally have a REG_EQUAL or REG_EQUIV note
with the original constant attached, so this patch generalises the
splitters to use such notes where possible.  The new approach also has
the advantage of avoiding two calls to avoid_constant_pool_reference.

The new splitters stash the result of find_constant_src in a spare
operand.  This idiom is already used by the MIPS port FWIW (and maybe
others).

I did a recursive grep to make sure that this was indeed the last
use of constant_pool_reference_p.

Bootstrapped & regression-tested on x86_64-linux-gnu.  Also tested on
i586-wrs-vxworks, where it fixes tests like i386/386-[34].c for -fPIC.
OK to install?

Richard


gcc/
	* rtl.h (constant_pool_reference_p): Delete.
	(find_constant_src): Declare.
	* rtlanal.c (find_constant_src): New function.
	* simplify-rtx.c (constant_pool_reference_p): Delete.
	* config/i386/i386.md: Use find_constant_src instead of
	constant_pool_reference_p/avoid_constant_pool_reference pairs.

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	(revision 122993)
+++ gcc/rtl.h	(working copy)
@@ -1641,7 +1641,6 @@ extern rtx simplify_gen_subreg (enum mac
 extern rtx simplify_replace_rtx (rtx, rtx, rtx);
 extern rtx simplify_rtx (rtx);
 extern rtx avoid_constant_pool_reference (rtx);
-extern bool constant_pool_reference_p (rtx x);
 extern bool mode_signbit_p (enum machine_mode, rtx);
 
 /* In regclass.c  */
@@ -1703,6 +1702,7 @@ extern int dead_or_set_regno_p (rtx, uns
 extern rtx find_reg_note (rtx, enum reg_note, rtx);
 extern rtx find_regno_note (rtx, enum reg_note, unsigned int);
 extern rtx find_reg_equal_equiv_note (rtx);
+extern rtx find_constant_src (rtx);
 extern int find_reg_fusage (rtx, enum rtx_code, rtx);
 extern int find_regno_fusage (rtx, enum rtx_code, unsigned int);
 extern int pure_call_p (rtx);
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	(revision 122993)
+++ gcc/rtlanal.c	(working copy)
@@ -1750,6 +1750,30 @@ find_reg_equal_equiv_note (rtx insn)
   return NULL;
 }
 
+/* Check whether INSN is a single_set whose source is known to be
+   equivalent to a constant.  Return that constant if so, otherwise
+   return null.  */
+
+rtx
+find_constant_src (rtx insn)
+{
+  rtx note, set, x;
+
+  set = single_set (insn);
+  if (set)
+    {
+      x = avoid_constant_pool_reference (SET_SRC (set));
+      if (CONSTANT_P (x))
+	return x;
+    }
+
+  note = find_reg_equal_equiv_note (insn);
+  if (note && CONSTANT_P (XEXP (note, 0)))
+    return XEXP (note, 0);
+
+  return NULL_RTX;
+}
+
 /* Return true if DATUM, or any overlap of DATUM, of kind CODE is found
    in the CALL_INSN_FUNCTION_USAGE information of INSN.  */
 
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 122993)
+++ gcc/simplify-rtx.c	(working copy)
@@ -202,14 +202,6 @@ avoid_constant_pool_reference (rtx x)
 
   return x;
 }
-
-/* Return true if X is a MEM referencing the constant pool.  */
-
-bool
-constant_pool_reference_p (rtx x)
-{
-  return avoid_constant_pool_reference (x) != x;
-}
 
 /* Make a unary operation by first seeing if it folds and otherwise making
    the specified operation.  */
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md	(revision 122993)
+++ gcc/config/i386/i386.md	(working copy)
@@ -2331,10 +2331,9 @@ (define_split
 	(match_operand:SF 1 "memory_operand" ""))]
   "reload_completed
    && MEM_P (operands[1])
-   && constant_pool_reference_p (operands[1])"
+   && (operands[2] = find_constant_src (insn))"
   [(set (match_dup 0)
-	(match_dup 1))]
-  "operands[1] = avoid_constant_pool_reference (operands[1]);")
+	(match_dup 2))])
 
 
 ;; %%% Kill this when call knows how to work this out.
@@ -3078,10 +3077,10 @@ (define_split
    && (GET_MODE (operands[0]) == XFmode
        || GET_MODE (operands[0]) == SFmode
        || GET_MODE (operands[0]) == DFmode)
-   && constant_pool_reference_p (operands[1])"
-  [(set (match_dup 0) (match_dup 1))]
+   && (operands[2] = find_constant_src (insn))"
+  [(set (match_dup 0) (match_dup 2))]
 {
-  rtx c = avoid_constant_pool_reference (operands[1]);
+  rtx c = operands[2];
   rtx r = operands[0];
 
   if (GET_CODE (r) == SUBREG)
@@ -3099,8 +3098,6 @@ (define_split
     }
   else if (MMX_REG_P (r))
     FAIL;
-
-  operands[1] = c;
 })
 
 (define_split
@@ -3111,10 +3108,10 @@ (define_split
    && (GET_MODE (operands[0]) == XFmode
        || GET_MODE (operands[0]) == SFmode
        || GET_MODE (operands[0]) == DFmode)
-   && constant_pool_reference_p (operands[1])"
-  [(set (match_dup 0) (match_dup 1))]
+   && (operands[2] = find_constant_src (insn))"
+  [(set (match_dup 0) (match_dup 2))]
 {
-  rtx c = avoid_constant_pool_reference (SET_SRC (PATTERN (curr_insn)));
+  rtx c = operands[2];
   rtx r = operands[0];
 
   if (GET_CODE (r) == SUBREG)
@@ -3132,8 +3129,6 @@ (define_split
     }
   else if (MMX_REG_P (r))
     FAIL;
-
-  operands[1] = c;
 })
 
 (define_insn "swapxf"



More information about the Gcc-patches mailing list