}
}
+ /* Optimize (cmp (and/ior x C1) C2) depending on the CMP and C1 and C2's
+ relationship. */
+ if ((op0code == AND || op0code == IOR)
+ && CONST_INT_P (op1)
+ && CONST_INT_P (XEXP (op0, 1)))
+ {
+ unsigned HOST_WIDE_INT c1 = UINTVAL (XEXP (op0, 1));
+ unsigned HOST_WIDE_INT c2 = UINTVAL (op1);
+
+ /* For AND operations:
+ - (x & c1) == c2 when some bits are set in c2 but not in c1 -> false
+ - (x & c1) != c2 when some bits are set in c2 but not in c1 -> true
+ - (x & c1) >= c2 when c1 is less than c2 -> false
+ - (x & c1) < c2 when c1 is less than c2 -> true
+ - (x & c1) > c2 when c1 is less than or equal to c2 -> false
+ - (x & c1) <= c2 when c1 is less than or equal to c2 -> true
+
+ For IOR operations:
+ - (x | c1) == c2 when some bits are set in c1 but not in c2 -> false
+ - (x | c1) != c2 when some bits are set in c1 but not in c2 -> true
+ - (x | c1) <= c2 when c1 is greater than c2 -> false
+ - (x | c1) > c2 when c1 is greater than c2 -> true
+ - (x | c1) < c2 when c1 is greater than or equal to c2 -> false
+ - (x | c1) >= c2 when c1 is greater than or equal to c2 -> true */
+ if ((op0code == AND
+ && ((code == EQ && (c1 & c2) != c2)
+ || (code == GEU && c1 < c2)
+ || (code == GTU && c1 <= c2)))
+ || ((op0code == IOR
+ && ((code == EQ && (c1 & c2) != c1)
+ || (code == LEU && c1 > c2)
+ || (code == LTU && c1 >= c2)))))
+ return const0_rtx;
+
+ if ((op0code == AND
+ && ((code == NE && (c1 & c2) != c2)
+ || (code == LTU && c1 < c2)
+ || (code == LEU && c1 <= c2)))
+ || ((op0code == IOR
+ && ((code == NE && (c1 & c2) != c1)
+ || (code == GTU && c1 > c2)
+ || (code == GEU && c1 >= c2)))))
+ return const_true_rtx;
+ }
+
/* (eq/ne (bswap x) C1) simplifies to (eq/ne x C2) with C2 swapped. */
if ((code == EQ || code == NE)
&& GET_CODE (op0) == BSWAP
/* { dg-final { scan-assembler-times "\[ \\t\]+sete" 1 { target { ia32 } } } } */
/* { dg-final { scan-assembler-times "\[ \\t\]+setne" 1 { target { ia32 } } } } */
/* { dg-final { scan-assembler-times "\[ \\t\]+je" 1 { target { ia32 } } } } */
-/* { dg-final { scan-assembler-times "\[ \\t\]+jne" 2 { target { ia32 } } } } */
+/* { dg-final { scan-assembler-times "\[ \\t\]+jne" 1 { target { ia32 } } } } */
/* { dg-final { scan-assembler-times "kortest" 12 { target { ia32 } } } } */
-/* { dg-final { scan-assembler-times "kortest" 17 { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-times "kortest" 16 { target { ! ia32 } } } } */
#include <immintrin.h>
--- /dev/null
+/* { dg-do link { target { rv64 } } } */
+/* { dg-options "-march=rv64gc_zbb_zbs -mabi=lp64d -flto" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" "-O1" } } */
+
+struct S {
+ int a;
+ char b;
+ int c;
+} s;
+
+const signed char c = -37;
+int d;
+struct S v1[] = {{0, 8}, 0, 0, -108976}, v2[] = {{}, 0, 0, 2804};
+int a;
+struct S v3[3];
+int *p = &a;
+
+void foo() {
+ int a;
+ if (a)
+ ;
+ else if (v1[0].b)
+ s.a = 0;
+ else
+ d = 0;
+ if (*p)
+ if (v3[1].c)
+ if (1 ^ (d & c & v2[1].c & ~v1[1].c | s.a))
+ v3[2].c = 0;
+}
+
+int main() { foo(); }