XEXP (op0, 1));
}
+ /* The following happens with bitfield merging.
+ (X & C) | ((X | Y) & ~C) -> X | (Y & ~C) */
+ if (GET_CODE (op0) == AND
+ && GET_CODE (op1) == AND
+ && CONST_INT_P (XEXP (op0, 1))
+ && CONST_INT_P (XEXP (op1, 1))
+ && (INTVAL (XEXP (op0, 1))
+ == ~INTVAL (XEXP (op1, 1))))
+ {
+ /* The IOR may be on both sides. */
+ rtx top0 = NULL_RTX, top1 = NULL_RTX;
+ if (GET_CODE (XEXP (op1, 0)) == IOR)
+ top0 = op0, top1 = op1;
+ else if (GET_CODE (XEXP (op0, 0)) == IOR)
+ top0 = op1, top1 = op0;
+ if (top0 && top1)
+ {
+ /* X may be on either side of the inner IOR. */
+ rtx tem = NULL_RTX;
+ if (rtx_equal_p (XEXP (top0, 0),
+ XEXP (XEXP (top1, 0), 0)))
+ tem = XEXP (XEXP (top1, 0), 1);
+ else if (rtx_equal_p (XEXP (top0, 0),
+ XEXP (XEXP (top1, 0), 1)))
+ tem = XEXP (XEXP (top1, 0), 0);
+ if (tem)
+ return simplify_gen_binary (IOR, mode, XEXP (top0, 0),
+ simplify_gen_binary
+ (AND, mode, tem, XEXP (top1, 1)));
+ }
+ }
+
tem = simplify_byte_swapping_operation (code, mode, op0, op1);
if (tem)
return tem;
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+struct B { unsigned bit0 : 1; unsigned bit1 : 1; };
+
+void
+bar (struct B *b, int x)
+{
+ b->bit0 |= x;
+}
+
+/* This fails to combine in 32bit mode but not for x32. */
+/* { dg-final { scan-assembler-times "and" 1 { xfail { { ! x32 } && ilp32 } } } } */
+/* { dg-final { scan-assembler-times "or" 1 { xfail { { ! x32 } && ilp32 } } } } */