pa.md (pre_ldwm): Fix bug exposed by recent changes.
authorJeff Law <law@gcc.gnu.org>
Sun, 14 Jan 1996 04:15:10 +0000 (21:15 -0700)
committerJeff Law <law@gcc.gnu.org>
Sun, 14 Jan 1996 04:15:10 +0000 (21:15 -0700)
        * pa.md (pre_ldwm): Fix bug exposed by recent changes.
        Simplify.
        (pre_stwm, post_ldwm, post_stwm): Likewise.
        (HImode and QImode variants): Likewise.
        * pa.c (hppa_expand_prologue): Corresponding changes.
        (hppa_expand_epilogue): Likewise.

        * pa.c (hppa_legitimize_address): Generate more indexing
        address modes.

From-SVN: r10972

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

index ed019cbeb0897ed3e04bbadac572a9ca338db99d..5c00d45bf5dcd14ee5282c19c59b45a234e46820 100644 (file)
@@ -718,10 +718,8 @@ hppa_legitimize_address (x, oldx, mode)
      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.
+     is a REG, SUBREG, SYMBOL_REF or the like.  */
 
-     For 2.5, indexing is also safe for (plus (symbol_ref) (const_int))
-     if the integer is > 0.  */
   if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
       && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
@@ -741,8 +739,64 @@ hppa_legitimize_address (x, oldx, mode)
                                 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
+      && 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))))
+    {
+      rtx regx1, regx2;
+
+      /* Add the two unscaled terms B and C; only force them into registers
+        if it's absolutely necessary.  */
+      regx1 = XEXP (XEXP (x, 0), 1);
+      if (! (GET_CODE (regx1) == REG
+            || (GET_CODE (regx1) == CONST_INT
+                && INT_14_BITS (regx1))))
+       regx1 = force_reg (Pmode, force_operand (XEXP (XEXP (x, 0), 1), 0));
+      
+      regx2 = XEXP (x, 1);
+      if (! (GET_CODE (regx2) == REG
+            || (GET_CODE (regx2) == CONST_INT
+                && INT_14_BITS (regx2))))
+       regx2 = force_reg (Pmode, force_operand (XEXP (x, 1), 0));
+      
+      /* 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
-     special handling.  */
+     special handling.
+
+     This is common enough that we want to try and rearrange the terms
+     so that we can use indexing for these addresses too.  Again, only
+     do the optimization for floatint point modes.  */
 
   if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
@@ -757,7 +811,7 @@ hppa_legitimize_address (x, oldx, mode)
         to access memory, or better yet have the MI parts of the compiler
         handle this.  */
 
-      rtx regx1, regy1, regy2, y;
+      rtx regx1, regx2, regy1, regy2, y;
 
       /* Strip off any CONST.  */
       y = XEXP (x, 1);
@@ -766,11 +820,41 @@ hppa_legitimize_address (x, oldx, mode)
 
       if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
        {
-         regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
-         regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
-         regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
-         regx1 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
-         return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1));
+         /* See if this looks like
+               (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
+             && GET_CODE (XEXP (y, 1)) == CONST_INT
+             && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0)
+           {
+             regx1
+               = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
+                                            / INTVAL (XEXP (XEXP (x, 0), 1))));
+             regx2 = XEXP (XEXP (x, 0), 0);
+             if (GET_CODE (regx2) != REG)
+               regx2 = force_reg (Pmode, force_operand (regx2, 0));
+             regx2 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode,
+                                                regx2, regx1));
+             return force_reg (Pmode,
+                               gen_rtx (PLUS, Pmode,
+                                        gen_rtx (MULT, Pmode, regx2,
+                                                 XEXP (XEXP (x, 0), 1)),
+                                        force_reg (Pmode, XEXP (y, 0))));
+           }
+         else
+           {
+             /* Doesn't look like one we can optimize.  */
+             regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
+             regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
+             regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
+             regx1 = force_reg (Pmode,
+                                gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
+             return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1));
+           }
        }
     }
 
@@ -2077,9 +2161,7 @@ hppa_expand_prologue()
        emit_move_insn (tmpreg, frame_pointer_rtx);
        emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
        if (VAL_14_BITS_P (actual_fsize))
