Ping?

Patch is rebased and attached.

Thanks!
-Zhenqiang

ChangeLog
2014-09-23  Zhenqiang Chen  <zhenqiang.c...@linaro.org>
            Andrew Pinski  <apin...@cavium.com>

        * ccmp.c (used_in_cond_stmt_p): Hande ? expr.
        * expr.c (expand_cond_expr_using_cmove): Handle CCmode.
        * ifcvt.c: #include "ccmp.h".
        (struct noce_if_info): Add a new field ccmp_p.
        (noce_emit_cmove): Allow ccmp condition.
        (noce_get_alt_condition): Call canonicalize_condition with ccmp_p.
        (noce_get_condition): Set ALLOW_CC_MODE to TRUE for ccmp.
        (noce_process_if_block): Set ccmp_p for ccmp.

testsuite/ChangeLog:
2014-09-23  Zhenqiang Chen  <zhenqiang.c...@linaro.org>

        * gcc.target/aarch64/ccmn-csel-1.c: New testcase.
        * gcc.target/aarch64/ccmn-csel-2.c: New testcase.
        * gcc.target/aarch64/ccmn-csel-3.c: New testcase.
        * gcc.target/aarch64/ccmp-csel-1.c: New testcase.
        * gcc.target/aarch64/ccmp-csel-2.c: New testcase.
        * gcc.target/aarch64/ccmp-csel-3.c: New testcase.
        * gcc.target/aarch64/ccmp-csel-4.c: New testcase.
        * gcc.target/aarch64/ccmp-csel-5.c: New testcase.
        * gcc.target/aarch64/ccmp-cset-1.c: New testcase.
        * gcc.target/aarch64/ccmp-cset-2.c: New testcase.

