gcse.c (want_to_gcse_p): On STACK_REGS targets...
authorRoger Sayle <roger@eyesopen.com>
Sun, 19 Feb 2006 22:01:17 +0000 (22:01 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sun, 19 Feb 2006 22:01:17 +0000 (22:01 +0000)
* gcse.c (want_to_gcse_p): On STACK_REGS targets, look through
constant pool references to identify stack mode constants.
* rtlanal.c (constant_pool_constant_p): New predicate to check
whether operand is a floating point constant in the pool.
* rtl.h (constant_pool_constant_p): Prototype here.
* loop.c (scan_loop): Avoid hoisting constants from the constant
pool on STACK_REGS targets.
(load_mems): Likewise.
* loop-invariant.c (get_inv_cost): Make hoisting constant pool
loads into x87 registers expensive in terms of register pressure.

Co-Authored-By: Steven Bosscher <stevenb.gcc@gmail.com>
From-SVN: r111283

gcc/ChangeLog
gcc/gcse.c
gcc/loop-invariant.c
gcc/loop.c
gcc/rtl.h
gcc/rtlanal.c

index f855ed05b120c04f93d6317d676f605d6c535740..988eed4045a276ac9c959e06694b1abcbbb4b244 100644 (file)
@@ -1,3 +1,17 @@
+2006-02-19  Roger Sayle  <roger@eyesopen.com>
+           Steven Bosscher  <stevenb.gcc@gmail.com>
+
+       * gcse.c (want_to_gcse_p): On STACK_REGS targets, look through
+       constant pool references to identify stack mode constants.
+       * rtlanal.c (constant_pool_constant_p): New predicate to check
+       whether operand is a floating point constant in the pool.
+       * rtl.h (constant_pool_constant_p): Prototype here.
+       * loop.c (scan_loop): Avoid hoisting constants from the constant
+       pool on STACK_REGS targets.
+       (load_mems): Likewise.
+       * loop-invariant.c (get_inv_cost): Make hoisting constant pool
+       loads into x87 registers expensive in terms of register pressure.
+
 2006-02-19  Roger Sayle  <roger@eyesopen.com>
 
        * gthr-posix.h: On Tru64, map __gthr_foo as a weak reference to
index 93c366b7dbe7696017b8f17791553a5aa762923b..4270737377980db321af495b7350d67050d7df7a 100644 (file)
@@ -1170,6 +1170,14 @@ static basic_block current_bb;
 static int
 want_to_gcse_p (rtx x)
 {
+#ifdef STACK_REGS
+  /* On register stack architectures, don't GCSE constants from the
+     constant pool, as the benefits are often swamped by the overhead
+     of shuffling the register stack between basic blocks.  */
+  if (IS_STACK_MODE (GET_MODE (x)))
+    x = avoid_constant_pool_reference (x);
+#endif
+
   switch (GET_CODE (x))
     {
     case REG:
index 04531a0e05fcc95afe97ac646d66aed7e059a76e..3f8f6e34848a1d52be455a61c2d974cf80f0a8e3 100644 (file)
@@ -932,6 +932,32 @@ get_inv_cost (struct invariant *inv, int *comp_cost, unsigned *regs_needed)
   (*regs_needed)++;
   (*comp_cost) += inv->cost;
 
+#ifdef STACK_REGS
+  {
+    /* Hoisting constant pool constants into stack regs may cost more than
+       just single register.  On x87, the balance is affected both by the
+       small number of FP registers, and by its register stack organisation,
+       that forces us to add compensation code in and around the loop to
+       shuffle the operands to the top of stack before use, and pop them
+       from the stack after the loop finishes.
+
+       To model this effect, we increase the number of registers needed for
+       stack registers by two: one register push, and one register pop.
+       This usually has the effect that FP constant loads from the constant
+       pool are not moved out of the loop.
+
+       Note that this also means that dependent invariants can not be moved.
+       However, the primary purpose of this pass is to move loop invariant
+       address arithmetic out of loops, and address arithmetic that depends
+       on floating point constants is unlikely to ever occur.  */
+    rtx set = single_set (inv->insn);
+    if (set
+       && IS_STACK_MODE (GET_MODE (SET_SRC (set)))
+       && constant_pool_constant_p (SET_SRC (set)))
+      (*regs_needed) += 2;
+  }
+#endif
+
   EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, depno, bi)
     {
       dep = VEC_index (invariant_p, invariants, depno);
index 1beb4dc16a6ae8ff37791a540426bcb03a1548b4..dc9d3a03c1b6160ea6098725dbcc7a58ae356645 100644 (file)
@@ -1222,6 +1222,12 @@ scan_loop (struct loop *loop, int flags)
              if (GET_MODE_CLASS (GET_MODE (SET_DEST (set))) == MODE_CC
                  && CONSTANT_P (src))
                ;
+#ifdef STACK_REGS
+             /* Don't hoist constant pool constants into stack regs. */
+             else if (IS_STACK_MODE (GET_MODE (SET_SRC (set)))
+                      && constant_pool_constant_p (SET_SRC (set)))
+               ;
+#endif
              /* Don't try to optimize a register that was made
                 by loop-optimization for an inner loop.
                 We don't know its life-span, so we can't compute
@@ -10823,6 +10829,13 @@ load_mems (const struct loop *loop)
          && SCALAR_FLOAT_MODE_P (GET_MODE (mem)))
        loop_info->mems[i].optimize = 0;
 
+#ifdef STACK_REGS
+      /* Don't hoist constant pool constants into stack registers.  */
+      if (IS_STACK_MODE (GET_MODE (mem))
+          && constant_pool_constant_p (mem))
+       loop_info->mems[i].optimize = 0;
+#endif
+
       /* If this MEM is written to, we must be sure that there
         are no reads from another MEM that aliases this one.  */
       if (loop_info->mems[i].optimize && written)
index 45fe6a0b35b34271833bc294ebbc1da92557e851..e35c8058f7e2b9849bf0f27fded78cc86e40db07 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1046,6 +1046,7 @@ extern bool subreg_offset_representable_p (unsigned int, enum machine_mode,
 extern unsigned int subreg_regno (rtx);
 extern unsigned HOST_WIDE_INT nonzero_bits (rtx, enum machine_mode);
 extern unsigned int num_sign_bit_copies (rtx, enum machine_mode);
+extern bool constant_pool_constant_p (rtx);
 
 
 /* 1 if RTX is a subreg containing a reg that is already known to be
index 1390ad985294dce8bbffcdf13faaec7aad153ffd..7c7731b7bb72388d801d8de92a012d2a60b63d52 100644 (file)
@@ -4800,3 +4800,12 @@ init_rtlanal (void)
       non_rtx_starting_operands[i] = first ? first - format : -1;
     }
 }
+\f
+/* Check whether this is a constant pool constant.  */
+bool
+constant_pool_constant_p (rtx x)
+{
+  x = avoid_constant_pool_reference (x);
+  return GET_CODE (x) == CONST_DOUBLE;
+}
+