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>
PR other/29442
......
......@@ -18826,6 +18826,11 @@ ix86_expand_int_movcc (rtx operands[])
rtx op0 = XEXP (operands[1], 0);
rtx op1 = XEXP (operands[1], 1);
if (GET_MODE (op0) == TImode
|| (GET_MODE (op0) == DImode
&& !TARGET_64BIT))
return false;
start_sequence ();
compare_op = ix86_expand_compare (code, op0, op1);
compare_seq = get_insns ();
......@@ -2346,6 +2346,26 @@ get_def_for_expr (tree name, enum tree_code code)
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
......@@ -7344,6 +7364,64 @@ highest_pow2_factor_for_target (const_tree target, const_tree exp)
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
expression EXP0 and EXP1 placing the results in OP0 and OP1.
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,
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
expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
enum expand_modifier modifier)
......@@ -8841,6 +9012,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
&& TREE_TYPE (treeop1) != 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 a target was specified use it; it will not be used as an
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,
&& original_target
&& safe_from_p (original_target, treeop0, 1)
&& GET_MODE (original_target) == mode
#ifdef HAVE_conditional_move
&& (! can_conditionally_move_p (mode)
|| REG_P (original_target))
#endif
&& !MEM_P (original_target))
temp = original_target;
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