The insns generated by hppa_legitimize_address for shift-add calculations are never directly inserted into a MEM -- they're loaded into a register first which may or may not be later combined into a memory reference.

So... We should be using the ASHIFT form rather than the MULT form for insns created by hppa_legitimize_address.

AFAICT hppa_legitimize_address is always passed in the MULT form; however, I've taken this opportunity to have it accept either form.

My recollection is a lot of this code was to improve the results of f2c translated Fortran code (yes, it's that old and largely unchanged). Thus, it's no great surprise that while the code is being called I can't show any difference in the final assembly output with this code enabled/disabled across my 300+ files from GCC itself. So I'm not including any new tests with this change (I've already spent far longer on this than I can reasonably justify :-)

Installed on the trunk after verifying my 300+ files generate the same code before/after this change on the PA and testing hppa.exp


Jeff


        * pa.c (mem_shadd_or_shadd_rtx_p): New function factored out
        of hppa_legitimize_address to handle both forms of a multiply
        by 2, 4 or 8.
        (hppa_legitimize_address): Use mem_shadd_or_shadd_rtx_p.
        Always generate the ASHIFT variant as the result is not directly
        used in a MEM.  Update comments and refactor slightly to improve
        readability.

        
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index f99cf33..090eeb4 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -997,6 +997,23 @@ legitimize_tls_address (rtx addr)
   return ret;
 }
 
+/* Helper for hppa_legitimize_address.  Given X, return true if it
+   is a left shift by 1, 2 or 3 positions or a multiply by 2, 4 or 8.
+
+   This respectively represent canonical shift-add rtxs or scaled
+   memory addresses.  */
+static bool
+mem_shadd_or_shadd_rtx_p (rtx x)
+{
+  return ((GET_CODE (x) == ASHIFT
+          || GET_CODE (x) == MULT)
+         && GET_CODE (XEXP (x, 1)) == CONST_INT
+         && ((GET_CODE (x) == ASHIFT
+              && pa_shadd_constant_p (INTVAL (XEXP (x, 1))))
+             || (GET_CODE (x) == MULT
+                 && pa_mem_shadd_constant_p (INTVAL (XEXP (x, 1))))));
+}
+
 /* Try machine-dependent ways of modifying an illegitimate address
    to be legitimate.  If we find one, return the new, valid address.
    This macro is used in only one place: `memory_address' in explow.c.
@@ -1042,6 +1059,13 @@ legitimize_tls_address (rtx addr)
    manner if Y is 2, 4, or 8.  (allows more shadd insns and shifted indexed
    addressing modes to be used).
 
+   Note that the addresses passed into hppa_legitimize_address always
+   come from a MEM, so we only have to match the MULT form on incoming
+   addresses.  But to be future proof we also match the ASHIFT form.
+
+   However, this routine always places those shift-add sequences into
+   registers, so we have to generate the ASHIFT form as our output.
+
    Put X and Z into registers.  Then put the entire expression into
    a register.  */
 
@@ -1138,18 +1162,21 @@ hppa_legitimize_address (rtx x, rtx oldx 
ATTRIBUTE_UNUSED,
       return plus_constant (Pmode, ptr_reg, offset - newoffset);
     }
 
-  /* Handle (plus (mult (a) (shadd_constant)) (b)).  */
+  /* Handle (plus (mult (a) (mem_shadd_constant)) (b)).  */
 
-  if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
-      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-      && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
+  if (GET_CODE (x) == PLUS
+      && mem_shadd_or_shadd_rtx_p (XEXP (x, 0))
       && (OBJECT_P (XEXP (x, 1))
          || GET_CODE (XEXP (x, 1)) == SUBREG)
       && GET_CODE (XEXP (x, 1)) != CONST)
     {
-      int val = INTVAL (XEXP (XEXP (x, 0), 1));
-      rtx reg1, reg2;
+      /* If we were given a MULT, we must fix the constant
+        as we're going to create the ASHIFT form.  */
+      int shift_val = INTVAL (XEXP (XEXP (x, 0), 1));
+      if (GET_CODE (XEXP (x, 0)) == MULT)
+       shift_val = exact_log2 (shift_val);
 
+      rtx reg1, reg2;
       reg1 = XEXP (x, 1);
       if (GET_CODE (reg1) != REG)
        reg1 = force_reg (Pmode, force_operand (reg1, 0));
@@ -1158,26 +1185,30 @@ hppa_legitimize_address (rtx x, rtx oldx 
ATTRIBUTE_UNUSED,
       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));
+      return force_reg (Pmode,
+                       gen_rtx_PLUS (Pmode,
+                                     gen_rtx_ASHIFT (Pmode, reg2,
+                                                     GEN_INT (shift_val)),
+                                     reg1));
     }
 
-  /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)).
+  /* Similarly for (plus (plus (mult (a) (mem_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 (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
-      && pa_shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
+      && mem_shadd_or_shadd_rtx_p (XEXP (XEXP (x, 0), 0))
       && (mode == SFmode || mode == DFmode))
     {
+      int shift_val = INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1));
+
+      /* If we were given a MULT, we must fix the constant
+        as we're going to create the ASHIFT form.  */
+      if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT)
+       shift_val = exact_log2 (shift_val);
 
-      /* First, try and figure out what to use as a base register.  */
+      /* Try and figure out what to use as a base register.  */
       rtx reg1, reg2, base, idx;
 
       reg1 = XEXP (XEXP (x, 0), 1);
