diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-10-24 10:44:56 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-10-24 10:44:56 +0000 |
commit | 4065f60aebbe2cb4efeb2d408ab3b4d05365e4cf (patch) | |
tree | ffea2d11e20212b983fdd0aaa7477e99a37899ee | |
parent | 7c5c4b3763e5f723ce1501fcd1b11a56c67e87b8 (diff) | |
download | gcc-4065f60aebbe2cb4efeb2d408ab3b4d05365e4cf.tar.gz |
PR target/82628
* config/i386/i386.md (addcarry<mode>, subborrow<mode>): Change
patterns to better describe from which operation the CF is computed.
(addcarry<mode>_0, subborrow<mode>_0): New patterns.
* config/i386/i386.c (ix86_expand_builtin) <case handlecarry>: Pass
one LTU with [DT]Imode and another one with [SD]Imode. If arg0
is 0, use _0 suffixed expanders instead of emitting a comparison
before it.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254039 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 45 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 59 |
3 files changed, 89 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 82d69edfb0b..c2c3a523405 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2017-10-24 Jakub Jelinek <jakub@redhat.com> + + PR target/82628 + * config/i386/i386.md (addcarry<mode>, subborrow<mode>): Change + patterns to better describe from which operation the CF is computed. + (addcarry<mode>_0, subborrow<mode>_0): New patterns. + * config/i386/i386.c (ix86_expand_builtin) <case handlecarry>: Pass + one LTU with [DT]Imode and another one with [SD]Imode. If arg0 + is 0, use _0 suffixed expanders instead of emitting a comparison + before it. + 2017-10-06 Sergey Shalnov <Sergey.Shalnov@intel.com> * config/i386/i386.md(*movsf_internal, *movdf_internal): diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 72caf62bbf8..d8241fa15cd 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -35080,10 +35080,10 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, int ignore) { size_t i; - enum insn_code icode; + enum insn_code icode, icode2; tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); tree arg0, arg1, arg2, arg3, arg4; - rtx op0, op1, op2, op3, op4, pat, insn; + rtx op0, op1, op2, op3, op4, pat, pat2, insn; machine_mode mode0, mode1, mode2, mode3, mode4; unsigned int fcode = DECL_FUNCTION_CODE (fndecl); @@ -36058,22 +36058,34 @@ rdseed_step: case IX86_BUILTIN_SBB32: icode = CODE_FOR_subborrowsi; + icode2 = CODE_FOR_subborrowsi_0; mode0 = SImode; + mode1 = DImode; + mode2 = CCmode; goto handlecarry; case IX86_BUILTIN_SBB64: icode = CODE_FOR_subborrowdi; + icode2 = CODE_FOR_subborrowdi_0; mode0 = DImode; + mode1 = TImode; + mode2 = CCmode; goto handlecarry; case IX86_BUILTIN_ADDCARRYX32: icode = CODE_FOR_addcarrysi; + icode2 = CODE_FOR_addcarrysi_0; mode0 = SImode; + mode1 = DImode; + mode2 = CCCmode; goto handlecarry; case IX86_BUILTIN_ADDCARRYX64: icode = CODE_FOR_addcarrydi; + icode2 = CODE_FOR_addcarrydi_0; mode0 = DImode; + mode1 = TImode; + mode2 = CCCmode; handlecarry: arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in. */ @@ -36082,7 +36094,8 @@ rdseed_step: arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out. */ op1 = expand_normal (arg0); - op1 = copy_to_mode_reg (QImode, convert_to_mode (QImode, op1, 1)); + 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)) @@ -36099,21 +36112,31 @@ rdseed_step: op4 = copy_addr_to_reg (op4); } - /* Generate CF from input operand. */ - emit_insn (gen_addqi3_cconly_overflow (op1, constm1_rtx)); - - /* Generate instruction that consumes CF. */ op0 = gen_reg_rtx (mode0); + if (integer_zerop (arg0)) + { + /* If arg0 is 0, optimize right away into add or sub + instruction that sets CCCmode flags. */ + op1 = gen_rtx_REG (mode2, FLAGS_REG); + emit_insn (GEN_FCN (icode2) (op0, op2, op3)); + } + else + { + /* Generate CF from input operand. */ + emit_insn (gen_addqi3_cconly_overflow (op1, constm1_rtx)); - op1 = gen_rtx_REG (CCCmode, FLAGS_REG); - pat = gen_rtx_LTU (mode0, op1, const0_rtx); - emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat)); + /* Generate instruction that consumes CF. */ + op1 = gen_rtx_REG (CCCmode, FLAGS_REG); + pat = gen_rtx_LTU (mode1, op1, const0_rtx); + pat2 = gen_rtx_LTU (mode0, op1, const0_rtx); + emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat, pat2)); + } /* Return current CF value. */ if (target == 0) target = gen_reg_rtx (QImode); - PUT_MODE (pat, QImode); + pat = gen_rtx_LTU (QImode, op1, const0_rtx); emit_insn (gen_rtx_SET (target, pat)); /* Store the result. */ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index d5792eb22a4..49ad0394fb5 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -6844,15 +6844,19 @@ (define_insn "addcarry<mode>" [(set (reg:CCC FLAGS_REG) (compare:CCC - (plus:SWI48 + (zero_extend:<DWI> (plus:SWI48 - (match_operator:SWI48 4 "ix86_carry_flag_operator" - [(match_operand 3 "flags_reg_operand") (const_int 0)]) - (match_operand:SWI48 1 "nonimmediate_operand" "%0")) - (match_operand:SWI48 2 "nonimmediate_operand" "rm")) - (match_dup 1))) + (plus:SWI48 + (match_operator:SWI48 5 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)]) + (match_operand:SWI48 1 "nonimmediate_operand" "%0")) + (match_operand:SWI48 2 "nonimmediate_operand" "rm"))) + (plus:<DWI> + (zero_extend:<DWI> (match_dup 2)) + (match_operator:<DWI> 4 "ix86_carry_flag_operator" + [(match_dup 3) (const_int 0)])))) (set (match_operand:SWI48 0 "register_operand" "=r") - (plus:SWI48 (plus:SWI48 (match_op_dup 4 + (plus:SWI48 (plus:SWI48 (match_op_dup 5 [(match_dup 3) (const_int 0)]) (match_dup 1)) (match_dup 2)))] @@ -6863,6 +6867,18 @@ (set_attr "pent_pair" "pu") (set_attr "mode" "<MODE>")]) +(define_expand "addcarry<mode>_0" + [(parallel + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand") + (match_operand:SWI48 2 "x86_64_general_operand")) + (match_dup 1))) + (set (match_operand:SWI48 0 "register_operand") + (plus:SWI48 (match_dup 1) (match_dup 2)))])] + "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)") + (define_insn "sub<mode>3_carry" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") (minus:SWI @@ -6945,15 +6961,18 @@ (define_insn "subborrow<mode>" [(set (reg:CCC FLAGS_REG) (compare:CCC - (match_operand:SWI48 1 "nonimmediate_operand" "0") - (plus:SWI48 - (match_operator:SWI48 4 "ix86_carry_flag_operator" - [(match_operand 3 "flags_reg_operand") (const_int 0)]) - (match_operand:SWI48 2 "nonimmediate_operand" "rm")))) + (zero_extend:<DWI> + (match_operand:SWI48 1 "nonimmediate_operand" "0")) + (plus:<DWI> + (match_operator:<DWI> 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)]) + (zero_extend:<DWI> + (match_operand:SWI48 2 "nonimmediate_operand" "rm"))))) (set (match_operand:SWI48 0 "register_operand" "=r") - (minus:SWI48 (minus:SWI48 (match_dup 1) - (match_op_dup 4 - [(match_dup 3) (const_int 0)])) + (minus:SWI48 (minus:SWI48 + (match_dup 1) + (match_operator:SWI48 5 "ix86_carry_flag_operator" + [(match_dup 3) (const_int 0)])) (match_dup 2)))] "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)" "sbb{<imodesuffix>}\t{%2, %0|%0, %2}" @@ -6961,6 +6980,16 @@ (set_attr "use_carry" "1") (set_attr "pent_pair" "pu") (set_attr "mode" "<MODE>")]) + +(define_expand "subborrow<mode>_0" + [(parallel + [(set (reg:CC FLAGS_REG) + (compare:CC + (match_operand:SWI48 1 "nonimmediate_operand") + (match_operand:SWI48 2 "<general_operand>"))) + (set (match_operand:SWI48 0 "register_operand") + (minus:SWI48 (match_dup 1) (match_dup 2)))])] + "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)") ;; Overflow setting add instructions |