diff mbox

Improve COND_EXPR expansion

Message ID CA+=Sn1=dbhtV8vHt+516_Y0GudHkwcysD_s5Zf-jzCT5Xdgajw@mail.gmail.com
State New
Headers show

Commit Message

Andrew Pinski May 4, 2012, 7:30 a.m. UTC
On Fri, May 4, 2012 at 12:29 AM, Andrew Pinski
<andrew.pinski@caviumnetworks.com> wrote:
> On Tue, May 1, 2012 at 9:45 AM, Richard Henderson <rth@redhat.com> wrote:
>> On 04/30/2012 08:22 PM, Andrew Pinski wrote:
>>>
>>> * expr.c (convert_tree_comp_to_rtx): New function.
>>> (expand_expr_real_2): Try using conditional moves for COND_EXPRs if they
>>> exist.
>>> * config/i386/i386.c (ix86_expand_int_movcc): Disallow comparison
>>> modes of DImode for 32bits and TImode.
>>
>>
>> Looks ok, modulo some unwrapped long lines.
>> Those lines might not be so long if this were split out as a subroutine...
>>
>> I'll not quibble about that though...
>
> Here is a new patch which splits this out into a subroutine which
> reduces the long lines.  I added some extra comments that might make
> some stuff like the extra can_conditionally_move_p check.
>
> OK?  Bootstrapped and tested on x86_64-linux-gnu.

This time with the patch.

-- Andrew

>
> Thanks,
> Andrew Pinski
>
> ChangeLog:
> * 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.

Comments

Richard Henderson May 4, 2012, 5:11 p.m. UTC | #1
On 05/04/12 00:30, Andrew Pinski wrote:
> +static rtx
> +expand_cond_expr_using_cmove (tree treeop0, tree treeop1, tree treeop2)
> +{
> +#ifdef HAVE_conditional_move

You'll need ATTRIBUTE_UNUSED markers here.

Otherwise ok.


r~
diff mbox

Patch

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 187138)
+++ gcc/expr.c	(working copy)
@@ -2346,6 +2346,26 @@  get_def_for_expr (tree name, enum tree_c
 
   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_tr
   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,96 @@  expand_expr_real (tree exp, rtx target,
   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, tree treeop1, tree treeop2)
+{
+#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 +9009,10 @@  expand_expr_real_2 (sepops ops, rtx targ
 		  && 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 +9022,6 @@  expand_expr_real_2 (sepops ops, rtx targ
 	  && 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
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 187138)
+++ gcc/config/i386/i386.c	(working copy)
@@ -18832,6 +18832,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 ();