@@ -1201,9 +1232,9 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
        {
          base = reg1;
          idx = gen_rtx_PLUS (Pmode,
-                             gen_rtx_MULT (Pmode,
-                                           XEXP (XEXP (XEXP (x, 0), 0), 0),
-                                           XEXP (XEXP (XEXP (x, 0), 0), 1)),
+                             gen_rtx_ASHIFT (Pmode,
+                                             XEXP (XEXP (XEXP (x, 0), 0), 0),
+                                             GEN_INT (shift_val)),
                              XEXP (x, 1));
        }
       else if (GET_CODE (reg2) == REG
@@ -1225,8 +1256,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
        {
          /* Divide the CONST_INT by the scale factor, then add it to A.  */
          int val = INTVAL (XEXP (idx, 1));
+         val /= (1 << shift_val);
 
-         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));
@@ -1237,8 +1268,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
          return
            force_reg
              (Pmode, gen_rtx_PLUS (Pmode,
-                                   gen_rtx_MULT (Pmode, reg1,
-                                                 XEXP (XEXP (idx, 0), 1)),
+                                   gen_rtx_ASHIFT (Pmode, reg1,
+                                                   GEN_INT (shift_val)),
                                    base));
        }
 
@@ -1247,7 +1278,6 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
          && 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)));
@@ -1256,11 +1286,11 @@ hppa_legitimize_address (rtx x, rtx oldx 
ATTRIBUTE_UNUSED,
          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));
+         return force_reg (Pmode,
+                           gen_rtx_PLUS (Pmode,
+                                         gen_rtx_ASHIFT (Pmode, reg2,
+                                                         GEN_INT (shift_val)),
+                                         reg1));
        }
 
       /* Get the index into a register, then add the base + index and
@@ -1278,8 +1308,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
 
       reg1 = force_reg (Pmode,
                        gen_rtx_PLUS (Pmode,
-                                     gen_rtx_MULT (Pmode, reg1,
-                                                   XEXP (XEXP (idx, 0), 1)),
+                                     gen_rtx_ASHIFT (Pmode, reg1,
+                                                     GEN_INT (shift_val)),
                                      reg2));
 
       /* Add the result to our base register and return.  */
@@ -1315,7 +1345,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
       if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
        {
          /* See if this looks like
-               (plus (mult (reg) (shadd_const))
+               (plus (mult (reg) (mem_shadd_const))
                      (const (plus (symbol_ref) (const_int))))
 
             Where const_int is small.  In that case the const
@@ -1324,14 +1354,18 @@ hppa_legitimize_address (rtx x, rtx oldx 
ATTRIBUTE_UNUSED,
             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
+             && mem_shadd_or_shadd_rtx_p (XEXP (x, 0))
              && GET_CODE (XEXP (y, 1)) == CONST_INT
              && INTVAL (XEXP (y, 1)) >= -4096
-             && INTVAL (XEXP (y, 1)) <= 4095
-             && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-             && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+             && INTVAL (XEXP (y, 1)) <= 4095)
            {
-             int val = INTVAL (XEXP (XEXP (x, 0), 1));
+             int shift_val = INTVAL (XEXP (XEXP (x, 0), 1));
+
+             /* If we were given a MULT, we must fix the constant
+                as we're going to create the ASHIFT form.  */
+             if (GET_CODE (XEXP (x, 0)) == MULT)
+               shift_val = exact_log2 (shift_val);
+
              rtx reg1, reg2;
 
              reg1 = XEXP (x, 1);
@@ -1342,21 +1376,27 @@ hppa_legitimize_address (rtx x, rtx oldx 
ATTRIBUTE_UNUSED,
              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));
+             return
+               force_reg (Pmode,
+                          gen_rtx_PLUS (Pmode,
+                                        gen_rtx_ASHIFT (Pmode,
+                                                        reg2,
+                                                        GEN_INT (shift_val)),
+                                        reg1));
            }
          else if ((mode == DFmode || mode == SFmode)
                   && GET_CODE (XEXP (y, 0)) == SYMBOL_REF
-                  && GET_CODE (XEXP (x, 0)) == MULT
+                  && mem_shadd_or_shadd_rtx_p (XEXP (x, 0))
                   && 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
-                  && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+                  && INTVAL (XEXP (y, 1)) % (1 << INTVAL (XEXP (XEXP (x, 0), 
1))) == 0)
            {
+             int shift_val = INTVAL (XEXP (XEXP (x, 0), 1));
+
+             /* If we were given a MULT, we must fix the constant
+                as we're going to create the ASHIFT form.  */
+             if (GET_CODE (XEXP (x, 0)) == MULT)
+               shift_val = exact_log2 (shift_val);
+
              regx1
                = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
                                             / INTVAL (XEXP (XEXP (x, 0), 1))));
@@ -1368,8 +1408,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
              return
                force_reg (Pmode,
                           gen_rtx_PLUS (Pmode,
-                                        gen_rtx_MULT (Pmode, regx2,
-                                                      XEXP (XEXP (x, 0), 1)),
+                                        gen_rtx_ASHIFT (Pmode, regx2,
+                                                        GEN_INT (shift_val)),
                                         force_reg (Pmode, XEXP (y, 0))));
            }
          else if (GET_CODE (XEXP (y, 1)) == CONST_INT

Reply via email to