summaryrefslogtreecommitdiff
path: root/gcc/ccmp.c
diff options
context:
space:
mode:
authorWilco Dijkstra <wdijkstr@arm.com>2016-01-19 14:14:56 +0000
committerJiong Wang <jiwang@gcc.gnu.org>2016-01-19 14:14:56 +0000
commit078fe40a489e7a4f62553feab15288066906d146 (patch)
tree8b9c7e2731d1acece79c506065da6b6bbed8eed0 /gcc/ccmp.c
parent786298dc13355be8942ad82002d4c675e7255299 (diff)
[PATCH 4/4] Add CCMP selection based on rtx costs
2015-01-19 Wilco Dijkstra <wdijkstr@arm.com> Jiong Wang <jiong.wang@arm.com> gcc/ * ccmp.c (expand_ccmp_expr_1): Cost the instruction sequences generated from different expand order. gcc/testsuite/ * gcc.target/aarch64/ccmp_1.c: Add new tests. Co-Authored-By: Jiong Wang <jiong.wang@arm.com> From-SVN: r232565
Diffstat (limited to 'gcc/ccmp.c')
-rw-r--r--gcc/ccmp.c65
1 files changed, 51 insertions, 14 deletions
diff --git a/gcc/ccmp.c b/gcc/ccmp.c
index a393d3546f3..9e49d1e4e4a 100644
--- a/gcc/ccmp.c
+++ b/gcc/ccmp.c
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-outof-ssa.h"
#include "cfgexpand.h"
#include "ccmp.h"
+#include "predict.h"
/* The following functions expand conditional compare (CCMP) instructions.
Here is a short description about the over all algorithm:
@@ -72,7 +73,7 @@ ccmp_candidate_p (gimple *g)
tree rhs = gimple_assign_rhs_to_tree (g);
tree lhs, op0, op1;
gimple *gs0, *gs1;
- enum tree_code tcode, tcode0, tcode1;
+ tree_code tcode, tcode0, tcode1;
tcode = TREE_CODE (rhs);
if (tcode != BIT_AND_EXPR && tcode != BIT_IOR_EXPR)
@@ -119,10 +120,10 @@ ccmp_candidate_p (gimple *g)
PREP_SEQ returns all insns to prepare opearands for compare.
GEN_SEQ returns all compare insns. */
static rtx
-expand_ccmp_next (gimple *g, enum tree_code code, rtx prev,
+expand_ccmp_next (gimple *g, tree_code code, rtx prev,
rtx *prep_seq, rtx *gen_seq)
{
- enum rtx_code rcode;
+ rtx_code rcode;
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)));
gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
@@ -149,13 +150,15 @@ expand_ccmp_next (gimple *g, enum tree_code code, rtx prev,
static rtx
expand_ccmp_expr_1 (gimple *g, rtx *prep_seq, rtx *gen_seq)
{
+ rtx prep_seq_1, gen_seq_1;
+ rtx prep_seq_2, gen_seq_2;
tree exp = gimple_assign_rhs_to_tree (g);
- enum tree_code code = TREE_CODE (exp);
+ tree_code code = TREE_CODE (exp);
gimple *gs0 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 0));
gimple *gs1 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 1));
rtx tmp;
- enum tree_code code0 = gimple_assign_rhs_code (gs0);
- enum tree_code code1 = gimple_assign_rhs_code (gs1);
+ tree_code code0 = gimple_assign_rhs_code (gs0);
+ tree_code code1 = gimple_assign_rhs_code (gs1);
gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
gcc_assert (gs0 && gs1 && is_gimple_assign (gs0) && is_gimple_assign (gs1));
@@ -164,19 +167,53 @@ expand_ccmp_expr_1 (gimple *g, rtx *prep_seq, rtx *gen_seq)
{
if (TREE_CODE_CLASS (code1) == tcc_comparison)
{
- int unsignedp0;
- enum rtx_code rcode0;
+ int unsignedp0, unsignedp1;
+ rtx_code rcode0, rcode1;
+ int speed_p = optimize_insn_for_speed_p ();
+ rtx tmp2, ret, ret2;
+ unsigned cost1 = MAX_COST;
+ unsigned cost2 = MAX_COST;
unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0)));
+ unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs1)));
rcode0 = get_rtx_code (code0, unsignedp0);
+ rcode1 = get_rtx_code (code1, unsignedp1);
- tmp = targetm.gen_ccmp_first (prep_seq, gen_seq, rcode0,
+ tmp = targetm.gen_ccmp_first (&prep_seq_1, &gen_seq_1, rcode0,
gimple_assign_rhs1 (gs0),
gimple_assign_rhs2 (gs0));
- if (!tmp)
+
+ tmp2 = targetm.gen_ccmp_first (&prep_seq_2, &gen_seq_2, rcode1,
+ gimple_assign_rhs1 (gs1),
+ gimple_assign_rhs2 (gs1));
+
+ if (!tmp && !tmp2)
return NULL_RTX;
- return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq);
+ if (tmp != NULL)
+ {
+ ret = expand_ccmp_next (gs1, code, tmp, &prep_seq_1, &gen_seq_1);
+ cost1 = seq_cost (safe_as_a <rtx_insn *> (prep_seq_1), speed_p);
+ cost1 += seq_cost (safe_as_a <rtx_insn *> (gen_seq_1), speed_p);
+ }
+ if (tmp2 != NULL)
+ {
+ ret2 = expand_ccmp_next (gs0, code, tmp2, &prep_seq_2,
+ &gen_seq_2);
+ cost2 = seq_cost (safe_as_a <rtx_insn *> (prep_seq_2), speed_p);
+ cost2 += seq_cost (safe_as_a <rtx_insn *> (gen_seq_2), speed_p);
+ }
+
+ if (cost2 < cost1)
+ {
+ *prep_seq = prep_seq_2;
+ *gen_seq = gen_seq_2;
+ return ret2;
+ }
+
+ *prep_seq = prep_seq_1;
+ *gen_seq = gen_seq_1;
+ return ret;
}
else
{
@@ -230,8 +267,8 @@ expand_ccmp_expr (gimple *g)
if (tmp)
{
- enum insn_code icode;
- enum machine_mode cc_mode = CCmode;
+ insn_code icode;
+ machine_mode cc_mode = CCmode;
tree lhs = gimple_assign_lhs (g);
rtx_code cmp_code = GET_CODE (tmp);
@@ -241,7 +278,7 @@ expand_ccmp_expr (gimple *g)
icode = optab_handler (cstore_optab, cc_mode);
if (icode != CODE_FOR_nothing)
{
- enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
+ machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
rtx target = gen_reg_rtx (mode);
emit_insn (prep_seq);