@@ -21699,6 +21699,19 @@ ix86_expand_branch (enum rtx_code code, rtx op0, rtx op1, rtx label)
case DImode:
if (TARGET_64BIT)
goto simple;
+ /* For 32-bit target DI comparison may be performed on
+ SSE registers. To allow this we should avoid split
+ to SI mode which is achieved by doing xor in DI mode
+ and then comparing with zero (which is recognized by
+ STV pass). We don't compare using xor when optimizing
+ for size. */
+ if (!optimize_insn_for_size_p ()
+ && TARGET_STV
+ && (code == EQ || code == NE))
+ {
+ op0 = force_reg (mode, gen_rtx_XOR (mode, op0, op1));
+ op1 = const0_rtx;
+ }
case TImode:
/* Expand DImode branch into multiple compare+branch. */
{
new file mode 100644
@@ -0,0 +1,22 @@
+/* PR target/pr65105 */
+/* { dg-do compile { target { ia32 } } } */
+/* { dg-options "-O2 -march=core-avx2" } */
+/* { dg-final { scan-assembler "pand" } } */
+/* { dg-final { scan-assembler "pxor" } } */
+/* { dg-final { scan-assembler "ptest" } } */
+
+struct S1
+{
+ unsigned long long a;
+ unsigned long long b;
+};
+
+void
+test (int p1, unsigned long long p2, int p3, struct S1 *p4)
+{
+ int i;
+
+ for (i = 0; i < p1; i++)
+ if ((p4[i].a & p2) != p2)
+ p4[i].a ^= (1ULL << p3);
+}