]> gcc.gnu.org Git - gcc.git/commitdiff
hppa: PR middle-end/87256: Improved hppa_rtx_costs avoids synth_mult madness.
authorRoger Sayle <roger@nextmovesoftware.com>
Wed, 26 Aug 2020 06:21:08 +0000 (07:21 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Wed, 26 Aug 2020 06:23:28 +0000 (07:23 +0100)
Backport from master:

2020-08-26  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
PR middle-end/87256
* config/pa/pa.c (hppa_rtx_costs_shadd_p): New helper function
to check for coefficients supported by shNadd and shladd,l.
(hppa_rtx_costs):  Rewrite to avoid using estimates based upon
FACTOR and enable recursing deeper into RTL expressions.
* config/pa/pa.md (shd_internal): Fix define_expand to provide
gen_shd_internal.

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

index 711234e597a5a4064ac03d70f0aa77c995ecce29..55185aab65044e67bcf430af635f17a0713222e6 100644 (file)
@@ -1492,6 +1492,33 @@ hppa_address_cost (rtx X, machine_mode mode ATTRIBUTE_UNUSED,
     }
 }
 
+/* Return true if X represents a (possibly non-canonical) shNadd pattern.
+   The machine mode of X is known to be SImode or DImode.  */
+
+static bool
+hppa_rtx_costs_shadd_p (rtx x)
+{
+  if (GET_CODE (x) != PLUS
+      || !REG_P (XEXP (x, 1)))
+    return false;
+  rtx op0 = XEXP (x, 0);
+  if (GET_CODE (op0) == ASHIFT
+      && CONST_INT_P (XEXP (op0, 1))
+      && REG_P (XEXP (op0, 0)))
+    {
+      unsigned HOST_WIDE_INT x = UINTVAL (XEXP (op0, 1));
+      return x == 1 || x == 2 || x == 3;
+    }
+  if (GET_CODE (op0) == MULT
+      && CONST_INT_P (XEXP (op0, 1))
+      && REG_P (XEXP (op0, 0)))
+    {
+      unsigned HOST_WIDE_INT x = UINTVAL (XEXP (op0, 1));
+      return x == 2 || x == 4 || x == 8;
+    }
+  return false;
+}
+
 /* Compute a (partial) cost for rtx X.  Return true if the complete
    cost has been computed, and false if subexpressions should be
    scanned.  In either case, *TOTAL contains the cost result.  */
@@ -1499,15 +1526,16 @@ hppa_address_cost (rtx X, machine_mode mode ATTRIBUTE_UNUSED,
 static bool
 hppa_rtx_costs (rtx x, machine_mode mode, int outer_code,
                int opno ATTRIBUTE_UNUSED,
-               int *total, bool speed ATTRIBUTE_UNUSED)
+               int *total, bool speed)
 {
-  int factor;
   int code = GET_CODE (x);
 
   switch (code)
     {
     case CONST_INT:
-      if (INTVAL (x) == 0)
+      if (outer_code == SET)
+       *total = COSTS_N_INSNS (1);
+      else if (INTVAL (x) == 0)
        *total = 0;
       else if (INT_14_BITS (x))
        *total = 1;
@@ -1530,32 +1558,35 @@ hppa_rtx_costs (rtx x, machine_mode mode, int outer_code,
          && outer_code != SET)
        *total = 0;
       else
-        *total = 8;
+       *total = 8;
       return true;
 
     case MULT:
       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
        {
          *total = COSTS_N_INSNS (3);
-         return true;
        }
-
-      /* A mode size N times larger than SImode needs O(N*N) more insns.  */
-      factor = GET_MODE_SIZE (mode) / 4;
-      if (factor == 0)
-       factor = 1;
-
-      if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT)
-       *total = factor * factor * COSTS_N_INSNS (8);
+      else if (mode == DImode)
+       {
+         if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT)
+           *total = COSTS_N_INSNS (32);
+         else
+           *total = COSTS_N_INSNS (80);
+       }
       else
-       *total = factor * factor * COSTS_N_INSNS (20);
-      return true;
+       {
+         if (TARGET_PA_11 && !TARGET_DISABLE_FPREGS && !TARGET_SOFT_FLOAT)
+           *total = COSTS_N_INSNS (8);
+         else
+           *total = COSTS_N_INSNS (20);
+       }
+      return REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1));
 
     case DIV:
       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
        {
          *total = COSTS_N_INSNS (14);
-         return true;
+         return false;
        }
       /* FALLTHRU */
 
