pa.h (EXTRA_CONSTRAINT): Loosen conditions for match of 'Q' and 'T' while reload...
authorJeff Law <law@gcc.gnu.org>
Wed, 2 Oct 1996 23:31:45 +0000 (17:31 -0600)
committerJeff Law <law@gcc.gnu.org>
Wed, 2 Oct 1996 23:31:45 +0000 (17:31 -0600)
        * pa.h (EXTRA_CONSTRAINT): Loosen conditions for match of
        'Q' and 'T' while reload is running.
        * pa/pa.c (hppa_legitimize_address): Rework to generate more
        indexed and scaled indexed addressing.
        * pa/pa.md (scaled indexed store): Add define_splits to undo
        pessimizations created by hppa_legitimize_address for integer
        stores.

From-SVN: r12892

gcc/config/pa/pa.c
gcc/config/pa/pa.h
gcc/config/pa/pa.md

index 9080f97..046f93a 100644 (file)
@@ -771,11 +771,7 @@ hppa_legitimize_address (x, oldx, mode)
       return plus_constant (ptr_reg, offset - newoffset);
     }
 
-  /* Try to arrange things so that indexing modes can be used, but
-     only do so if indexing is safe.
-
-     Indexing is safe when the second operand for the outer PLUS
-     is a REG, SUBREG, SYMBOL_REF or the like.  */
+  /* Handle (plus (mult (a) (shadd_constant)) (b)).  */
 
   if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
@@ -786,66 +782,145 @@ hppa_legitimize_address (x, oldx, mode)
     {
       int val = INTVAL (XEXP (XEXP (x, 0), 1));
       rtx reg1, reg2;
-      reg1 = force_reg (Pmode, force_operand (XEXP (x, 1), 0));
-      reg2 = force_reg (Pmode,
-                       force_operand (XEXP (XEXP (x, 0), 0), 0));
-      return force_reg (Pmode,
-                       gen_rtx (PLUS, Pmode,
-                                gen_rtx (MULT, Pmode, reg2,
-                                         GEN_INT (val)),
-                                reg1));
+
+      reg1 = XEXP (x, 1);
+      if (GET_CODE (reg1) != REG)
+       reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+      reg2 = XEXP (XEXP (x, 0), 0);
+      if (GET_CODE (reg2) != REG)
+        reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+      if (INTVAL (XEXP (XEXP (x, 0), 1)) != GET_MODE_SIZE (mode))
+       {
+         reg2 = force_reg (Pmode, gen_rtx (MULT, Pmode, reg2, GEN_INT (val)));
+         return force_reg (Pmode, gen_rtx (PLUS, Pmode, reg1, reg2));
+       }
+       
+      return force_reg (Pmode, gen_rtx (PLUS, Pmode,
+                                       gen_rtx (MULT, Pmode,
+                                                reg2, GEN_INT (val)),
+                                       reg1));
     }
 
   /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)).
 
      Only do so for floating point modes since this is more speculative
      and we lose if it's an integer store.  */
