This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, i386]: Fix addcarry<mode>/subborrow<mode> patterns
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Uros Bizjak <ubizjak at gmail dot com>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 24 Oct 2017 08:51:05 +0200
- Subject: [PATCH, i386]: Fix addcarry<mode>/subborrow<mode> patterns
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=jakub at redhat dot com
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E4FA98608
- References: <CAFULd4ac9j-uJEatmjkid4=--CfkMs=RRYuD2eVb9wP0ER4MKA@mail.gmail.com> <20171023100903.GD14653@tucnak> <CAFULd4aSJ=c2NfSs850vZaNSq-+u5V8jCKQOyVBv-sBjE49few@mail.gmail.com> <20171023110737.GF14653@tucnak> <CAFULd4YsRDyXndw1r+jfLgRJVi+=Yf0KNE90AAV08QPF6_CwKw@mail.gmail.com> <CAFULd4ZQ4xjohzSB9WCWsBw=cYPQC+RTb5jmU5rkZ92LRQd+XQ@mail.gmail.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Mon, Oct 23, 2017 at 09:03:33PM +0200, Uros Bizjak wrote:
> >> As for addcarry/subborrow, the problem is that we expect in the pr67317*
> >> tests that combine is able to notice that the CF setter sets CF to
> >> unconditional 0 and matches the pattern. With the patch I wrote
> >> we end up with the combiner trying to match an insn where the CCC
> >> is set from a TImode comparison:
> >> (parallel [
> >> (set (reg:CC 17 flags)
> >> (compare:CC (zero_extend:TI (plus:DI (reg/v:DI 92 [ a ])
> >> (reg/v:DI 94 [ c ])))
> >> (zero_extend:TI (reg/v:DI 94 [ c ]))))
> >> (set (reg:DI 98)
> >> (plus:DI (reg/v:DI 92 [ a ])
> >> (reg/v:DI 94 [ c ])))
> >> ])
> >> So, either we need a define_insn_and_split pattern that would deal with
> >> that (for UNSPEC it would be the same thing, have a define_insn_and_split
> >> that would replace the (ltu...) with (const_int 0)), or perhaps be smarter
> >> during expansion, if we see the first argument is constant 0, expand it
> >> like a normal add instruction with CC setter.
This patch fixes the addcarry/subborrow patterns and deals with the
pr67317* regressions by special casing the first argument 0 case already
at expansion rather than waiting for combine.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
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.
--- gcc/config/i386/i386.c.jj 2017-10-23 12:52:20.711575924 +0200
+++ gcc/config/i386/i386.c 2017-10-23 15:59:07.379391029 +0200
@@ -35050,10 +35050,10 @@ ix86_expand_builtin (tree exp, rtx targe
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);
@@ -36028,22 +36028,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. */
@@ -36052,7 +36064,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))
@@ -36069,21 +36082,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. */
--- gcc/config/i386/i386.md.jj 2017-10-23 12:52:20.701576051 +0200
+++ gcc/config/i386/i386.md 2017-10-23 15:53:36.013585636 +0200
@@ -6840,15 +6840,19 @@ (define_insn "*addsi3_carry_zext"
(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)))]
@@ -6859,6 +6863,18 @@ (define_insn "addcarry<mode>"
(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
@@ -6941,15 +6957,18 @@ (define_insn "sub<mode>3_carry_ccgz"
(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}"
@@ -6957,6 +6976,16 @@ (define_insn "subborrow<mode>"
(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
Jakub
- References:
- [PATCH, i386]: Fix PR 82628, wrong code at -Os on x86_64-linux-gnu in the 32-bit mode
- Re: [PATCH, i386]: Fix PR 82628, wrong code at -Os on x86_64-linux-gnu in the 32-bit mode
- Re: [PATCH, i386]: Fix PR 82628, wrong code at -Os on x86_64-linux-gnu in the 32-bit mode
- Re: [PATCH, i386]: Fix PR 82628, wrong code at -Os on x86_64-linux-gnu in the 32-bit mode
- Re: [PATCH, i386]: Fix PR 82628, wrong code at -Os on x86_64-linux-gnu in the 32-bit mode
- Re: [PATCH, i386]: Fix PR 82628, wrong code at -Os on x86_64-linux-gnu in the 32-bit mode