diff mbox

[10/15] rs6000: Use rotldi in constant generation

Message ID 1439341904-9345-11-git-send-email-rth@redhat.com
State New
Headers show

Commit Message

Richard Henderson Aug. 12, 2015, 1:11 a.m. UTC
Helps for constants like 0x3300000000000033ul and 0xf5555ffffffffffful.

Cc: David Edelsohn <dje.gcc@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 mbox

Patch

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: