}
else if (GET_CODE (XEXP (x, 0)) == PLUS)
{
+ rtx op = XEXP (XEXP (x, 0), 0);
+
/* Add with carry, ignore the cost of adding a carry flag. */
- if (ix86_carry_flag_operator (XEXP (XEXP (x, 0), 0), mode))
+ if (ix86_carry_flag_operator (op, mode)
+ || ix86_carry_flag_unset_operator (op, mode))
*total = cost->add;
else
{
*total = cost->lea;
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode,
+ *total += rtx_cost (op, mode,
outer_code, opno, speed);
}
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) <= UNITS_PER_WORD
&& GET_CODE (XEXP (x, 0)) == MINUS
- && ix86_carry_flag_operator (XEXP (XEXP (x, 0), 1), mode))
+ && (ix86_carry_flag_operator (XEXP (XEXP (x, 0), 1), mode)
+ || ix86_carry_flag_unset_operator (XEXP (XEXP (x, 0), 1), mode)))
{
*total = cost->add;
*total += rtx_cost (XEXP (XEXP (x, 0), 0), mode,
(define_insn "*add<mode>3_carry_0"
[(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
(plus:SWI
- (match_operator:SWI 3 "ix86_carry_flag_operator"
- [(match_operand 2 "flags_reg_operand") (const_int 0)])
+ (match_operator:SWI 2 "ix86_carry_flag_operator"
+ [(reg FLAGS_REG) (const_int 0)])
(match_operand:SWI 1 "nonimmediate_operand" "0")))
(clobber (reg:CC FLAGS_REG))]
"!MEM_P (operands[0]) || rtx_equal_p (operands[0], operands[1])"
(set_attr "pent_pair" "pu")
(set_attr "mode" "<MODE>")])
+(define_insn "*add<mode>3_carry_0r"
+ [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
+ (plus:SWI
+ (match_operator:SWI 2 "ix86_carry_flag_unset_operator"
+ [(reg FLAGS_REG) (const_int 0)])
+ (match_operand:SWI 1 "nonimmediate_operand" "0")))
+ (clobber (reg:CC FLAGS_REG))]
+ "!MEM_P (operands[0]) || rtx_equal_p (operands[0], operands[1])"
+ "sbb{<imodesuffix>}\t{$-1, %0|%0, -1}"
+ [(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
+ (set_attr "pent_pair" "pu")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "*addsi3_carry_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")])
+(define_insn "*addsi3_carry_zext_0r"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (plus:SI (match_operator:SI 2 "ix86_carry_flag_unset_operator"
+ [(reg FLAGS_REG) (const_int 0)])
+ (match_operand:SI 1 "register_operand" "0"))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "sbb{l}\t{$-1, %k0|%k0, -1}"
+ [(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
+ (set_attr "pent_pair" "pu")
+ (set_attr "mode" "SI")])
+
;; There is no point to generate ADCX instruction. ADC is shorter and faster.
(define_insn "addcarry<mode>"
[(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
(minus:SWI
(match_operand:SWI 1 "nonimmediate_operand" "0")
- (match_operator:SWI 3 "ix86_carry_flag_operator"
- [(match_operand 2 "flags_reg_operand") (const_int 0)])))
+ (match_operator:SWI 2 "ix86_carry_flag_operator"
+ [(reg FLAGS_REG) (const_int 0)])))
(clobber (reg:CC FLAGS_REG))]
"!MEM_P (operands[0]) || rtx_equal_p (operands[0], operands[1])"
"sbb{<imodesuffix>}\t{$0, %0|%0, 0}"
(set_attr "pent_pair" "pu")
(set_attr "mode" "<MODE>")])
+(define_insn "*sub<mode>3_carry_0r"
+ [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
+ (minus:SWI
+ (match_operand:SWI 1 "nonimmediate_operand" "0")
+ (match_operator:SWI 2 "ix86_carry_flag_unset_operator"
+ [(reg FLAGS_REG) (const_int 0)])))
+ (clobber (reg:CC FLAGS_REG))]
+ "!MEM_P (operands[0]) || rtx_equal_p (operands[0], operands[1])"
+ "adc{<imodesuffix>}\t{$-1, %0|%0, -1}"
+ [(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
+ (set_attr "pent_pair" "pu")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "*subsi3_carry_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")])
+(define_insn "*subsi3_carry_zext_0r"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (minus:SI
+ (match_operand:SI 1 "register_operand" "0")
+ (match_operator:SI 2 "ix86_carry_flag_unset_operator"
+ [(reg FLAGS_REG) (const_int 0)]))))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_64BIT"
+ "adc{l}\t{$-1, %k0|%k0, -1}"
+ [(set_attr "type" "alu")
+ (set_attr "use_carry" "1")
+ (set_attr "pent_pair" "pu")
+ (set_attr "mode" "SI")])
+
(define_insn "@sub<mode>3_carry_ccc"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
--- /dev/null
+/* PR target/98060 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-not "set" } } */
+/* { dg-final { scan-assembler-times "adc" 4 } } */
+/* { dg-final { scan-assembler-times "sbb" 4 } } */
+
+int r1 (unsigned v0, unsigned v1, int v2)
+{
+ return v2 + (v0 >= v1);
+}
+
+int r2 (unsigned v0, unsigned v1, int v2)
+{
+ return v2 + (v0 <= v1);
+}
+
+int r3 (unsigned v0, unsigned v1, int v2)
+{
+ return v2 + (v0 > v1);
+}
+
+int r4 (unsigned v0, unsigned v1, int v2)
+{
+ return v2 + (v0 < v1);
+}
+
+int r5 (unsigned v0, unsigned v1, int v2)
+{
+ return v2 - (v0 >= v1);
+}
+
+int r6 (unsigned v0, unsigned v1, int v2)
+{
+ return v2 - (v0 <= v1);
+}
+
+int r7 (unsigned v0, unsigned v1, int v2)
+{
+ return v2 - (v0 > v1);
+}
+
+int r8 (unsigned v0, unsigned v1, int v2)
+{
+ return v2 - (v0 < v1);
+}