Bootstrapped and regtested on powerpc64le-linux-gnu {P10,P9}
powerpc64-linux-gnu {P8, P7} and X86.  OK for master?

gcc/ChangeLog:

        PR 90323
        * simplify-rtx.c (simplify_context::simplify_binary_operation_1): Relax
        C from constant to constant or reg.

gcc/testsuite/ChangeLog:

        * gcc.target/powerpc/pr90323.c: New test.
---
 gcc/simplify-rtx.c                         | 11 ++++----
 gcc/testsuite/gcc.target/powerpc/pr90323.c | 33 ++++++++++++++++++++++
 2 files changed, 39 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/pr90323.c

diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index a060f1bbce0..be240b2979e 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -3581,12 +3581,13 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
            }
        }
 
-      /* If we have (xor (and (xor A B) C) A) with C a constant we can instead
-        do (ior (and A ~C) (and B C)) which is a machine instruction on some
-        machines, and also has shorter instruction path length.  */
+      /* If we have (xor (and (xor A B) C) A) with C a constant or register
+        we can instead do (ior (and A ~C) (and B C)) which is a machine
+        instruction on some machines, and also has shorter instruction path
+        length.  */
       if (GET_CODE (op0) == AND
          && GET_CODE (XEXP (op0, 0)) == XOR
-         && CONST_INT_P (XEXP (op0, 1))
+         && (CONST_INT_P (XEXP (op0, 1)) || REG_P (XEXP (op0, 1)))
          && rtx_equal_p (XEXP (XEXP (op0, 0), 0), trueop1))
        {
          rtx a = trueop1;
@@ -3600,7 +3601,7 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
       /* Similarly, (xor (and (xor A B) C) B) as (ior (and A C) (and B ~C))  */
       else if (GET_CODE (op0) == AND
          && GET_CODE (XEXP (op0, 0)) == XOR
-         && CONST_INT_P (XEXP (op0, 1))
+         && (CONST_INT_P (XEXP (op0, 1)) || REG_P (XEXP (op0, 1)))
          && rtx_equal_p (XEXP (XEXP (op0, 0), 1), trueop1))
        {
          rtx a = XEXP (XEXP (op0, 0), 0);
diff --git a/gcc/testsuite/gcc.target/powerpc/pr90323.c 
b/gcc/testsuite/gcc.target/powerpc/pr90323.c
new file mode 100644
index 00000000000..e80609c477f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr90323.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <altivec.h>
+#include <stdio.h>
+volatile vector unsigned orig = {0xebebebeb, 0x34343434, 0x76767676, 
0x12121212};
+volatile vector unsigned mask = {0xffffffff, 0, 0xffffffff, 0};
+volatile vector unsigned fill = {0xfefefefe, 0xaaaaaaaa, 0xbbbbbbbb, 
0xcccccccc};
+volatile vector unsigned expected = {0xfefefefe, 0x34343434, 0xbbbbbbbb, 
0x12121212};
+__attribute__((noinline)) vector unsigned
+without_sel(vector unsigned l, vector unsigned r, vector unsigned mask) {
+  l = l & ~mask;
+  l |= mask & r;
+  return l;
+}
+
+__attribute__((noinline)) vector unsigned
+with_sel(vector unsigned l, vector unsigned r, vector unsigned mask) {
+  return vec_sel(l, r, mask);
+}
+
+int main() {
+  vector unsigned res1 = without_sel(orig, fill, mask);
+  vector unsigned res2 = with_sel(orig, fill, mask);
+  if (!vec_all_eq(res1, expected))
+    printf("error1\n");
+  if (!vec_all_eq(res2, expected))
+    printf("error2\n");
+  return 0;
+}
+
+
+/* { dg-final { scan-assembler-times {\mxxsel\M} 2 } } */
-- 
2.27.0

Reply via email to