diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 8bc5430..2b6d24d 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -13531,8 +13531,6 @@ rdseed_step: arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out. */ op1 = expand_normal (arg0); - if (!integer_zerop (arg0)) - op1 = copy_to_mode_reg (QImode, convert_to_mode (QImode, op1, 1)); op2 = expand_normal (arg1); if (!register_operand (op2, mode0)) @@ -13550,7 +13548,7 @@ rdseed_step: } op0 = gen_reg_rtx (mode0); - if (integer_zerop (arg0)) + if (op1 == const0_rtx) { /* If arg0 is 0, optimize right away into add or sub instruction that sets CCCmode flags. */ @@ -13560,7 +13558,14 @@ rdseed_step: else { /* Generate CF from input operand. */ - emit_insn (gen_addqi3_cconly_overflow (op1, constm1_rtx)); + if (!CONST_INT_P (op1)) + { + op1 = convert_to_mode (QImode, op1, 1); + op1 = copy_to_mode_reg (QImode, op1); + emit_insn (gen_negqi_ccc_1 (op1, op1)); + } + else + emit_insn (gen_x86_stc ()); /* Generate instruction that consumes CF. */ op1 = gen_rtx_REG (CCCmode, FLAGS_REG); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 5b53841..1cc3989 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1765,6 +1765,22 @@ (set_attr "bdver1_decode" "direct") (set_attr "mode" "SI")]) +(define_insn "x86_clc" + [(set (reg:CCC FLAGS_REG) (const_int 0))] + "" + "stc" + [(set_attr "length" "1") + (set_attr "length_immediate" "0") + (set_attr "modrm" "0")]) + +(define_insn "x86_stc" + [(set (reg:CCC FLAGS_REG) (const_int 1))] + "" + "stc" + [(set_attr "length" "1") + (set_attr "length_immediate" "0") + (set_attr "modrm" "0")]) + ;; Pentium Pro can do both steps in one go. ;; (these instructions set flags directly) @@ -7735,6 +7751,14 @@ "#" "&& 1" [(const_int 0)]) + +(define_insn_and_split "*setcc_qi_negqi_ccc_1_" + [(set (reg:CCC FLAGS_REG) + (ltu:CCC (reg:CC_CCC FLAGS_REG) (const_int 0)))] + "ix86_pre_reload_split ()" + "#" + "&& 1" + [(const_int 0)]) ;; Overflow setting add instructions @@ -11218,7 +11242,7 @@ [(set_attr "type" "negnot") (set_attr "mode" "SI")]) -(define_insn "*neg_ccc_1" +(define_insn "neg_ccc_1" [(set (reg:CCC FLAGS_REG) (ne:CCC (match_operand:SWI 1 "nonimmediate_operand" "0") @@ -15072,7 +15096,7 @@ ;; Convert setcc + movzbl to xor + setcc if operands don't overlap. (define_peephole2 - [(set (reg FLAGS_REG) (match_operand 0)) + [(set (match_operand 4 "flags_reg_operand") (match_operand 0)) (set (match_operand:QI 1 "register_operand") (match_operator:QI 2 "ix86_comparison_operator" [(reg FLAGS_REG) (const_int 0)])) @@ -15086,13 +15110,12 @@ (set (strict_low_part (match_dup 5)) (match_dup 2))] { - operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG); operands[5] = gen_lowpart (QImode, operands[3]); ix86_expand_clear (operands[3]); }) (define_peephole2 - [(parallel [(set (reg FLAGS_REG) (match_operand 0)) + [(parallel [(set (match_operand 5 "flags_reg_operand") (match_operand 0)) (match_operand 4)]) (set (match_operand:QI 1 "register_operand") (match_operator:QI 2 "ix86_comparison_operator" @@ -15110,14 +15133,13 @@ (set (strict_low_part (match_dup 6)) (match_dup 2))] { - operands[5] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG); operands[6] = gen_lowpart (QImode, operands[3]); ix86_expand_clear (operands[3]); }) (define_peephole2 - [(set (reg FLAGS_REG) (match_operand 0)) - (parallel [(set (reg FLAGS_REG) (match_operand 1)) + [(set (match_operand 6 "flags_reg_operand") (match_operand 0)) + (parallel [(set (match_operand 7 "flags_reg_operand") (match_operand 1)) (match_operand 5)]) (set (match_operand:QI 2 "register_operand") (match_operator:QI 3 "ix86_comparison_operator" @@ -15138,8 +15160,6 @@ (set (strict_low_part (match_dup 8)) (match_dup 3))] { - operands[6] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG); - operands[7] = gen_rtx_REG (GET_MODE (operands[1]), FLAGS_REG); operands[8] = gen_lowpart (QImode, operands[4]); ix86_expand_clear (operands[4]); }) @@ -15147,7 +15167,7 @@ ;; Similar, but match zero extend with andsi3. (define_peephole2 - [(set (reg FLAGS_REG) (match_operand 0)) + [(set (match_operand 4 "flags_reg_operand") (match_operand 0)) (set (match_operand:QI 1 "register_operand") (match_operator:QI 2 "ix86_comparison_operator" [(reg FLAGS_REG) (const_int 0)])) @@ -15161,13 +15181,12 @@ (set (strict_low_part (match_dup 5)) (match_dup 2))] { - operands[4] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG); operands[5] = gen_lowpart (QImode, operands[3]); ix86_expand_clear (operands[3]); }) (define_peephole2 - [(parallel [(set (reg FLAGS_REG) (match_operand 0)) + [(parallel [(set (match_operand 5 "flags_reg_operand") (match_operand 0)) (match_operand 4)]) (set (match_operand:QI 1 "register_operand") (match_operator:QI 2 "ix86_comparison_operator" @@ -15186,14 +15205,13 @@ (set (strict_low_part (match_dup 6)) (match_dup 2))] { - operands[5] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG); operands[6] = gen_lowpart (QImode, operands[3]); ix86_expand_clear (operands[3]); }) (define_peephole2 - [(set (reg FLAGS_REG) (match_operand 0)) - (parallel [(set (reg FLAGS_REG) (match_operand 1)) + [(set (match_operand 6 "flags_reg_operand") (match_operand 0)) + (parallel [(set (match_operand 7 "flags_reg_operand") (match_operand 1)) (match_operand 5)]) (set (match_operand:QI 2 "register_operand") (match_operator:QI 3 "ix86_comparison_operator" @@ -15215,8 +15233,6 @@ (set (strict_low_part (match_dup 8)) (match_dup 3))] { - operands[6] = gen_rtx_REG (GET_MODE (operands[0]), FLAGS_REG); - operands[7] = gen_rtx_REG (GET_MODE (operands[1]), FLAGS_REG); operands[8] = gen_lowpart (QImode, operands[4]); ix86_expand_clear (operands[4]); }) diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index fa20665..73ec5c7 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -6026,6 +6026,18 @@ simplify_const_relational_operation (enum rtx_code code, return 0; } + /* Handle MODE_CC comparisons that have been simplified to + constants. */ + if (GET_MODE_CLASS (mode) == MODE_CC + && op1 == const0_rtx + && CONST_INT_P (op0)) + { + /* LTU represents the carry flag. */ + if (code == LTU) + return op0 == const0_rtx ? const0_rtx : const_true_rtx; + return 0; + } + /* We can't simplify MODE_CC values since we don't know what the actual comparison is. */ if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC) diff --git a/gcc/testsuite/gcc.target/i386/stc-1.c b/gcc/testsuite/gcc.target/i386/stc-1.c new file mode 100644 index 0000000..857c939 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/stc-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef unsigned int u32; + +unsigned int foo (unsigned int a, unsigned int b, unsigned int *c) +{ + return __builtin_ia32_addcarryx_u32 (1, a, b, c); +} + +unsigned int bar (unsigned int b, unsigned int *c) +{ + return __builtin_ia32_addcarryx_u32 (1, 2, b, c); +} + +unsigned int baz (unsigned int a, unsigned int *c) +{ + return __builtin_ia32_addcarryx_u32 (1, a, 3, c); +} + +/* { dg-final { scan-assembler "stc" } } */