https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101807
--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> --- Here is what I have so far without the cost model: /* Hand bool0 CMP bool1 because bitwise operators are normally better than comparisons. */ if (INTEGRAL_TYPE_P (type) && ((tree_nonzero_bits (arg0) == 1 && tree_nonzero_bits (arg1) == 1) || (unsignedp && TYPE_PRECISION (type) == 1))) { tree b0 = arg0; tree b1 = arg1; bool not_p = false; bool operand1_not_p = false; tree_code code = ERROR_MARK; switch (ops->code) { case EQ_EXPR: not_p = true; code = BIT_XOR_EXPR; break; case NE_EXPR: code = BIT_XOR_EXPR; break; case GT_EXPR: std::swap (b0, b1); code = BIT_AND_EXPR; operand1_not_p = true; break; case LT_EXPR: code = BIT_AND_EXPR; operand1_not_p = true; break; case GE_EXPR: std::swap (b0, b1); code = BIT_IOR_EXPR; operand1_not_p = true; break; case LE_EXPR: code = BIT_IOR_EXPR; operand1_not_p = true; break; default: code = ERROR_MARK; break; } if (code != ERROR_MARK) { tree exp; tree one = build_int_cst (type, 1); if (operand1_not_p) b0 = build2_loc (loc, BIT_XOR_EXPR, type, b0, one); exp = build2_loc (loc, code, type, b0, b1); if (not_p) exp = build2_loc (loc, BIT_XOR_EXPR, type, exp, one); return expand_expr (exp, target, VOIDmode, EXPAND_NORMAL); } }