From: Andrew Pinski <pinskia@gmail.com>
To: Zhenqiang Chen <zhenqiang.chen@linaro.org>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Subject: Re: [PATCH, 10/10] aarch64: Handle ccmp in ifcvt to make it work with cmov
Date: Mon, 23 Jun 2014 07:09:00 -0000 [thread overview]
Message-ID: <CA+=Sn1mk_2eifK8-idtuA1nzoGNYahZ1N3o0yPBJZ8+X8K8ipg@mail.gmail.com> (raw)
In-Reply-To: <CACgzC7AOZh5tFio6=Sx0RmHvjkY7UWCHEJfbQsHFvdHv61QXPg@mail.gmail.com>
On Mon, Jun 23, 2014 at 12:01 AM, Zhenqiang Chen
<zhenqiang.chen@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.chen@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.chen@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.
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.
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" } } */
next prev parent reply other threads:[~2014-06-23 7:09 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-23 7:02 Zhenqiang Chen
2014-06-23 7:09 ` Andrew Pinski [this message]
2014-06-23 7:12 ` Andrew Pinski
2014-06-23 7:37 ` Zhenqiang Chen
2014-06-23 7:51 ` pinskia
2014-07-04 6:54 ` Zhenqiang Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CA+=Sn1mk_2eifK8-idtuA1nzoGNYahZ1N3o0yPBJZ8+X8K8ipg@mail.gmail.com' \
--to=pinskia@gmail.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=zhenqiang.chen@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).