@@ -1563,34 +1594,107 @@ hppa_rtx_costs (rtx x, machine_mode mode, int outer_code,
     case MOD:
     case UMOD:
       /* A mode size N times larger than SImode needs O(N*N) more insns.  */
-      factor = GET_MODE_SIZE (mode) / 4;
-      if (factor == 0)
-       factor = 1;
-
-      *total = factor * factor * COSTS_N_INSNS (60);
-      return true;
+      if (mode == DImode)
+       *total = COSTS_N_INSNS (240);
+      else
+       *total = COSTS_N_INSNS (60);
+      return REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1));
 
     case PLUS: /* this includes shNadd insns */
     case MINUS:
       if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+       *total = COSTS_N_INSNS (3);
+      else if (mode == DImode)
        {
-         *total = COSTS_N_INSNS (3);
-         return true;
+         if (TARGET_64BIT)
+           {
+             *total = COSTS_N_INSNS (1);
+             /* Handle shladd,l instructions.  */
+             if (hppa_rtx_costs_shadd_p (x))
+               return true;
+           }
+         else
+           *total = COSTS_N_INSNS (2);
        }
-
-      /* A size N times larger than UNITS_PER_WORD needs N times as
-        many insns, taking N times as long.  */
-      factor = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
-      if (factor == 0)
-       factor = 1;
-      *total = factor * COSTS_N_INSNS (1);
-      return true;
+      else
+       {
+         *total = COSTS_N_INSNS (1);
+         /* Handle shNadd instructions.  */
+         if (hppa_rtx_costs_shadd_p (x))
+           return true;
+       }
+      return REG_P (XEXP (x, 0))
+            && (REG_P (XEXP (x, 1))
+                || CONST_INT_P (XEXP (x, 1)));
 
     case ASHIFT:
+      if (mode == DImode)
+       {
+         if (TARGET_64BIT)
+           *total = COSTS_N_INSNS (3);
+         else if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1)))
+           {
+             *total = COSTS_N_INSNS (2);
+             return true;
+           }
+         else if (speed)
+           *total = COSTS_N_INSNS (13);
+         else
+           *total = COSTS_N_INSNS (18);
+       }
+      else if (TARGET_64BIT)
+       *total = COSTS_N_INSNS (4);
+      else
+       *total = COSTS_N_INSNS (2);
+      return REG_P (XEXP (x, 0))
+            && (REG_P (XEXP (x, 1))
+                || CONST_INT_P (XEXP (x, 1)));
+
     case ASHIFTRT:
+      if (mode == DImode)
+       {
+         if (TARGET_64BIT)
+           *total = COSTS_N_INSNS (3);
+         else if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1)))
+           {
+             *total = COSTS_N_INSNS (2);
+             return true;
+           }
+         else if (speed)
+           *total = COSTS_N_INSNS (14);
+         else
+           *total = COSTS_N_INSNS (19);
+       }
+      else if (TARGET_64BIT)
+       *total = COSTS_N_INSNS (4);
+      else
+       *total = COSTS_N_INSNS (2);
+      return REG_P (XEXP (x, 0))
+            && (REG_P (XEXP (x, 1))
+                || CONST_INT_P (XEXP (x, 1)));
+
     case LSHIFTRT:
-      *total = COSTS_N_INSNS (1);
-      return true;
+      if (mode == DImode)
+       {
+         if (TARGET_64BIT)
+           *total = COSTS_N_INSNS (2);
+         else if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1)))
+           {
+             *total = COSTS_N_INSNS (2);
+             return true;
+           }
+         else if (speed)
+           *total = COSTS_N_INSNS (12);
+         else
+           *total = COSTS_N_INSNS (15);
+       }
+      else if (TARGET_64BIT)
+       *total = COSTS_N_INSNS (3);
+      else
+       *total = COSTS_N_INSNS (2);
+      return REG_P (XEXP (x, 0))
+            && (REG_P (XEXP (x, 1))
+                || CONST_INT_P (XEXP (x, 1)));
 
     default:
       return false;
index e7b763555271717bb8da73af1c4a588f7e77317e..713ff175445cccb4ebe9a517c1164d8412028d59 100644 (file)
     {
       if (REG_P (operands[0]) && GET_CODE (operands[2]) == CONST_INT)
        {
-          unsigned HOST_WIDE_INT shift = UINTVAL (operands[2]);
+         unsigned HOST_WIDE_INT shift = UINTVAL (operands[2]);
          if (shift >= 1 && shift <= 31)
            {
              rtx dst = operands[0];
              rtx src = force_reg (DImode, operands[1]);
              emit_insn (gen_shd_internal (gen_highpart (SImode, dst),
-                                          gen_highpart (SImode, src),
-                                          GEN_INT (32-shift),
                                           gen_lowpart (SImode, src),
+                                          GEN_INT (32-shift),
+                                          gen_highpart (SImode, src),
                                           GEN_INT (shift)));
              emit_insn (gen_ashlsi3 (gen_lowpart (SImode, dst),
                                      gen_lowpart (SImode, src),
This page took 0.088983 seconds and 5 git commands to generate.