-  if ((mode == DFmode || mode == SFmode)
-      && GET_CODE (x) == PLUS
+  if (GET_CODE (x) == PLUS
       && GET_CODE (XEXP (x, 0)) == PLUS
       && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
       && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
-      && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))))
+      && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
+      && (mode == SFmode || mode == DFmode))
     {
-      rtx regx1, regx2;
-
-      /* Add the two unscaled terms B and C; if either B or C isn't
-        a register or small constant int, then fail.  */
-      regx1 = XEXP (XEXP (x, 0), 1);
-      if (! (GET_CODE (regx1) == REG
-            || (GET_CODE (regx1) == CONST_INT
-                && INT_14_BITS (regx1))))
-       return orig;
-      
-      regx2 = XEXP (x, 1);
-      if (! (GET_CODE (regx2) == REG
-            || (GET_CODE (regx2) == CONST_INT
-                && INT_14_BITS (regx2))))
+
+      /* First, try and figure out what to use as a base register.  */
+      rtx reg1, reg2, base, idx, orig_base;
+
+      reg1 = XEXP (XEXP (x, 0), 1);
+      reg2 = XEXP (x, 1);
+      base = NULL_RTX;
+      idx = NULL_RTX;
+
+      /* Make sure they're both regs.  If one was a SYMBOL_REF [+ const],
+        then emit_move_sequence will turn on REGNO_POINTER_FLAG so we'll
+        know it's a base register below.  */
+      if (GET_CODE (reg1) != REG)
+       reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+      if (GET_CODE (reg2) != REG)
+       reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+      /* Figure out what the base and index are.  */
+        
+      if (GET_CODE (reg1) == REG
+         && REGNO_POINTER_FLAG (REGNO (reg1)))
+       {
+         base = reg1;
+         orig_base = XEXP (XEXP (x, 0), 1);
+         idx = gen_rtx (PLUS, Pmode,
+                        gen_rtx (MULT, Pmode,
+                                 XEXP (XEXP (XEXP (x, 0), 0), 0),
+                                 XEXP (XEXP (XEXP (x, 0), 0), 1)),
+                        XEXP (x, 1));
+       }
+      else if (GET_CODE (reg2) == REG
+              && REGNO_POINTER_FLAG (REGNO (reg2)))
+       {
+         base = reg2;
+         orig_base = XEXP (x, 1);
+         idx = XEXP (x, 0);
+       }
+
+      if (base == 0)
        return orig;
+
+      /* If the index adds a large constant, try to scale the
+        constant so that it can be loaded with only one insn.  */
+      if (GET_CODE (XEXP (idx, 1)) == CONST_INT
+         && VAL_14_BITS_P (INTVAL (XEXP (idx, 1))
+                           / INTVAL (XEXP (XEXP (idx, 0), 1)))
+         && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0)
+       {
+         /* Divide the CONST_INT by the scale factor, then add it to A.  */
+         int val = INTVAL (XEXP (idx, 1));
+
+         val /= INTVAL (XEXP (XEXP (idx, 0), 1));
+         reg1 = XEXP (XEXP (idx, 0), 0);
+         if (GET_CODE (reg1) != REG)
+           reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+         reg1 = force_reg (Pmode, gen_rtx (PLUS, Pmode, reg1, GEN_INT (val)));
+
+         /* We can now generate a simple scaled indexed address.  */
+         return force_reg (Pmode, gen_rtx (PLUS, Pmode,
+                                           gen_rtx (MULT, Pmode, reg1,
+                                                    XEXP (XEXP (idx, 0), 1)),
+                                           base));
+       }
+
+      /* If B + C is still a valid base register, then add them.  */
+      if (GET_CODE (XEXP (idx, 1)) == CONST_INT
+         && INTVAL (XEXP (idx, 1)) <= 4096
+         && INTVAL (XEXP (idx, 1)) >= -4096)
+       {
+         int val = INTVAL (XEXP (XEXP (idx, 0), 1));
+         rtx reg1, reg2;
+
+         reg1 = force_reg (Pmode, gen_rtx (PLUS, Pmode, base, XEXP (idx, 1)));
+
+         reg2 = XEXP (XEXP (idx, 0), 0);
+         if (GET_CODE (reg2) != CONST_INT)
+           reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+         return force_reg (Pmode, gen_rtx (PLUS, Pmode,
+                                           gen_rtx (MULT, Pmode,
+                                                    reg2, GEN_INT (val)),
+                                           reg1));
+       }
+
+      /* Get the index into a register, then add the base + index and
+        return a register holding the result.  */
+
+      /* First get A into a register.  */
+      reg1 = XEXP (XEXP (idx, 0), 0);
+      if (GET_CODE (reg1) != REG)
+       reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+      /* And get B into a register.  */
+      reg2 = XEXP (idx, 1);
+      if (GET_CODE (reg2) != REG)
+       reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+      reg1 = force_reg (Pmode, gen_rtx (PLUS, Pmode,
+                                       gen_rtx (MULT, Pmode, reg1,
+                                                XEXP (XEXP (idx, 0), 1)),
+                                       reg2));
+
+      /* Add the result to our base register and return.  */
+      return force_reg (Pmode, gen_rtx (PLUS, Pmode, base, reg1));
       
-      /* Add them, make sure the result is in canonical form.  */
-      if (GET_CODE (regx1) == REG)
-       regx1 = force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regx2));
-      else if (GET_CODE (regx2) == REG)
-       regx1 = force_reg (Pmode, gen_rtx (PLUS, Pmode, regx2, regx1));
-      else
-       regx1 = force_reg (Pmode, gen_rtx (PLUS, Pmode,
-                                          force_reg (Pmode, regx1),
-                                          regx2));
-
-      /* Get the term to scale in a register.  */
-      regx2 = XEXP (XEXP (XEXP (x, 0), 0), 0);
-      if (GET_CODE (regx2) != REG)
-       regx2 = force_reg (Pmode, force_operand (regx2, 0));
-
-      /* And make an indexed address.  */
-      regx2 = gen_rtx (PLUS, Pmode,
-                      gen_rtx (MULT, Pmode, regx2,
-                               XEXP (XEXP (XEXP (x, 0), 0), 1)),
-                       regx1);
-
-      /* Return it.  */
-      return force_reg (Pmode, regx2);
     }
 
   /* Uh-oh.  We might have an address for x[n-100000].  This needs
@@ -879,12 +954,42 @@ hppa_legitimize_address (x, oldx, mode)
                (plus (mult (reg) (shadd_const))
                      (const (plus (symbol_ref) (const_int))))
 
-            Where const_int can be divided evenly by shadd_const and
-            added to (reg).  This allows more scaled indexed addresses.  */
-         if ((mode == DFmode || mode == SFmode)
-             && GET_CODE (XEXP (y, 0)) == SYMBOL_REF
+            Where const_int is small.  In that case the const
+            expression is a valid pointer for indexing. 
+
+            If const_int is big, but can be divided evenly by shadd_const
+            and added to (reg).  This allows more scaled indexed addresses.  */
+         if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF
+             && GET_CODE (XEXP (x, 0)) == MULT
              && GET_CODE (XEXP (y, 1)) == CONST_INT
-             && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0)
+             && INTVAL (XEXP (y, 1)) >= -4096
+             && INTVAL (XEXP (y, 1)) <= 4095
+             && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+             && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+           {
+             int val = INTVAL (XEXP (XEXP (x, 0), 1));
+             rtx reg1, reg2;
+
+             reg1 = XEXP (x, 1);
+             if (GET_CODE (reg1) != REG)
+               reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+             reg2 = XEXP (XEXP (x, 0), 0);
+             if (GET_CODE (reg2) != REG)
+               reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+             return force_reg (Pmode, gen_rtx (PLUS, Pmode,
+                                               gen_rtx (MULT, Pmode,
+                                                        reg2, GEN_INT (val)),
+                                               reg1));
+           }
+         else if ((mode == DFmode || mode == SFmode)
+                  && GET_CODE (XEXP (y, 0)) == SYMBOL_REF
+                  && GET_CODE (XEXP (x, 0)) == MULT
+                  && GET_CODE (XEXP (y, 1)) == CONST_INT
+                  && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0
+                  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+                  && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
            {
              regx1
                = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
index f9a3d93..f691025 100644 (file)
@@ -1405,7 +1405,8 @@ extern struct rtx_def *hppa_builtin_saveregs ();
   ((C) == 'Q' ?                                                \
    (IS_RELOADING_PSEUDO_P (OP)                         \
     || (GET_CODE (OP) == MEM                           \
-       && memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
+       && (memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
+           || reload_in_progress)                      \
        && ! symbolic_memory_operand (OP, VOIDmode)     \
         && !(GET_CODE (XEXP (OP, 0)) == PLUS           \
             && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT\
@@ -1416,7 +1417,8 @@ extern struct rtx_def *hppa_builtin_saveregs ();
       && (GET_CODE (XEXP (XEXP (OP, 0), 0)) == MULT    \
          || GET_CODE (XEXP (XEXP (OP, 0), 1)) == MULT) \
       && (move_operand (OP, GET_MODE (OP))             \
-         || memory_address_p (GET_MODE (OP), XEXP (OP, 0))))\
+         || memory_address_p (GET_MODE (OP), XEXP (OP, 0))\
+         || reload_in_progress))                       \
    : ((C) == 'T' ?                                     \
       (GET_CODE (OP) == MEM                            \
        /* Using DFmode forces only short displacements \
index de3b001..d881956 100644 (file)
    (set (match_dup 0) (lo_sum:SI (match_dup 2) (match_dup 1)))]
   "")
 
+;; hppa_legitimize_address goes to a great deal of trouble to
+;; create addresses which use indexing.  In some cases, this
+;; is a lose because there isn't any store instructions which
+;; allow indexed addresses (with integer register source).
+;;
+;; These define_splits try to turn a 3 insn store into
+;; a 2 insn store with some creative RTL rewriting.
+(define_split
+  [(set (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
+                              (match_operand:SI 1 "shadd_operand" ""))
+                  (plus:SI (match_operand:SI 2 "register_operand" "")
+                           (match_operand:SI 3 "const_int_operand" ""))))
+       (match_operand:SI 4 "register_operand" ""))
+   (clobber (match_operand:SI 5 "register_operand" ""))]
+  ""
+  [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+                              (match_dup 2)))
+   (set (mem:SI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
+  "")
+
+(define_split
+  [(set (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
+                              (match_operand:SI 1 "shadd_operand" ""))
+                  (plus:SI (match_operand:SI 2 "register_operand" "")
+                           (match_operand:SI 3 "const_int_operand" ""))))
+       (match_operand:HI 4 "register_operand" ""))
+   (clobber (match_operand:SI 5 "register_operand" ""))]
+  ""
+  [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+                              (match_dup 2)))
+   (set (mem:HI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
+  "")
+
+(define_split
+  [(set (mem:QI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
+                              (match_operand:SI 1 "shadd_operand" ""))
+                  (plus:SI (match_operand:SI 2 "register_operand" "")
+                           (match_operand:SI 3 "const_int_operand" ""))))
+       (match_operand:QI 4 "register_operand" ""))
+   (clobber (match_operand:SI 5 "register_operand" ""))]
+  ""
+  [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+                              (match_dup 2)))
+   (set (mem:QI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
+  "")
+
 (define_expand "movhi"
   [(set (match_operand:HI 0 "general_operand" "")
        (match_operand:HI 1 "general_operand" ""))]