Commit 683c600b by Andrew Pinski Committed by Andrew Pinski

expr.c (get_def_for_expr_class): New function.

2012-05-04  Andrew Pinski  <apinski@cavium.com>

	* expr.c (get_def_for_expr_class): New function.
	(convert_tree_comp_to_rtx): New function.
	(expand_cond_expr_using_cmove): New function.
	(expand_expr_real_2 <case COND_EXPR>): Call
	expand_cond_expr_using_cmove first and return if it succeeds.
	Remove the check for HAVE_conditional_move since we should have
	already converted it to a conditional move.
	* config/i386/i386.c (ix86_expand_int_movcc): Disallow comparison
	modes of DImode for 32bits and TImode.

From-SVN: r187183
parent 41723253
2012-05-04 Andrew Pinski <apinski@cavium.com>
* expr.c (get_def_for_expr_class): New function.
(convert_tree_comp_to_rtx): New function.
(expand_cond_expr_using_cmove): New function.
(expand_expr_real_2 <case COND_EXPR>): Call
expand_cond_expr_using_cmove first and return if it succeeds.
Remove the check for HAVE_conditional_move since we should have
already converted it to a conditional move.
* config/i386/i386.c (ix86_expand_int_movcc): Disallow comparison
modes of DImode for 32bits and TImode.
2012-05-04 Steven Bosscher <steven@gcc.gnu.org> 2012-05-04 Steven Bosscher <steven@gcc.gnu.org>
PR other/29442 PR other/29442
......
...@@ -18826,6 +18826,11 @@ ix86_expand_int_movcc (rtx operands[]) ...@@ -18826,6 +18826,11 @@ ix86_expand_int_movcc (rtx operands[])
rtx op0 = XEXP (operands[1], 0); rtx op0 = XEXP (operands[1], 0);
rtx op1 = XEXP (operands[1], 1); rtx op1 = XEXP (operands[1], 1);
if (GET_MODE (op0) == TImode
|| (GET_MODE (op0) == DImode
&& !TARGET_64BIT))
return false;
start_sequence (); start_sequence ();
compare_op = ix86_expand_compare (code, op0, op1); compare_op = ix86_expand_compare (code, op0, op1);
compare_seq = get_insns (); compare_seq = get_insns ();
...@@ -2347,6 +2347,26 @@ get_def_for_expr (tree name, enum tree_code code) ...@@ -2347,6 +2347,26 @@ get_def_for_expr (tree name, enum tree_code code)
return def_stmt; return def_stmt;
} }
/* Return the defining gimple statement for SSA_NAME NAME if it is an
assigment and the class of the expresion on the RHS is CLASS. Return
NULL otherwise. */
static gimple
get_def_for_expr_class (tree name, enum tree_code_class tclass)
{
gimple def_stmt;
if (TREE_CODE (name) != SSA_NAME)
return NULL;
def_stmt = get_gimple_for_ssa_name (name);
if (!def_stmt
|| TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt)) != tclass)
return NULL;
return def_stmt;
}
/* Determine whether the LEN bytes generated by CONSTFUN can be /* Determine whether the LEN bytes generated by CONSTFUN can be
stored to memory using several move instructions. CONSTFUNDATA is stored to memory using several move instructions. CONSTFUNDATA is
...@@ -7344,6 +7364,64 @@ highest_pow2_factor_for_target (const_tree target, const_tree exp) ...@@ -7344,6 +7364,64 @@ highest_pow2_factor_for_target (const_tree target, const_tree exp)
return MAX (factor, talign); return MAX (factor, talign);
} }
/* Convert the tree comparision code TCODE to the rtl one where the
signedness is UNSIGNEDP. */
static enum rtx_code
convert_tree_comp_to_rtx (enum tree_code tcode, int unsignedp)
{
enum rtx_code code;
switch (tcode)
{
case EQ_EXPR:
code = EQ;
break;
case NE_EXPR:
code = NE;
break;
case LT_EXPR:
code = unsignedp ? LTU : LT;
break;
case LE_EXPR:
code = unsignedp ? LEU : LE;
break;
case GT_EXPR:
code = unsignedp ? GTU : GT;
break;
case GE_EXPR:
code = unsignedp ? GEU : GE;
break;
case UNORDERED_EXPR:
code = UNORDERED;
break;
case ORDERED_EXPR:
code = ORDERED;
break;
case UNLT_EXPR:
code = UNLT;
break;
case UNLE_EXPR:
code = UNLE;
break;
case UNGT_EXPR:
code = UNGT;
break;
case UNGE_EXPR:
code = UNGE;
break;
case UNEQ_EXPR:
code = UNEQ;
break;
case LTGT_EXPR:
code = LTGT;
break;
default:
gcc_unreachable ();
}
return code;
}
/* Subroutine of expand_expr. Expand the two operands of a binary /* Subroutine of expand_expr. Expand the two operands of a binary
expression EXP0 and EXP1 placing the results in OP0 and OP1. expression EXP0 and EXP1 placing the results in OP0 and OP1.
The value may be stored in TARGET if TARGET is nonzero. The The value may be stored in TARGET if TARGET is nonzero. The
...@@ -7782,6 +7860,99 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, ...@@ -7782,6 +7860,99 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
return ret; return ret;
} }
/* Try to expand the conditional expression which is represented by
TREEOP0 ? TREEOP1 : TREEOP2 using conditonal moves. If succeseds
return the rtl reg which repsents the result. Otherwise return
NULL_RTL. */
static rtx
expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
tree treeop1 ATTRIBUTE_UNUSED,
tree treeop2 ATTRIBUTE_UNUSED)
{
#ifdef HAVE_conditional_move
rtx insn;
rtx op00, op01, op1, op2;
enum rtx_code comparison_code;
enum machine_mode comparison_mode;
gimple srcstmt;
rtx temp;
tree type = TREE_TYPE (treeop1);
int unsignedp = TYPE_UNSIGNED (type);
enum machine_mode mode = TYPE_MODE (type);
temp = assign_temp (type, 0, 0, 1);
/* If we cannot do a conditional move on the mode, try doing it
with the promoted mode. */
if (!can_conditionally_move_p (mode))
mode = promote_mode (type, mode, &unsignedp);
if (!can_conditionally_move_p (mode))
return NULL_RTX;
start_sequence ();
expand_operands (treeop1, treeop2,
temp, &op1, &op2, EXPAND_NORMAL);
if (TREE_CODE (treeop0) == SSA_NAME
&& (srcstmt = get_def_for_expr_class (treeop0, tcc_comparison)))
{
tree type = TREE_TYPE (gimple_assign_rhs1 (srcstmt));
enum tree_code cmpcode = gimple_assign_rhs_code (srcstmt);
op00 = expand_normal (gimple_assign_rhs1 (srcstmt));
op01 = expand_normal (gimple_assign_rhs2 (srcstmt));
comparison_mode = TYPE_MODE (type);
unsignedp = TYPE_UNSIGNED (type);
comparison_code = convert_tree_comp_to_rtx (cmpcode, unsignedp);
}
else if (TREE_CODE_CLASS (TREE_CODE (treeop0)) == tcc_comparison)
{
tree type = TREE_TYPE (TREE_OPERAND (treeop0, 0));
enum tree_code cmpcode = TREE_CODE (treeop0);
op00 = expand_normal (TREE_OPERAND (treeop0, 0));
op01 = expand_normal (TREE_OPERAND (treeop0, 1));
unsignedp = TYPE_UNSIGNED (type);
comparison_mode = TYPE_MODE (type);
comparison_code = convert_tree_comp_to_rtx (cmpcode, unsignedp);
}
else
{
op00 = expand_normal (treeop0);
op01 = const0_rtx;
comparison_code = NE;
comparison_mode = TYPE_MODE (TREE_TYPE (treeop0));
}
if (GET_MODE (op1) != mode)
op1 = gen_lowpart (mode, op1);
if (GET_MODE (op2) != mode)
op2 = gen_lowpart (mode, op2);
/* Try to emit the conditional move. */
insn = emit_conditional_move (temp, comparison_code,
op00, op01, comparison_mode,
op1, op2, mode,
unsignedp);
/* If we could do the conditional move, emit the sequence,
and return. */
if (insn)
{
rtx seq = get_insns ();
end_sequence ();
emit_insn (seq);
return temp;
}
/* Otherwise discard the sequence and fall back to code with
branches. */
end_sequence ();
#endif
return NULL_RTX;
}
rtx rtx
expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
enum expand_modifier modifier) enum expand_modifier modifier)
...@@ -8841,6 +9012,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, ...@@ -8841,6 +9012,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
&& TREE_TYPE (treeop1) != void_type_node && TREE_TYPE (treeop1) != void_type_node
&& TREE_TYPE (treeop2) != void_type_node); && TREE_TYPE (treeop2) != void_type_node);
temp = expand_cond_expr_using_cmove (treeop0, treeop1, treeop2);
if (temp)
return temp;
/* If we are not to produce a result, we have no target. Otherwise, /* If we are not to produce a result, we have no target. Otherwise,
if a target was specified use it; it will not be used as an if a target was specified use it; it will not be used as an
intermediate target unless it is safe. If no target, use a intermediate target unless it is safe. If no target, use a
...@@ -8850,10 +9025,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, ...@@ -8850,10 +9025,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
&& original_target && original_target
&& safe_from_p (original_target, treeop0, 1) && safe_from_p (original_target, treeop0, 1)
&& GET_MODE (original_target) == mode && GET_MODE (original_target) == mode
#ifdef HAVE_conditional_move
&& (! can_conditionally_move_p (mode)
|| REG_P (original_target))
#endif
&& !MEM_P (original_target)) && !MEM_P (original_target))
temp = original_target; temp = original_target;
else else
......
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