From 683c600b1fb53494c3cdcde83da5b3cb518cfa70 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Fri, 4 May 2012 21:03:27 +0000 Subject: [PATCH] expr.c (get_def_for_expr_class): New function. 2012-05-04 Andrew Pinski * 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 ): 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 --- gcc/ChangeLog | 12 ++++ gcc/config/i386/i386.c | 5 ++ gcc/expr.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 192 insertions(+), 4 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8dafc82..bd2e135 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2012-05-04 Andrew Pinski + + * 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 ): 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 PR other/29442 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index a8be095..1b8d074 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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 (); diff --git a/gcc/expr.c b/gcc/expr.c index 3e8e004..1e0e96a 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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 -- 2.7.4