Commit f580a969 by Steve Ellcey Committed by Steve Ellcey

ccmp.c (ccmp_tree_comparison_p): New function.

2017-06-29  Steve Ellcey  <sellcey@cavium.com>

	* ccmp.c (ccmp_tree_comparison_p): New function.
	(ccmp_candidate_p): Update to use above function.
	(get_compare_parts): New function.
	(expand_ccmp_next): Update to use new functions.
	(expand_ccmp_expr_1): Take tree arg instead of gimple, update to use
	new functions.
	(expand_ccmp_expr): Pass tree instead of gimple to expand_ccmp_expr_1,
	take mode as argument.
	* ccmp.h (expand_ccmp_expr): Add mode as argument.
	* expr.c (expand_expr_real_1): Pass mode as argument.

From-SVN: r249805
parent be3b7dcf
2017-06-29 Steve Ellcey <sellcey@cavium.com>
* ccmp.c (ccmp_tree_comparison_p): New function.
(ccmp_candidate_p): Update to use above function.
(get_compare_parts): New function.
(expand_ccmp_next): Update to use new functions.
(expand_ccmp_expr_1): Take tree arg instead of gimple, update to use
new functions.
(expand_ccmp_expr): Pass tree instead of gimple to expand_ccmp_expr_1,
take mode as argument.
* ccmp.h (expand_ccmp_expr): Add mode as argument.
* expr.c (expand_expr_real_1): Pass mode as argument.
2017-06-29 Segher Boessenkool <segher@kernel.crashing.org> 2017-06-29 Segher Boessenkool <segher@kernel.crashing.org>
* combine.c (combine_instructions): Print insns to dump_file, together * combine.c (combine_instructions): Print insns to dump_file, together
......
...@@ -38,6 +38,29 @@ along with GCC; see the file COPYING3. If not see ...@@ -38,6 +38,29 @@ along with GCC; see the file COPYING3. If not see
#include "ccmp.h" #include "ccmp.h"
#include "predict.h" #include "predict.h"
/* Check whether T is a simple boolean variable or a SSA name
set by a comparison operator in the same basic block. */
static bool
ccmp_tree_comparison_p (tree t, basic_block bb)
{
gimple *g = get_gimple_for_ssa_name (t);
tree_code tcode;
/* If we have a boolean variable allow it and generate a compare
to zero reg when expanding. */
if (!g)
return (TREE_CODE (TREE_TYPE (t)) == BOOLEAN_TYPE);
/* Check to see if SSA name is set by a comparison operator in
the same basic block. */
if (!is_gimple_assign (g))
return false;
if (bb != gimple_bb (g))
return false;
tcode = gimple_assign_rhs_code (g);
return TREE_CODE_CLASS (tcode) == tcc_comparison;
}
/* The following functions expand conditional compare (CCMP) instructions. /* The following functions expand conditional compare (CCMP) instructions.
Here is a short description about the over all algorithm: Here is a short description about the over all algorithm:
* ccmp_candidate_p is used to identify the CCMP candidate * ccmp_candidate_p is used to identify the CCMP candidate
...@@ -71,49 +94,69 @@ along with GCC; see the file COPYING3. If not see ...@@ -71,49 +94,69 @@ along with GCC; see the file COPYING3. If not see
static bool static bool
ccmp_candidate_p (gimple *g) ccmp_candidate_p (gimple *g)
{ {
tree rhs = gimple_assign_rhs_to_tree (g); tree rhs;
tree lhs, op0, op1; tree lhs, op0, op1;
gimple *gs0, *gs1; gimple *gs0, *gs1;
tree_code tcode, tcode0, tcode1; tree_code tcode;
tcode = TREE_CODE (rhs); basic_block bb;
if (!g)
return false;
rhs = gimple_assign_rhs_to_tree (g);
tcode = TREE_CODE (rhs);
if (tcode != BIT_AND_EXPR && tcode != BIT_IOR_EXPR) if (tcode != BIT_AND_EXPR && tcode != BIT_IOR_EXPR)
return false; return false;
lhs = gimple_assign_lhs (g); lhs = gimple_assign_lhs (g);
op0 = TREE_OPERAND (rhs, 0); op0 = TREE_OPERAND (rhs, 0);
op1 = TREE_OPERAND (rhs, 1); op1 = TREE_OPERAND (rhs, 1);
bb = gimple_bb (g);
if ((TREE_CODE (op0) != SSA_NAME) || (TREE_CODE (op1) != SSA_NAME) if ((TREE_CODE (op0) != SSA_NAME) || (TREE_CODE (op1) != SSA_NAME)
|| !has_single_use (lhs)) || !has_single_use (lhs))
return false; return false;
gs0 = get_gimple_for_ssa_name (op0); gs0 = get_gimple_for_ssa_name (op0); /* gs0 may be NULL */
gs1 = get_gimple_for_ssa_name (op1); gs1 = get_gimple_for_ssa_name (op1); /* gs1 may be NULL */
if (!gs0 || !gs1 || !is_gimple_assign (gs0) || !is_gimple_assign (gs1)
/* g, gs0 and gs1 must be in the same basic block, since current stage
is out-of-ssa. We can not guarantee the correctness when forwording
the gs0 and gs1 into g whithout DATAFLOW analysis. */
|| gimple_bb (gs0) != gimple_bb (gs1)
|| gimple_bb (gs0) != gimple_bb (g))
return false;
tcode0 = gimple_assign_rhs_code (gs0); if (ccmp_tree_comparison_p (op0, bb) && ccmp_tree_comparison_p (op1, bb))
tcode1 = gimple_assign_rhs_code (gs1);
if (TREE_CODE_CLASS (tcode0) == tcc_comparison
&& TREE_CODE_CLASS (tcode1) == tcc_comparison)
return true; return true;
if (TREE_CODE_CLASS (tcode0) == tcc_comparison if (ccmp_tree_comparison_p (op0, bb) && ccmp_candidate_p (gs1))
&& ccmp_candidate_p (gs1))
return true; return true;
else if (TREE_CODE_CLASS (tcode1) == tcc_comparison if (ccmp_tree_comparison_p (op1, bb) && ccmp_candidate_p (gs0))
&& ccmp_candidate_p (gs0))
return true; return true;
/* We skip ccmp_candidate_p (gs1) && ccmp_candidate_p (gs0) since /* We skip ccmp_candidate_p (gs1) && ccmp_candidate_p (gs0) since
there is no way to set the CC flag. */ there is no way to set and maintain the CC flag on both sides of
the logical operator at the same time. */
return false; return false;
} }
/* Extract the comparison we want to do from the tree. */
void
get_compare_parts (tree t, int *up, rtx_code *rcode,
tree *rhs1, tree *rhs2)
{
tree_code code;
gimple *g = get_gimple_for_ssa_name (t);
if (g)
{
*up = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)));
code = gimple_assign_rhs_code (g);
*rcode = get_rtx_code (code, *up);
*rhs1 = gimple_assign_rhs1 (g);
*rhs2 = gimple_assign_rhs2 (g);
}
else
{
/* If g is not a comparison operator create a compare to zero. */
*up = 1;
*rcode = NE;
*rhs1 = t;
*rhs2 = build_zero_cst (TREE_TYPE (t));
}
}
/* PREV is a comparison with the CC register which represents the /* PREV is a comparison with the CC register which represents the
result of the previous CMP or CCMP. The function expands the result of the previous CMP or CCMP. The function expands the
next compare based on G which is ANDed/ORed with the previous next compare based on G which is ANDed/ORed with the previous
...@@ -121,20 +164,16 @@ ccmp_candidate_p (gimple *g) ...@@ -121,20 +164,16 @@ ccmp_candidate_p (gimple *g)
PREP_SEQ returns all insns to prepare opearands for compare. PREP_SEQ returns all insns to prepare opearands for compare.
GEN_SEQ returns all compare insns. */ GEN_SEQ returns all compare insns. */
static rtx static rtx
expand_ccmp_next (gimple *g, tree_code code, rtx prev, expand_ccmp_next (tree op, tree_code code, rtx prev,
rtx_insn **prep_seq, rtx_insn **gen_seq) rtx_insn **prep_seq, rtx_insn **gen_seq)
{ {
rtx_code rcode; rtx_code rcode;
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g))); int unsignedp;
tree rhs1, rhs2;
gcc_assert (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
rcode = get_rtx_code (gimple_assign_rhs_code (g), unsignedp);
get_compare_parts(op, &unsignedp, &rcode, &rhs1, &rhs2);
return targetm.gen_ccmp_next (prep_seq, gen_seq, prev, rcode, return targetm.gen_ccmp_next (prep_seq, gen_seq, prev, rcode,
gimple_assign_rhs1 (g), rhs1, rhs2, get_rtx_code (code, 0));
gimple_assign_rhs2 (g),
get_rtx_code (code, 0));
} }
/* Expand conditional compare gimple G. A typical CCMP sequence is like: /* Expand conditional compare gimple G. A typical CCMP sequence is like:
...@@ -153,39 +192,42 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq) ...@@ -153,39 +192,42 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
{ {
tree exp = gimple_assign_rhs_to_tree (g); tree exp = gimple_assign_rhs_to_tree (g);
tree_code code = TREE_CODE (exp); tree_code code = TREE_CODE (exp);
gimple *gs0 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 0)); basic_block bb = gimple_bb (g);
gimple *gs1 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 1));
tree op0 = TREE_OPERAND (exp, 0);
tree op1 = TREE_OPERAND (exp, 1);
gimple *gs0 = get_gimple_for_ssa_name (op0);
gimple *gs1 = get_gimple_for_ssa_name (op1);
rtx tmp; rtx tmp;
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 (code == BIT_AND_EXPR || code == BIT_IOR_EXPR);
gcc_assert (gs0 && gs1 && is_gimple_assign (gs0) && is_gimple_assign (gs1));
if (TREE_CODE_CLASS (code0) == tcc_comparison) if (ccmp_tree_comparison_p (op0, bb))
{ {
if (TREE_CODE_CLASS (code1) == tcc_comparison) if (ccmp_tree_comparison_p (op1, bb))
{ {
int unsignedp0, unsignedp1; int unsignedp0, unsignedp1;
rtx_code rcode0, rcode1; rtx_code rcode0, rcode1;
tree logical_op0_rhs1, logical_op0_rhs2;
tree logical_op1_rhs1, logical_op1_rhs2;
int speed_p = optimize_insn_for_speed_p (); int speed_p = optimize_insn_for_speed_p ();
rtx tmp2 = NULL_RTX, ret = NULL_RTX, ret2 = NULL_RTX; rtx tmp2 = NULL_RTX, ret = NULL_RTX, ret2 = NULL_RTX;
unsigned cost1 = MAX_COST; unsigned cost1 = MAX_COST;
unsigned cost2 = MAX_COST; unsigned cost2 = MAX_COST;
unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs0))); get_compare_parts (op0, &unsignedp0, &rcode0,
unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (gs1))); &logical_op0_rhs1, &logical_op0_rhs2);
rcode0 = get_rtx_code (code0, unsignedp0);
rcode1 = get_rtx_code (code1, unsignedp1); get_compare_parts (op1, &unsignedp1, &rcode1,
&logical_op1_rhs1, &logical_op1_rhs2);
rtx_insn *prep_seq_1, *gen_seq_1; rtx_insn *prep_seq_1, *gen_seq_1;
tmp = targetm.gen_ccmp_first (&prep_seq_1, &gen_seq_1, rcode0, tmp = targetm.gen_ccmp_first (&prep_seq_1, &gen_seq_1, rcode0,
gimple_assign_rhs1 (gs0), logical_op0_rhs1, logical_op0_rhs2);
gimple_assign_rhs2 (gs0));
if (tmp != NULL) if (tmp != NULL)
{ {
ret = expand_ccmp_next (gs1, code, tmp, &prep_seq_1, &gen_seq_1); ret = expand_ccmp_next (op1, code, tmp, &prep_seq_1, &gen_seq_1);
cost1 = seq_cost (prep_seq_1, speed_p); cost1 = seq_cost (prep_seq_1, speed_p);
cost1 += seq_cost (gen_seq_1, speed_p); cost1 += seq_cost (gen_seq_1, speed_p);
} }
...@@ -197,27 +239,22 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq) ...@@ -197,27 +239,22 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
rtx_insn *prep_seq_2, *gen_seq_2; rtx_insn *prep_seq_2, *gen_seq_2;
if (tmp == NULL || cost1 < COSTS_N_INSNS (25)) if (tmp == NULL || cost1 < COSTS_N_INSNS (25))
tmp2 = targetm.gen_ccmp_first (&prep_seq_2, &gen_seq_2, rcode1, tmp2 = targetm.gen_ccmp_first (&prep_seq_2, &gen_seq_2, rcode1,
gimple_assign_rhs1 (gs1), logical_op1_rhs1, logical_op1_rhs2);
gimple_assign_rhs2 (gs1));
if (!tmp && !tmp2) if (!tmp && !tmp2)
return NULL_RTX; return NULL_RTX;
if (tmp2 != NULL) if (tmp2 != NULL)
{ {
ret2 = expand_ccmp_next (gs0, code, tmp2, &prep_seq_2, ret2 = expand_ccmp_next (op0, code, tmp2, &prep_seq_2,
&gen_seq_2); &gen_seq_2);
cost2 = seq_cost (prep_seq_2, speed_p); cost2 = seq_cost (prep_seq_2, speed_p);
cost2 += seq_cost (gen_seq_2, speed_p); cost2 += seq_cost (gen_seq_2, speed_p);
} }
if (cost2 < cost1) if (cost2 < cost1)
{ {
*prep_seq = prep_seq_2; *prep_seq = prep_seq_2;
*gen_seq = gen_seq_2; *gen_seq = gen_seq_2;
return ret2; return ret2;
} }
*prep_seq = prep_seq_1; *prep_seq = prep_seq_1;
*gen_seq = gen_seq_1; *gen_seq = gen_seq_1;
return ret; return ret;
...@@ -227,28 +264,18 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq) ...@@ -227,28 +264,18 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
tmp = expand_ccmp_expr_1 (gs1, prep_seq, gen_seq); tmp = expand_ccmp_expr_1 (gs1, prep_seq, gen_seq);
if (!tmp) if (!tmp)
return NULL_RTX; return NULL_RTX;
return expand_ccmp_next (op0, code, tmp, prep_seq, gen_seq);
return expand_ccmp_next (gs0, code, tmp, prep_seq, gen_seq);
} }
} }
else else
{ {
gcc_assert (gimple_assign_rhs_code (gs0) == BIT_AND_EXPR gcc_assert (gimple_assign_rhs_code (gs0) == BIT_AND_EXPR
|| gimple_assign_rhs_code (gs0) == BIT_IOR_EXPR); || gimple_assign_rhs_code (gs0) == BIT_IOR_EXPR);
gcc_assert (ccmp_tree_comparison_p (op1, bb));
if (TREE_CODE_CLASS (gimple_assign_rhs_code (gs1)) == tcc_comparison) tmp = expand_ccmp_expr_1 (gs0, prep_seq, gen_seq);
{ if (!tmp)
tmp = expand_ccmp_expr_1 (gs0, prep_seq, gen_seq); return NULL_RTX;
if (!tmp) return expand_ccmp_next (op1, code, tmp, prep_seq, gen_seq);
return NULL_RTX;
return expand_ccmp_next (gs1, code, tmp, prep_seq, gen_seq);
}
else
{
gcc_assert (gimple_assign_rhs_code (gs1) == BIT_AND_EXPR
|| gimple_assign_rhs_code (gs1) == BIT_IOR_EXPR);
}
} }
return NULL_RTX; return NULL_RTX;
...@@ -258,7 +285,7 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq) ...@@ -258,7 +285,7 @@ expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
Return NULL_RTX if G is not a legal candidate or expand fail. Return NULL_RTX if G is not a legal candidate or expand fail.
Otherwise return the target. */ Otherwise return the target. */
rtx rtx
expand_ccmp_expr (gimple *g) expand_ccmp_expr (gimple *g, machine_mode mode)
{ {
rtx_insn *last; rtx_insn *last;
rtx tmp; rtx tmp;
...@@ -275,7 +302,6 @@ expand_ccmp_expr (gimple *g) ...@@ -275,7 +302,6 @@ expand_ccmp_expr (gimple *g)
{ {
insn_code icode; insn_code icode;
machine_mode cc_mode = CCmode; machine_mode cc_mode = CCmode;
tree lhs = gimple_assign_lhs (g);
rtx_code cmp_code = GET_CODE (tmp); rtx_code cmp_code = GET_CODE (tmp);
#ifdef SELECT_CC_MODE #ifdef SELECT_CC_MODE
...@@ -284,7 +310,6 @@ expand_ccmp_expr (gimple *g) ...@@ -284,7 +310,6 @@ expand_ccmp_expr (gimple *g)
icode = optab_handler (cstore_optab, cc_mode); icode = optab_handler (cstore_optab, cc_mode);
if (icode != CODE_FOR_nothing) if (icode != CODE_FOR_nothing)
{ {
machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
rtx target = gen_reg_rtx (mode); rtx target = gen_reg_rtx (mode);
emit_insn (prep_seq); emit_insn (prep_seq);
...@@ -300,4 +325,3 @@ expand_ccmp_expr (gimple *g) ...@@ -300,4 +325,3 @@ expand_ccmp_expr (gimple *g)
delete_insns_since (last); delete_insns_since (last);
return NULL_RTX; return NULL_RTX;
} }
...@@ -20,6 +20,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -20,6 +20,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_CCMP_H #ifndef GCC_CCMP_H
#define GCC_CCMP_H #define GCC_CCMP_H
extern rtx expand_ccmp_expr (gimple *); extern rtx expand_ccmp_expr (gimple *, machine_mode);
#endif /* GCC_CCMP_H */ #endif /* GCC_CCMP_H */
...@@ -9776,7 +9776,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, ...@@ -9776,7 +9776,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
if (targetm.gen_ccmp_first) if (targetm.gen_ccmp_first)
{ {
gcc_checking_assert (targetm.gen_ccmp_next != NULL); gcc_checking_assert (targetm.gen_ccmp_next != NULL);
r = expand_ccmp_expr (g); r = expand_ccmp_expr (g, mode);
if (r) if (r)
break; break;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment