[(set_attr "type" "alu")
(set_attr "mode" "SI")])
+;; x == 0 with zero flag test can be done also as x < 1U with carry flag
+;; test, where the latter is preferrable if we have some carry consuming
+;; instruction.
+;; For x != 0, we need to use x < 1U with negation of carry, i.e.
+;; + (1 - CF).
+(define_insn_and_split "*add<mode>3_eq"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (plus:SWI
+ (plus:SWI
+ (eq:SWI (match_operand 3 "int_nonimmediate_operand") (const_int 0))
+ (match_operand:SWI 1 "nonimmediate_operand"))
+ (match_operand:SWI 2 "<general_operand>")))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 3) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (plus:SWI
+ (plus:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 1))
+ (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])])
+
+(define_insn_and_split "*add<mode>3_ne"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (plus:SWI
+ (plus:SWI
+ (ne:SWI (match_operand 3 "int_nonimmediate_operand") (const_int 0))
+ (match_operand:SWI 1 "nonimmediate_operand"))
+ (match_operand:SWI 2 "<immediate_operand>")))
+ (clobber (reg:CC FLAGS_REG))]
+ "CONST_INT_P (operands[2])
+ && (<MODE>mode != DImode
+ || INTVAL (operands[2]) != HOST_WIDE_INT_C (-0x80000000))
+ && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 3) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (minus:SWI
+ (minus:SWI (match_dup 1)
+ (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)))
+ (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ operands[2] = gen_int_mode (~INTVAL (operands[2]),
+ <MODE>mode == DImode ? SImode : <MODE>mode);
+})
+
+(define_insn_and_split "*add<mode>3_eq_0"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (plus:SWI
+ (eq:SWI (match_operand 2 "int_nonimmediate_operand") (const_int 0))
+ (match_operand:SWI 1 "<general_operand>")))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_unary_operator_ok (PLUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 2) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (plus:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 1)))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ if (!nonimmediate_operand (operands[1], <MODE>mode))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+})
+
+(define_insn_and_split "*add<mode>3_ne_0"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (plus:SWI
+ (ne:SWI (match_operand 2 "int_nonimmediate_operand") (const_int 0))
+ (match_operand:SWI 1 "<general_operand>")))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_unary_operator_ok (PLUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 2) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (minus:SWI (minus:SWI
+ (match_dup 1)
+ (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)))
+ (const_int -1)))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ if (!nonimmediate_operand (operands[1], <MODE>mode))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+})
+
+(define_insn_and_split "*sub<mode>3_eq"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (minus:SWI
+ (minus:SWI
+ (match_operand:SWI 1 "nonimmediate_operand")
+ (eq:SWI (match_operand 3 "int_nonimmediate_operand")
+ (const_int 0)))
+ (match_operand:SWI 2 "<general_operand>")))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 3) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (minus:SWI
+ (minus:SWI (match_dup 1)
+ (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)))
+ (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])])
+
+(define_insn_and_split "*sub<mode>3_ne"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (plus:SWI
+ (minus:SWI
+ (match_operand:SWI 1 "nonimmediate_operand")
+ (ne:SWI (match_operand 3 "int_nonimmediate_operand")
+ (const_int 0)))
+ (match_operand:SWI 2 "<immediate_operand>")))
+ (clobber (reg:CC FLAGS_REG))]
+ "CONST_INT_P (operands[2])
+ && (<MODE>mode != DImode
+ || INTVAL (operands[2]) != HOST_WIDE_INT_C (-0x80000000))
+ && ix86_binary_operator_ok (MINUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 3) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (plus:SWI
+ (plus:SWI (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 1))
+ (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ operands[2] = gen_int_mode (INTVAL (operands[2]) - 1,
+ <MODE>mode == DImode ? SImode : <MODE>mode);
+})
+
+(define_insn_and_split "*sub<mode>3_eq_1"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (plus:SWI
+ (minus:SWI
+ (match_operand:SWI 1 "nonimmediate_operand")
+ (eq:SWI (match_operand 3 "int_nonimmediate_operand")
+ (const_int 0)))
+ (match_operand:SWI 2 "<immediate_operand>")))
+ (clobber (reg:CC FLAGS_REG))]
+ "CONST_INT_P (operands[2])
+ && (<MODE>mode != DImode
+ || INTVAL (operands[2]) != HOST_WIDE_INT_C (-0x80000000))
+ && ix86_binary_operator_ok (MINUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 3) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (minus:SWI
+ (minus:SWI (match_dup 1)
+ (ltu:SWI (reg:CC FLAGS_REG) (const_int 0)))
+ (match_dup 2)))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ operands[2] = gen_int_mode (-INTVAL (operands[2]),
+ <MODE>mode == DImode ? SImode : <MODE>mode);
+})
+
+(define_insn_and_split "*sub<mode>3_eq_0"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (minus:SWI
+ (match_operand:SWI 1 "<general_operand>")
+ (eq:SWI (match_operand 2 "int_nonimmediate_operand") (const_int 0))))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_unary_operator_ok (MINUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 2) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (minus:SWI (match_dup 1)
+ (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ if (!nonimmediate_operand (operands[1], <MODE>mode))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+})
+
+(define_insn_and_split "*sub<mode>3_ne_0"
+ [(set (match_operand:SWI 0 "nonimmediate_operand")
+ (minus:SWI
+ (match_operand:SWI 1 "<general_operand>")
+ (ne:SWI (match_operand 2 "int_nonimmediate_operand") (const_int 0))))
+ (clobber (reg:CC FLAGS_REG))]
+ "ix86_unary_operator_ok (MINUS, <MODE>mode, operands)
+ && can_create_pseudo_p ()"
+ "#"
+ "&& 1"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_dup 2) (const_int 1)))
+ (parallel [(set (match_dup 0)
+ (plus:SWI (plus:SWI
+ (ltu:SWI (reg:CC FLAGS_REG) (const_int 0))
+ (match_dup 1))
+ (const_int -1)))
+ (clobber (reg:CC FLAGS_REG))])]
+{
+ if (!nonimmediate_operand (operands[1], <MODE>mode))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+})
+
;; The patterns that match these are at the end of this file.
(define_expand "<plusminus_insn>xf3"
--- /dev/null
+/* PR target/92140 */
+/* { dg-do compile { target nonpic } } */
+/* { dg-options "-O2 -mtune=generic -masm=att" } */
+/* { dg-additional-options "-mregparm=1" { target ia32 } } */
+/* { dg-final { scan-assembler-times "\tsbbl\t\\\$-1, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tadcl\t\\\$-1, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tadcl\t\\\$0, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tsbbl\t\\\$0, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tsbbl\t\\\$25, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tadcl\t\\\$25, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tadcl\t\\\$-26, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tsbbl\t\\\$-26, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tsbbl\t\\\$-43, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tadcl\t\\\$-43, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tadcl\t\\\$42, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tsbbl\t\\\$42, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tadcl\t%\[a-z0-9]*, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tsbbl\t%\[a-z0-9]*, v" 1 } } */
+/* { dg-final { scan-assembler-times "\tsbbl\t\\\$-1, %" 1 } } */
+
+char c;
+int v;
+
+__attribute__((noipa)) void f1 (void) { v += c != 0; }
+__attribute__((noipa)) void f2 (void) { v -= c != 0; }
+__attribute__((noipa)) void f3 (void) { v += c == 0; }
+__attribute__((noipa)) void f4 (void) { v -= c == 0; }
+__attribute__((noipa)) void f5 (void) { v += (c != 0) - 26; }
+__attribute__((noipa)) void f6 (void) { v -= (c != 0) - 26; }
+__attribute__((noipa)) void f7 (void) { v += (c == 0) - 26; }
+__attribute__((noipa)) void f8 (void) { v -= (c == 0) - 26; }
+__attribute__((noipa)) void f9 (void) { v += (c != 0) + 42; }
+__attribute__((noipa)) void f10 (void) { v -= (c != 0) + 42; }
+__attribute__((noipa)) void f11 (void) { v += (c == 0) + 42; }
+__attribute__((noipa)) void f12 (void) { v -= (c == 0) + 42; }
+__attribute__((noipa)) void f13 (int z) { v += (c == 0) + z; }
+__attribute__((noipa)) void f14 (int z) { v -= (c == 0) + z; }
+__attribute__((noipa)) unsigned int f15 (unsigned int n) { return n ? 2 : 1; }