-         emit_insn (gen_post_stwm (stack_pointer_rtx,
-                                   stack_pointer_rtx,
-                                   size_rtx, tmpreg));
+         emit_insn (gen_post_stwm (stack_pointer_rtx, tmpreg, size_rtx));
        else
          {
            /* It is incorrect to store the saved frame pointer at *sp,
@@ -2088,9 +2170,7 @@ hppa_expand_prologue()
               So instead use stwm to store at *sp and post-increment the
               stack pointer as an atomic operation.  Then increment sp to
               finish allocating the new frame.  */
-           emit_insn (gen_post_stwm (stack_pointer_rtx,
-                                     stack_pointer_rtx,
-                                     GEN_INT (64), tmpreg));
+           emit_insn (gen_post_stwm (stack_pointer_rtx, tmpreg, GEN_INT (64)));
            set_reg_plus_d (STACK_POINTER_REGNUM,
                            STACK_POINTER_REGNUM,
                            actual_fsize - 64);
@@ -2209,9 +2289,8 @@ hppa_expand_prologue()
              {
                merge_sp_adjust_with_store = 0;
                emit_insn (gen_post_stwm (stack_pointer_rtx,
-                                         stack_pointer_rtx,
-                                         GEN_INT (-offset),
-                                         gen_rtx (REG, SImode, i)));
+                                         gen_rtx (REG, SImode, i),
+                                         GEN_INT (-offset)));
              }
            else
              store_reg (i, offset, STACK_POINTER_REGNUM);
@@ -2425,16 +2504,16 @@ hppa_expand_epilogue ()
         stream, doing so avoids some very obscure problems.  */
       emit_insn (gen_blockage ());
       set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
-      emit_insn (gen_pre_ldwm (stack_pointer_rtx, stack_pointer_rtx,
-                              GEN_INT (-64), frame_pointer_rtx));
+      emit_insn (gen_pre_ldwm (frame_pointer_rtx, 
+                              stack_pointer_rtx,
+                              GEN_INT (-64)));
     }
   /* If we were deferring a callee register restore, do it now.  */
   else if (! frame_pointer_needed  && merge_sp_adjust_with_load)
-    emit_insn (gen_pre_ldwm (stack_pointer_rtx,
+    emit_insn (gen_pre_ldwm (gen_rtx (REG, SImode,
+                                     merge_sp_adjust_with_load),
                             stack_pointer_rtx,
-                            GEN_INT (- actual_fsize),
-                            gen_rtx (REG, SImode,
-                            merge_sp_adjust_with_load)));
+                            GEN_INT (- actual_fsize)));
   else if (actual_fsize != 0)
     set_reg_plus_d (STACK_POINTER_REGNUM,
                    STACK_POINTER_REGNUM,
index 8b23ea4d9f9a82d2d0f2fead4c8bb62d95c83d28..abaaa36b4d647f61d59deb27ed2ec10abd528d65 100644 (file)
 ;; Load or store with base-register modification.
 
 (define_insn "pre_ldwm"
-  [(set (match_operand:SI 3 "register_operand" "=r")
-       (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "0")
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "=r")
                         (match_operand:SI 2 "pre_cint_operand" ""))))
