On Tue, Oct 24, 2017 at 8:51 AM, Jakub Jelinek <ja...@redhat.com> wrote:
> 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  <ja...@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.

OK.

Thanks,
Uros.

> --- 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

Reply via email to