> -----Original Message-----
> From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches-
> ow...@gcc.gnu.org] On Behalf Of Zhenqiang Chen
> Sent: Friday, July 04, 2014 2:54 PM
> To: Andrew Pinski
> Cc: gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH, 10/10] aarch64: Handle ccmp in ifcvt to make it work
> with cmov
> 
> Andrew,
> 
> Thanks for the input. Patch is updated with your codes. In addition, add
> "cstorecc4" and 4 test cases. So it can optimized the following example
> 
> int foo (int a, int b)
> {
>    return a > 0 && b < 7;
> }
> to:
>     cmp    w0, wzr
>     ccmp    w1, #6, #9, gt
>     cset    w0, le
> 
> Bootstrap and no make check regression on qemu.
> 
> OK for trunk?
> 
> Thanks!
> -Zhenqiang
> 
> 2014-07-04  Zhenqiang Chen  <zhenqiang.c...@linaro.org>
>             Andrew Pinski  <apin...@cavium.com>
> 
>         * config/aarch64/aarch64.md (cstorecc4): New.
>         (mov<mode>cc): Handle ccmp_cc.
>         * ccmp.c (used_in_cond_stmt_p): Hande ? expr.
>         (expand_ccmp_expr): Set mode to the MODE of gimple_assign_lhs (g).
>         * expr.c (expand_cond_expr_using_cmove): Handle CCmode.
>         * ifcvt.c: #include "ccmp.h".
>         (struct noce_if_info): Add a new field ccmp_p.
>         (noce_emit_cmove): Allow ccmp condition.
>         (noce_get_alt_condition): Call canonicalize_condition with ccmp_p.
>         (noce_get_condition): Set ALLOW_CC_MODE to TRUE for ccmp.
>         (noce_process_if_block): Set ccmp_p for ccmp.
> 
> testsuite/ChangeLog:
> 2014-07-04  Zhenqiang Chen  <zhenqiang.c...@linaro.org>
> 
>         * gcc.target/aarch64/ccmn-csel-1.c: New testcase.
>         * gcc.target/aarch64/ccmn-csel-2.c: New testcase.
>         * gcc.target/aarch64/ccmn-csel-3.c: New testcase.
>         * gcc.target/aarch64/ccmp-csel-1.c: New testcase.
>         * gcc.target/aarch64/ccmp-csel-2.c: New testcase.
>         * gcc.target/aarch64/ccmp-csel-3.c: New testcase.
>         * gcc.target/aarch64/ccmp-csel-4.c: New testcase.
>         * gcc.target/aarch64/ccmp-csel-5.c: New testcase.
>         * gcc.target/aarch64/ccmp-cset-1.c: New testcase.
>         * gcc.target/aarch64/ccmp-cset-2.c: New testcase.
> 
> diff --git a/gcc/ccmp.c b/gcc/ccmp.c
> index e0670f1..6382974 100644
> --- a/gcc/ccmp.c
> +++ b/gcc/ccmp.c
> @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
> #include "tm_p.h"
>  #include "tree.h"
>  #include "stringpool.h"
> +#include "stor-layout.h"
>  #include "regs.h"
>  #include "expr.h"
>  #include "optabs.h"
> @@ -133,6 +134,13 @@ used_in_cond_stmt_p (tree exp)
>           expand_cond = true;
>         BREAK_FROM_IMM_USE_STMT (ui);
>        }
> +    else if (gimple_code (use_stmt) == GIMPLE_ASSIGN
> +            && gimple_expr_code (use_stmt) == COND_EXPR)
> +      {
> +       if (gimple_assign_rhs1 (use_stmt) == exp)
> +         expand_cond = true;
> +      }
> +
>    return expand_cond;
>  }
> 
> @@ -274,9 +282,11 @@ expand_ccmp_expr (gimple g)
>        icode = optab_handler (cstore_optab, cc_mode);
>        if (icode != CODE_FOR_nothing)
>         {
> -         rtx target = gen_reg_rtx (word_mode);
> -         tmp = emit_cstore (target, icode, NE, CCmode, CCmode,
> -                            0, tmp, const0_rtx, 1, word_mode);
> +         tree lhs = gimple_assign_lhs(g);
> +         enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
> +         rtx target = gen_reg_rtx (mode);
> +         tmp = emit_cstore (target, icode, NE, cc_mode, cc_mode,
> +                            0, tmp, const0_rtx, 1, mode);
>           if (tmp)
>             return tmp;
>         }
> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
> index c25d940..88733f4 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -2337,6 +2337,19 @@
>    "
>  )
> 
> +(define_expand "cstorecc4"
> +  [(set (match_operand:SI 0 "register_operand")
> +       (match_operator 1 "aarch64_comparison_operator"
> +        [(match_operand 2 "ccmp_cc_register")
> +         (match_operand 3 "aarch64_plus_operand")]))]
> +  ""
> +"{
> +  operands[3] = const0_rtx;
> +  emit_insn (gen_rtx_SET (SImode, operands[0], operands[1]));
> +  DONE;
> +}")
> +
> +
>  (define_expand "cstore<mode>4"
>    [(set (match_operand:SI 0 "register_operand" "")
>         (match_operator:SI 1 "aarch64_comparison_operator"
> @@ -2485,15 +2498,19 @@
>                            (match_operand:ALLI 3 "register_operand" "")))]
>    ""
>    {
> -    rtx ccreg;
>      enum rtx_code code = GET_CODE (operands[1]);
> 
>      if (code == UNEQ || code == LTGT)
>        FAIL;
> 
> -    ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
> -                                 XEXP (operands[1], 1));
> -    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
> +    if (!ccmp_cc_register (XEXP (operands[1], 0),
> +                          GET_MODE (XEXP (operands[1], 0))))
> +      {
> +       rtx ccreg;
> +       ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
> +                                        XEXP (operands[1], 1));
> +       operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
> +      }
>    }
>  )
> diff --git a/gcc/expr.c b/gcc/expr.c
> index 4c31521..88928aa 100644
> --- a/gcc/expr.c
> +++ b/gcc/expr.c
> @@ -7986,7 +7986,9 @@ expand_cond_expr_using_cmove (tree treeop0
> ATTRIBUTE_UNUSED,
>        op00 = expand_normal (treeop0);
>        op01 = const0_rtx;
>        comparison_code = NE;
> -      comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
> +      comparison_mode = GET_MODE (op00);
> +      if (comparison_mode == VOIDmode)
> +       comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
>      }
> 
>    if (GET_MODE (op1) != mode)
> diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
> index 2ca2278..733d583 100644
> --- a/gcc/ifcvt.c
> +++ b/gcc/ifcvt.c
> @@ -43,6 +43,7 @@
>  #include "vec.h"
>  #include "pointer-set.h"
>  #include "dbgcnt.h"
> +#include "ccmp.h"
> 
>  #ifndef HAVE_conditional_move
>  #define HAVE_conditional_move 0
> @@ -786,6 +787,9 @@ struct noce_if_info
> 
>    /* Estimated cost of the particular branch instruction.  */
>    int branch_cost;
> +
> +  /* The COND is a conditional compare or not.  */  bool ccmp_p;
>  };
> 
>  static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int);
@@ -
> 1407,9 +1411,16 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x,
> enum rtx_code code,
>        end_sequence ();
>      }
> 
> -  /* Don't even try if the comparison operands are weird.  */
> -  if (! general_operand (cmp_a, GET_MODE (cmp_a))
> -      || ! general_operand (cmp_b, GET_MODE (cmp_b)))
> +  /* Don't even try if the comparison operands are weird
> +     except conditional compare.  */
> +  if (if_info->ccmp_p)
> +    {
> +      if (!(GET_MODE_CLASS (GET_MODE (cmp_a)) == MODE_CC
> +           || GET_MODE_CLASS (GET_MODE (cmp_b)) == MODE_CC))
> +       return NULL_RTX;
> +    }
> +  else if (! general_operand (cmp_a, GET_MODE (cmp_a))
> +          || ! general_operand (cmp_b, GET_MODE (cmp_b)))
>      return NULL_RTX;
> 
>  #if HAVE_conditional_move
> @@ -1849,7 +1860,7 @@ noce_get_alt_condition (struct noce_if_info
> *if_info, rtx target,
>      }
> 
>    cond = canonicalize_condition (if_info->jump, cond, reverse,
> -                                earliest, target, false, true);
> +                                earliest, target, if_info->ccmp_p,
> + true);
>    if (! cond || ! reg_mentioned_p (target, cond))
>      return NULL;
> 
> @@ -2300,6 +2311,7 @@ noce_get_condition (rtx jump, rtx *earliest, bool
> then_else_reversed)  {
>    rtx cond, set, tmp;
>    bool reverse;
> +  int allow_cc_mode = false;
> 
>    if (! any_condjump_p (jump))
>      return NULL_RTX;
> @@ -2333,10 +2345,21 @@ noce_get_condition (rtx jump, rtx *earliest, bool
> then_else_reversed)
>        return cond;
>      }
> 
> +  /* For conditional compare, set ALLOW_CC_MODE to TRUE.  */  if
> + (targetm.gen_ccmp_first)
> +    {
> +      rtx prev = prev_nonnote_nondebug_insn (jump);
> +      if (prev
> +         && NONJUMP_INSN_P (prev)
> +         && BLOCK_FOR_INSN (prev) == BLOCK_FOR_INSN (jump)
> +         && ccmp_insn_p (prev))
> +       allow_cc_mode = true;
> +    }
> +
>    /* Otherwise, fall back on canonicalize_condition to do the dirty
>       work of manipulating MODE_CC values and COMPARE rtx codes.  */
>    tmp = canonicalize_condition (jump, cond, reverse, earliest,
> -                               NULL_RTX, false, true);
> +                               NULL_RTX, allow_cc_mode, true);
> 
>    /* We don't handle side-effects in the condition, like handling
>       REG_INC notes and making sure no duplicate conditions are emitted.
*/
> @@ -2577,6 +2600,11 @@ noce_process_if_block (struct noce_if_info
> *if_info)
>    if_info->a = a;
>    if_info->b = b;
> 
> +  if (targetm.gen_ccmp_first)
> +    if (GET_MODE_CLASS (GET_MODE (XEXP (if_info->cond, 0))) ==
> MODE_CC
> +       || GET_MODE_CLASS (GET_MODE (XEXP (if_info->cond, 1))) ==
> MODE_CC)
> +      if_info->ccmp_p = true;
> +
>    /* Try optimizations in some approximation of a useful order.  */
>    /* ??? Should first look to see if X is live incoming at all.  If it
>       isn't, we don't need anything but an unconditional set.  */
> 
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmn-csel-1.c
> b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-1.c
> new file mode 100644
> index 0000000..472c271
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-1.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +int foo (int a, int b, int c, int d)
> +{
> +  return a < b && c > -5 ? d : 7;
> +}
> +
> +/* { dg-final { scan-assembler "ccmn" } } */
> +/* { dg-final { scan-assembler "csel" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmn-csel-2.c
> b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-2.c
> new file mode 100644
> index 0000000..c7d41d5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-2.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +int foo (int a, int b, int c, int d)
> +{
> +  return a < b && c > -9 ? d : c;
> +}
> +
> +/* { dg-final { scan-assembler "ccmn" } } */
> +/* { dg-final { scan-assembler "csel" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmn-csel-3.c
> b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-3.c
> new file mode 100644
> index 0000000..9350e5d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-3.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +int foo (int a, int b, int c, int d)
> +{
> +  return a > b && c <= -2 ? 9 : 7;
> +}
> +
> +/* { dg-final { scan-assembler "ccmn" } } */
> +/* { dg-final { scan-assembler "csel" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-csel-1.c
> b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-1.c
> new file mode 100644
> index 0000000..2d0929f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-1.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +int foo (int a, int b, int c, int d)
> +{
> +  return a < b && c <= d ? d : 7;
> +}
> +
> +/* { dg-final { scan-assembler "ccmp" } } */
> +/* { dg-final { scan-assembler "csel" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-csel-2.c
> b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-2.c
> new file mode 100644
> index 0000000..978aa64
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-2.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +int foo (int a, int b, int c, int d)
> +{
> +  return a < b && c > d ? d : c;
> +}
> +
> +/* { dg-final { scan-assembler "ccmp" } } */
> +/* { dg-final { scan-assembler "csel" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-csel-3.c
> b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-3.c
> new file mode 100644
> index 0000000..7db1cd5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-3.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +int foo (int a, int b, int c, int d)
> +{
> +  return a > b && c <= d ? 9 : 7;
> +}
> +
> +/* { dg-final { scan-assembler "ccmp" } } */
> +/* { dg-final { scan-assembler "csel" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-csel-4.c
> b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-4.c
> new file mode 100644
> index 0000000..51b1ce8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-4.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +int foo (int a, int b, int c, int d)
> +{
> +  return (a > 0 && b < 7) ? c : d;
> +}
> +
> +/* { dg-final { scan-assembler "ccmp" } } */
> +/* { dg-final { scan-assembler "csel" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-csel-5.c
> b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-5.c
> new file mode 100644
> index 0000000..04d27fa
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-5.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +_Bool foo (int a, int b, _Bool c, _Bool d) {
> +  return (a > 0 && b < 7) ? c : d;
> +}
> +
> +/* { dg-final { scan-assembler "ccmp" } } */
> +/* { dg-final { scan-assembler "csel" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-cset-1.c
> b/gcc/testsuite/gcc.target/aarch64/ccmp-cset-1.c
> new file mode 100644
> index 0000000..fa3dd5b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-cset-1.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +int foo (int a, int b)
> +{
> +  return a > 0 && b < 7;
> +}
> +
> +/* { dg-final { scan-assembler "ccmp" } } */
> +/* { dg-final { scan-assembler "cset" } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-cset-2.c
> b/gcc/testsuite/gcc.target/aarch64/ccmp-cset-2.c
> new file mode 100644
> index 0000000..afcd4d0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-cset-2.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options " -O2 " } */
> +
> +_Bool foo (int a, int b)
> +{
> +  return a > 0 && b < 7;
> +}
> +
> +/* { dg-final { scan-assembler "ccmp" } } */
> +/* { dg-final { scan-assembler "cset" } } */
> 
> On 23 June 2014 15:51,  <pins...@gmail.com> wrote:
> >
> >
> >> On Jun 23, 2014, at 12:37 AM, Zhenqiang Chen
> <zhenqiang.c...@linaro.org> wrote:
> >>
> >>> On 23 June 2014 15:09, Andrew Pinski <pins...@gmail.com> wrote:
> >>> On Mon, Jun 23, 2014 at 12:01 AM, Zhenqiang Chen
> >>> <zhenqiang.c...@linaro.org> wrote:
> >>>> Hi,
> >>>>
> >>>> The patch enhances ifcvt to handle conditional compare instruction
> >>>> (ccmp) to make it work with cmov. For ccmp, ALLOW_CC_MODE is set
> to
> >>>> TRUE when calling canonicalize_condition. And the backend does not
> >>>> need to generate additional "compare (CC, 0)" for it.
> >>>>
> >>>> Bootstrap and no check regression on qemu.
> >>>>
> >>>> OK for trunk?
> >>>>
> >>>> Thanks!
> >>>> -Zhenqiang
> >>>>
> >>>> ChangeLog:
> >>>> 2014-06-23  Zhenqiang Chen  <zhenqiang.c...@linaro.org>
> >>>>
> >>>>        * config/aarch64/aarch64.md (mov<mode>cc): Handle ccmp_cc.
> >>>>        * ifcvt.c: #include "ccmp.h".
> >>>>        (struct noce_if_info): Add a new field ccmp_p.
> >>>>        (noce_emit_cmove): Allow ccmp condition.
> >>>>        (noce_get_alt_condition): Call canonicalize_condition with
ccmp_p.
> >>>>        (noce_get_condition): Set ALLOW_CC_MODE to TRUE for ccmp.
> >>>>        (noce_process_if_block): Set ccmp_p for ccmp.
> >>>>
> >>>> testsuite/ChangeLog:
> >>>> 2014-06-23  Zhenqiang Chen  <zhenqiang.c...@linaro.org>
> >>>>
> >>>>        * gcc.target/aarch64/ccmn-csel-1.c: New testcase.
> >>>>        * gcc.target/aarch64/ccmn-csel-2.c: New testcase.
> >>>>        * gcc.target/aarch64/ccmn-csel-3.c: New testcase.
> >>>>        * gcc.target/aarch64/ccmp-csel-1.c: New testcase.
> >>>>        * gcc.target/aarch64/ccmp-csel-2.c: New testcase.
> >>>>        * gcc.target/aarch64/ccmp-csel-3.c: New testcase.
> >>>>
> >>>> diff --git a/gcc/config/aarch64/aarch64.md
> >>>> b/gcc/config/aarch64/aarch64.md index fcc5559..82cc561 100644
> >>>> --- a/gcc/config/aarch64/aarch64.md
> >>>> +++ b/gcc/config/aarch64/aarch64.md
> >>>> @@ -2459,15 +2459,19 @@
> >>>>                           (match_operand:ALLI 3 "register_operand"
"")))]
> >>>>   ""
> >>>>   {
> >>>> -    rtx ccreg;
> >>>>     enum rtx_code code = GET_CODE (operands[1]);
> >>>>
> >>>>     if (code == UNEQ || code == LTGT)
> >>>>       FAIL;
> >>>>
> >>>> -    ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
> >>>> -                                 XEXP (operands[1], 1));
> >>>> -    operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg,
> const0_rtx);
> >>>> +    if (!ccmp_cc_register (XEXP (operands[1], 0),
> >>>> +                          GET_MODE (XEXP (operands[1], 0))))
> >>>> +      {
> >>>> +       rtx ccreg;
> >>>> +       ccreg = aarch64_gen_compare_reg (code, XEXP (operands[1], 0),
> >>>> +                                        XEXP (operands[1], 1));
> >>>> +       operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg,
> const0_rtx);
> >>>> +      }
> >>>>   }
> >>>> )
> >>>>
> >>>
> >>>
> >>> You should do the same thing for the FP one.  The change to
> >>> aarch64.md is exactly the same patch which I came up with.
> >>
> >> Thanks for the comments.
> >>
> >> For AARCH64, we can mix INT and FP compares. But FP compare would be
> >> slower than INT compare.
> >
> > One point is that this is not about fp compares but rather moving of fp
> register. The fp pattern is used for that.  So something like this would
fail/ice:
> > double f(double a, double b, int c, int d) {
> >   return c>10&&d>20?a:b;
> > }
> >
> > Thanks,
> > Andrew
> >
> >
> >
> >>
> >> CMP
> >> FCCMP
> >>
> >> FCMP
> >> CCMP
> >>
> >> FCMP
> >> FCCMP
> >>
> >> I have no enough resource to collect benchmark results to approve
> >> them valuable. So the patches did not handle FP at all. If you had
> >> approved CCMP for FP valuable, I will work out a separate patch to
> support it.
> >> Or you can share your patches.
> >
> > I need to l
> >
> >>
> >> Thanks!
> >> -Zhenqiang
> >>
> >>> For the rest I actually I have a late phi-opt pass which does the
> >>> conversion into COND_EXPR.  That is I don't change ifcvt at all.
> >>>
> >>> And then I needed two more patches after that to get conditional
> >>> compares to work with cmov's.
> >>
> >> Thanks. Any patch to improve ccmp is welcome.
> >>
> >> -Zhenqiang
> >>
> >>> The following patch which fixes up expand_cond_expr_using_cmove to
> >>> handle CCmode correctly:
> >>> --- a/gcc/expr.c
> >>> +++ b/gcc/expr.c
> >>> @@ -7989,7 +7989,9 @@ expand_cond_expr_using_cmove (tree
> treeop0
> >>> ATTRIBUTE_UNUSED,
> >>>       op00 = expand_normal (treeop0);
> >>>       op01 = const0_rtx;
> >>>       comparison_code = NE;
> >>> -      comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
> >>> +      comparison_mode = GET_MODE (op00);
> >>> +      if (comparison_mode == VOIDmode)
> >>> +       comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
> >>>     }
> >>>
> >>>   if (GET_MODE (op1) != mode)
> >>>
> >>>
> >>> --- CUT ---
> >>> And then this one to have ccmp to be expanded from the tree level:
> >>> index cfc4a16..056e9b0 100644 (file)
> >>> --- a/gcc/expr.c
> >>> +++ b/gcc/expr.c
> >>> @@ -9300,26 +9300,36 @@ used_in_cond_stmt_p (tree exp)
> >>>   imm_use_iterator ui;
> >>>   gimple use_stmt;
> >>>   FOR_EACH_IMM_USE_STMT (use_stmt, ui, exp)
> >>> -    if (gimple_code (use_stmt) == GIMPLE_COND)
> >>> -      {
> >>> -       tree op1 = gimple_cond_rhs (use_stmt);
> >>> -       /* TBD: If we can convert all
> >>> -           _Bool t;
> >>> +    {
> >>> +      if (gimple_code (use_stmt) == GIMPLE_COND)
> >>> +       {
> >>> +         tree op1 = gimple_cond_rhs (use_stmt);
> >>> +         /* TBD: If we can convert all
> >>> +             _Bool t;
> >>>
> >>> -           if (t == 1)
> >>> -             goto <bb 3>;
> >>> -           else
> >>> -             goto <bb 4>;
> >>> -          to
> >>> -           if (t != 0)
> >>> -             goto <bb 3>;
> >>> -           else
> >>> -             goto <bb 4>;
> >>> -          we can remove the following check.  */
> >>> -       if (integer_zerop (op1))
> >>> -         expand_cond = true;
> >>> -       BREAK_FROM_IMM_USE_STMT (ui);
> >>> -      }
> >>> +             if (t == 1)
> >>> +               goto <bb 3>;
> >>> +             else
> >>> +               goto <bb 4>;
> >>> +            to
> >>> +             if (t != 0)
> >>> +               goto <bb 3>;
> >>> +             else
> >>> +               goto <bb 4>;
> >>> +            we can remove the following check.  */
> >>> +         if (integer_zerop (op1))
> >>> +           expand_cond = true;
> >>> +         BREAK_FROM_IMM_USE_STMT (ui);
> >>> +       }
> >>> +      /* a = EXP ? b : c is also an use in conditional
> >>> +         statement. */
> >>> +      else if (gimple_code (use_stmt) == GIMPLE_ASSIGN
> >>> +              && gimple_expr_code (use_stmt) == COND_EXPR)
> >>> +       {
> >>> +         if (gimple_assign_rhs1 (use_stmt) == exp)
> >>> +           expand_cond = true;
> >>> +       }
> >>> +    }
> >>>   return expand_cond;
> >>> }
> >>>
> >>> Thanks,
> >>> Andrew Pinski
> >>>
> >>>
> >>>> diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 2ca2278..8ee1266
> >>>> 100644
> >>>> --- a/gcc/ifcvt.c
> >>>> +++ b/gcc/ifcvt.c
> >>>> @@ -43,6 +43,7 @@
> >>>> #include "vec.h"
> >>>> #include "pointer-set.h"
> >>>> #include "dbgcnt.h"
> >>>> +#include "ccmp.h"
> >>>>
> >>>> #ifndef HAVE_conditional_move
> >>>> #define HAVE_conditional_move 0
> >>>> @@ -786,6 +787,9 @@ struct noce_if_info
> >>>>
> >>>>   /* Estimated cost of the particular branch instruction.  */
> >>>>   int branch_cost;
> >>>> +
> >>>> +  /* The COND is a conditional compare or not.  */  bool ccmp_p;
> >>>> };
> >>>>
> >>>> static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int,
> >>>> int); @@ -1407,9 +1411,16 @@ noce_emit_cmove (struct noce_if_info
> >>>> *if_info, rtx x, enum rtx_code code,
> >>>>       end_sequence ();
> >>>>     }
> >>>>
> >>>> -  /* Don't even try if the comparison operands are weird.  */
> >>>> -  if (! general_operand (cmp_a, GET_MODE (cmp_a))
> >>>> -      || ! general_operand (cmp_b, GET_MODE (cmp_b)))
> >>>> +  /* Don't even try if the comparison operands are weird
> >>>> +     except conditional compare.  */  if (if_info->ccmp_p)
> >>>> +    {
> >>>> +      if (!(GET_MODE_CLASS (GET_MODE (cmp_a)) == MODE_CC
> >>>> +           || GET_MODE_CLASS (GET_MODE (cmp_b)) == MODE_CC))
> >>>> +       return NULL_RTX;
> >>>> +    }
> >>>> +  else if (! general_operand (cmp_a, GET_MODE (cmp_a))
> >>>> +          || ! general_operand (cmp_b, GET_MODE (cmp_b)))
> >>>>     return NULL_RTX;
> >>>>
> >>>> #if HAVE_conditional_move
> >>>> @@ -1849,7 +1860,7 @@ noce_get_alt_condition (struct noce_if_info
> >>>> *if_info, rtx target,
> >>>>     }
> >>>>
> >>>>   cond = canonicalize_condition (if_info->jump, cond, reverse,
> >>>> -                                earliest, target, false, true);
> >>>> +                                earliest, target, if_info->ccmp_p,
> >>>> + true);
> >>>>   if (! cond || ! reg_mentioned_p (target, cond))
> >>>>     return NULL;
> >>>>
> >>>> @@ -2300,6 +2311,7 @@ noce_get_condition (rtx jump, rtx *earliest,
> >>>> bool then_else_reversed) {
> >>>>   rtx cond, set, tmp;
> >>>>   bool reverse;
> >>>> +  int allow_cc_mode = false;
> >>>>
> >>>>   if (! any_condjump_p (jump))
> >>>>     return NULL_RTX;
> >>>> @@ -2333,10 +2345,21 @@ noce_get_condition (rtx jump, rtx
> >>>> *earliest, bool then_else_reversed)
> >>>>       return cond;
> >>>>     }
> >>>>
> >>>> +  /* For conditional compare, set ALLOW_CC_MODE to TRUE.  */  if
> >>>> + (targetm.gen_ccmp_first)
> >>>> +    {
> >>>> +      rtx prev = prev_nonnote_nondebug_insn (jump);
> >>>> +      if (prev
> >>>> +         && NONJUMP_INSN_P (prev)
> >>>> +         && BLOCK_FOR_INSN (prev) == BLOCK_FOR_INSN (jump)
> >>>> +         && ccmp_insn_p (prev))
> >>>> +       allow_cc_mode = true;
> >>>> +    }
> >>>> +
> >>>>   /* Otherwise, fall back on canonicalize_condition to do the dirty
> >>>>      work of manipulating MODE_CC values and COMPARE rtx codes.  */
> >>>>   tmp = canonicalize_condition (jump, cond, reverse, earliest,
> >>>> -                               NULL_RTX, false, true);
> >>>> +                               NULL_RTX, allow_cc_mode, true);
> >>>>
> >>>>   /* We don't handle side-effects in the condition, like handling
> >>>>      REG_INC notes and making sure no duplicate conditions are
> >>>> emitted.  */ @@ -2577,6 +2600,11 @@ noce_process_if_block (struct
> noce_if_info *if_info)
> >>>>   if_info->a = a;
> >>>>   if_info->b = b;
> >>>>
> >>>> +  if (targetm.gen_ccmp_first)
> >>>> +    if (GET_MODE_CLASS (GET_MODE (XEXP (if_info->cond, 0))) ==
> MODE_CC
> >>>> +       || GET_MODE_CLASS (GET_MODE (XEXP (if_info->cond, 1))) ==
> MODE_CC)
> >>>> +      if_info->ccmp_p = true;
> >>>> +
> >>>>   /* Try optimizations in some approximation of a useful order.  */
> >>>>   /* ??? Should first look to see if X is live incoming at all.  If
it
> >>>>      isn't, we don't need anything but an unconditional set.  */
> >>>> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmn-csel-1.c
> >>>> b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-1.c
> >>>> new file mode 100644
> >>>> index 0000000..472c271
> >>>> --- /dev/null
> >>>> +++ b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-1.c
> >>>> @@ -0,0 +1,10 @@
> >>>> +/* { dg-do compile } */
> >>>> +/* { dg-options " -O2 " } */
> >>>> +
> >>>> +int foo (int a, int b, int c, int d) {
> >>>> +  return a < b && c > -5 ? d : 7;
> >>>> +}
> >>>> +
> >>>> +/* { dg-final { scan-assembler "ccmn" } } */
> >>>> +/* { dg-final { scan-assembler "csel" } } */
> >>>> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmn-csel-2.c
> >>>> b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-2.c
> >>>> new file mode 100644
> >>>> index 0000000..c7d41d5
> >>>> --- /dev/null
> >>>> +++ b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-2.c
> >>>> @@ -0,0 +1,10 @@
> >>>> +/* { dg-do compile } */
> >>>> +/* { dg-options " -O2 " } */
> >>>> +
> >>>> +int foo (int a, int b, int c, int d) {
> >>>> +  return a < b && c > -9 ? d : c;
> >>>> +}
> >>>> +
> >>>> +/* { dg-final { scan-assembler "ccmn" } } */
> >>>> +/* { dg-final { scan-assembler "csel" } } */
> >>>> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmn-csel-3.c
> >>>> b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-3.c
> >>>> new file mode 100644
> >>>> index 0000000..9350e5d
> >>>> --- /dev/null
> >>>> +++ b/gcc/testsuite/gcc.target/aarch64/ccmn-csel-3.c
> >>>> @@ -0,0 +1,10 @@
> >>>> +/* { dg-do compile } */
> >>>> +/* { dg-options " -O2 " } */
> >>>> +
> >>>> +int foo (int a, int b, int c, int d) {
> >>>> +  return a > b && c <= -2 ? 9 : 7; }
> >>>> +
> >>>> +/* { dg-final { scan-assembler "ccmn" } } */
> >>>> +/* { dg-final { scan-assembler "csel" } } */
> >>>> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-csel-1.c
> >>>> b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-1.c
> >>>> new file mode 100644
> >>>> index 0000000..2d0929f
> >>>> --- /dev/null
> >>>> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-1.c
> >>>> @@ -0,0 +1,10 @@
> >>>> +/* { dg-do compile } */
> >>>> +/* { dg-options " -O2 " } */
> >>>> +
> >>>> +int foo (int a, int b, int c, int d) {
> >>>> +  return a < b && c <= d ? d : 7;
> >>>> +}
> >>>> +
> >>>> +/* { dg-final { scan-assembler "ccmp" } } */
> >>>> +/* { dg-final { scan-assembler "csel" } } */
> >>>> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-csel-2.c
> >>>> b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-2.c
> >>>> new file mode 100644
> >>>> index 0000000..978aa64
> >>>> --- /dev/null
> >>>> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-2.c
> >>>> @@ -0,0 +1,10 @@
> >>>> +/* { dg-do compile } */
> >>>> +/* { dg-options " -O2 " } */
> >>>> +
> >>>> +int foo (int a, int b, int c, int d) {
> >>>> +  return a < b && c > d ? d : c;
> >>>> +}
> >>>> +
> >>>> +/* { dg-final { scan-assembler "ccmp" } } */
> >>>> +/* { dg-final { scan-assembler "csel" } } */
> >>>> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp-csel-3.c
> >>>> b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-3.c
> >>>> new file mode 100644
> >>>> index 0000000..7db1cd5
> >>>> --- /dev/null
> >>>> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp-csel-3.c
> >>>> @@ -0,0 +1,10 @@
> >>>> +/* { dg-do compile } */
> >>>> +/* { dg-options " -O2 " } */
> >>>> +
> >>>> +int foo (int a, int b, int c, int d) {
> >>>> +  return a > b && c <= d ? 9 : 7;
> >>>> +}
> >>>> +
> >>>> +/* { dg-final { scan-assembler "ccmp" } } */
> >>>> +/* { dg-final { scan-assembler "csel" } } */

Attachment: 10-ifcvt.patch
Description: Binary data

Reply via email to