This has been pending in my queue for a while.   Just keeps getting pushed down.

As the PR notes, I added a patch a while back that could reassociate an xor operation out of certain sequences which in turn would allow the sequence to be recognized as rotate+xor.

That patch did not handle 128 bit integers as I used the HOST_WIDE_INT interfaces.  Similarly it didn't handle BitInt.

This patch changes it to use the wi:: interfaces which fix the code generation issue on aarch64 with int128 and allow the sequence to safely fire for BitInt.  The recommendations for adjustment were Jakub's.

Bootstrapped and regression tested on x86, aarch64 and riscv. Crosses also tested without regressions, though I don't think they provide meaningfully more coverage for int128 and BitInt.

OK for the trunk?

Jeff
diff --git a/gcc/match.pd b/gcc/match.pd
index 54cad1cd2bc..d0ea9153c6b 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -13319,8 +13319,7 @@ and,
    (if (type_has_mode_precision_p (type)
 	&& tree_fits_uhwi_p (@1)
 	&& tree_fits_uhwi_p (@3)
-	&& tree_fits_uhwi_p (@4)
-	&& ((~((HOST_WIDE_INT_1U << tree_to_uhwi (@1)) - 1)) & tree_to_uhwi (@4)) == 0
+	&& (wi::mask (tree_to_uhwi (@1), true, TYPE_PRECISION (type)) & wi::to_wide (@4)) == 0
         && (tree_to_uhwi (@1) + tree_to_uhwi (@3)) == TYPE_PRECISION (type)
         && TYPE_UNSIGNED (type)
         && @0 == @2)
@@ -13333,9 +13332,8 @@ and,
 	     (rshift @3 INTEGER_CST@4))
    (if (type_has_mode_precision_p (type)
 	&& tree_fits_uhwi_p (@1)
-	&& tree_fits_uhwi_p (@2)
 	&& tree_fits_uhwi_p (@4)
-	&& (((((HOST_WIDE_INT_1U << tree_to_uhwi (@1)) - 1)) & tree_to_uhwi (@2)) == 0)
+	&& ((wi::mask (tree_to_uhwi (@1), false, TYPE_PRECISION (type)) & wi::to_wide (@2)) == 0)
         && (tree_to_uhwi (@1) + tree_to_uhwi (@4)) == TYPE_PRECISION (type)
         && TYPE_UNSIGNED (type)
         && @0 == @3)
diff --git a/gcc/testsuite/gcc.dg/torture/pr126462.c b/gcc/testsuite/gcc.dg/torture/pr126462.c
new file mode 100644
index 00000000000..d32ba6f04ed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr126462.c
@@ -0,0 +1,26 @@
+/* { dg-do run { target int128 } } */
+
+typedef unsigned __int128 u128;
+
+__attribute__((noipa)) u128
+f (u128 x)
+{
+  return ((x << 64) ^ (u128) 1) | (x >> 64);
+}
+
+__attribute__((noipa)) u128
+g (u128 x)
+{
+  return ((x << 96) ^ ((u128) 1 << 32)) | (x >> 32);
+}
+
+int
+main (void)
+{
+  u128 x = (u128) 1 << 64;
+  if (f (x) != 1)
+    __builtin_abort ();
+  if (g (x) != ((u128) 1 << 32))
+    __builtin_abort ();
+  return 0;
+}

Reply via email to