-   (set (match_operand:SI 0 "register_operand" "=r")
+   (set (match_dup 1)
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
   "*
 {
   if (INTVAL (operands[2]) < 0)
-    return \"ldwm %2(0,%0),%3\";
-  return \"ldws,mb %2(0,%0),%3\";
+    return \"ldwm %2(0,%1),%0\";
+  return \"ldws,mb %2(0,%1),%0\";
 }"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
 (define_insn "pre_stwm"
-  [(set (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "0")
-                        (match_operand:SI 2 "pre_cint_operand" "")))
-       (match_operand:SI 3 "reg_or_0_operand" "rM"))
-   (set (match_operand:SI 0 "register_operand" "=r")
-       (plus:SI (match_dup 1) (match_dup 2)))]
+  [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+                        (match_operand:SI 1 "pre_cint_operand" "")))
+       (match_operand:SI 2 "reg_or_0_operand" "rM"))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0) (match_dup 1)))]
   ""
   "*
 {
-  if (INTVAL (operands[2]) < 0)
-    return \"stwm %r3,%2(0,%0)\";
-  return \"stws,mb %r3,%2(0,%0)\";
+  if (INTVAL (operands[1]) < 0)
+    return \"stwm %r2,%1(0,%0)\";
+  return \"stws,mb %r2,%1(0,%0)\";
 }"
   [(set_attr "type" "store")
    (set_attr "length" "4")])
 
 (define_insn "post_ldwm"
-  [(set (match_operand:SI 3 "register_operand" "r")
-       (mem:SI (match_operand:SI 1 "register_operand" "0")))
-   (set (match_operand:SI 0 "register_operand" "=r")
-       (plus:SI (match_dup 1)
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (mem:SI (match_operand:SI 1 "register_operand" "=r")))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0)
                 (match_operand:SI 2 "post_cint_operand" "")))]
   ""
   "*
 {
   if (INTVAL (operands[2]) > 0)
-    return \"ldwm %2(0,%0),%3\";
-  return \"ldws,ma %2(0,%0),%3\";
+    return \"ldwm %2(0,%1),%0\";
+  return \"ldws,ma %2(0,%1),%1\";
 }"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
 (define_insn "post_stwm"
-  [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
-       (match_operand:SI 3 "reg_or_0_operand" "rM"))
-   (set (match_operand:SI 0 "register_operand" "=r")
-       (plus:SI (match_dup 1)
+  [(set (mem:SI (match_operand:SI 0 "register_operand" "=r"))
+       (match_operand:SI 1 "reg_or_0_operand" "rM"))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0)
                 (match_operand:SI 2 "post_cint_operand" "")))]
   ""
   "*
 {
   if (INTVAL (operands[2]) > 0)
-    return \"stwm %r3,%2(0,%0)\";
-  return \"stws,ma %r3,%2(0,%0)\";
+    return \"stwm %r1,%2(0,%0)\";
+  return \"stws,ma %r1,%2(0,%0)\";
 }"
   [(set_attr "type" "store")
    (set_attr "length" "4")])
    (set_attr "length" "4")])
 
 (define_insn ""
-  [(set (match_operand:HI 3 "register_operand" "=r")
-       (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "0")
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "=r")
                         (match_operand:SI 2 "int5_operand" "L"))))
-   (set (match_operand:SI 0 "register_operand" "=r")
+   (set (match_dup 1)
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ldhs,mb %2(0,%0),%3"
+  "ldhs,mb %2(0,%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
 (define_insn ""
-  [(set (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "0")
-                        (match_operand:SI 2 "int5_operand" "L")))
-       (match_operand:HI 3 "reg_or_0_operand" "rM"))
-   (set (match_operand:SI 0 "register_operand" "=r")
-       (plus:SI (match_dup 1) (match_dup 2)))]
+  [(set (mem:HI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+                        (match_operand:SI 1 "int5_operand" "L")))
+       (match_operand:HI 2 "reg_or_0_operand" "rM"))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0) (match_dup 1)))]
   ""
-  "sths,mb %r3,%2(0,%0)"
+  "sths,mb %r2,%1(0,%0)"
   [(set_attr "type" "store")
    (set_attr "length" "4")])
 
    (set_attr "length" "4")])
 
 (define_insn ""
-  [(set (match_operand:QI 3 "register_operand" "=r")
-       (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "0")
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "=r")
                         (match_operand:SI 2 "int5_operand" "L"))))
-   (set (match_operand:SI 0 "register_operand" "=r")
-       (plus:SI (match_dup 1) (match_dup 2)))]
+   (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ldbs,mb %2(0,%0),%3"
+  "ldbs,mb %2(0,%1),%0"
   [(set_attr "type" "load")
    (set_attr "length" "4")])
 
 (define_insn ""
-  [(set (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "0")
-                        (match_operand:SI 2 "int5_operand" "L")))
-       (match_operand:QI 3 "reg_or_0_operand" "rM"))
-   (set (match_operand:SI 0 "register_operand" "=r")
-       (plus:SI (match_dup 1) (match_dup 2)))]
+  [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+                        (match_operand:SI 1 "int5_operand" "L")))
+       (match_operand:QI 2 "reg_or_0_operand" "rM"))
+   (set (match_dup 0)
+       (plus:SI (match_dup 0) (match_dup 1)))]
   ""
-  "stbs,mb %r3,%2(0,%0)"
+  "stbs,mb %r2,%1(0,%0)"
   [(set_attr "type" "store")
    (set_attr "length" "4")])