Helps for constants like 0x3300000000000033ul and 0xf5555ffffffffffful.

Cc: David Edelsohn <dje....@gmail.com>
---
        * config/rs6000/rs6000.c (genimm_ppc::exam_rotl): New.
        (genimm_ppc::exam_search): Use it.
        (genimm_ppc::generate): Handle ROTATE.
---
 gcc/config/rs6000/rs6000.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 40b29b0..f5d6fdf 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -8059,6 +8059,7 @@ struct genimm_ppc : genimm_base <rtx_code, 5>
   bool exam_simple (HOST_WIDE_INT c, machine_mode, int budget);
   bool exam_sub (HOST_WIDE_INT c, int budget);
   bool exam_mask (HOST_WIDE_INT c, HOST_WIDE_INT mask, int sub_budget);
+  bool exam_rotl (HOST_WIDE_INT c, int bits);
   bool exam_search (HOST_WIDE_INT c, int budget);
   void exam_full (HOST_WIDE_INT c);
   void generate (rtx dest, machine_mode mode) const;
@@ -8137,6 +8138,24 @@ genimm_ppc::exam_mask (HOST_WIDE_INT c, HOST_WIDE_INT 
mask, int sub_budget)
   return false;
 }
 
+/* If we're able to rotate a 16-bit signed constant to form C,
+   return true and fill in the recipe.  */
+
+bool
+genimm_ppc::exam_rotl (HOST_WIDE_INT c, int bits)
+{
+  HOST_WIDE_INT sub_c = (unsigned HOST_WIDE_INT)c >> bits;
+  sub_c |= (unsigned HOST_WIDE_INT)c << (64 - bits);
+
+  if ((unsigned HOST_WIDE_INT)sub_c + 0x8000 < 0x10000)
+    {
+      set0 (sub_c);
+      opN (ROTATE, bits);
+      return true;
+    }
+  return false;
+}
+
 /* The body of the recursive search for C within BUDGET.
    We've already failed exam_simple.  */
 
@@ -8212,6 +8231,35 @@ genimm_ppc::exam_search (HOST_WIDE_INT c, int budget)
        }
     }
 
+  /* Rotate the constant left.  Because of combinatorial complexity,
+     only consider this with a 16-bit base, which means there's no
+     point in considering this high in the search tree.  */
+  if (sub_budget == 1)
+    {
+      /* The 16-bit signed constant upon which we are going to base
+        the rotate can have no more than 15 bits set as a positive
+        or no less than 49 bits set as a negative.  */
+      bits = popcount_hwi (c);
+      if (bits <= 15)
+       {
+         /* The constant must be positive, and it must have failed
+            the simpler shift test above.  Therefore, any success
+            will be with a rotate of more than 48.  */
+         bits = ctz_hwi (c & ~ HOST_WIDE_INT_UC (0x7fff));
+         if (bits > 48 && exam_rotl (c, bits))
+           return true;
+       }
+      else if (bits > 48)
+       {
+         /* The constant must be negative, and it must have rotated
+            copies of the sign bit around into the low order bits.
+            Those copies must be the number of rotations.  */
+         bits = ctz_hwi (~c);
+         if (exam_rotl (c, bits))
+           return true;
+       }
+    }
+
   return false;
 }
 
@@ -8255,6 +8303,9 @@ genimm_ppc::generate (rtx dest, machine_mode mode) const
        case SET:
          x = op2;
          break;
+       case ROTATE:
+         gcc_assert (mode == DImode);
+         /* FALLTHRU */
        case PLUS:
        case AND:
        case IOR:
-- 
2.4.3

Reply via email to