This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] post-cond-optab improvements part 3


This is another patch that is needed to have the target-independent
expander do all tricks currently supported by the i386 backend.

The idea is to try swapping the condition when profitable, i.e.
when for example LT is not supported but GT is.  This patch fixes
a few regressions with the i386 patch I'm also going to submit as
soon as my testing finishes, for example ssefp-1.c and cmov5.c in
gcc.target/i386.

Bootstrapped/regtested i686-pc-linux-gnu together with the other
patches, ok?

Paolo
2009-05-13  Paolo Bonzini  <bonzini@gnu.org>

	* dojump.c (do_compare_rtx_and_jump): Try swapping the
	condition for floating point modes.
	* expmed.c (emit_store_flag_1): Move here a bigger part
	of emit_store_flag.
	(emit_store_flag): Try swapping the condition for floating point
	modes.
	* optabs.c (emit_cmp_and_jump_insns): Cope with constant op0 better.

Index: gcc/dojump.c
===================================================================
--- gcc/dojump.c	(branch cond-optab2)
+++ gcc/dojump.c	(working copy)
@@ -919,16 +919,27 @@ do_compare_rtx_and_jump (rtx op0, rtx op
     {
       if (GET_MODE_CLASS (mode) == MODE_FLOAT
 	  && ! can_compare_p (code, mode, ccp_jump)
+	  && can_compare_p (swap_condition (code), mode, ccp_jump))
+	{
+	  rtx tmp;
+	  code = swap_condition (code);
+	  tmp = op0;
+	  op0 = op1;
+	  op1 = tmp;
+	}
+
+      else if (GET_MODE_CLASS (mode) == MODE_FLOAT
+	       && ! can_compare_p (code, mode, ccp_jump)
 
-	  /* Never split ORDERED and UNORDERED.  These must be implemented.  */
-	  && (code != ORDERED && code != UNORDERED)
+	       /* Never split ORDERED and UNORDERED.  These must be implemented.  */
+	       && (code != ORDERED && code != UNORDERED)
 
-          /* Split a floating-point comparison if we can jump on other
-	     conditions...  */
-	  && (have_insn_for (COMPARE, mode)
+               /* Split a floating-point comparison if we can jump on other
+	          conditions...  */
+	       && (have_insn_for (COMPARE, mode)
 
-	      /* ... or if there is no libcall for it.  */
-	      || code_to_optab[code] == NULL))
+	           /* ... or if there is no libcall for it.  */
+	           || code_to_optab[code] == NULL))
         {
 	  enum rtx_code first_code;
 	  bool and_them = split_comparison (code, mode, &first_code, &code);
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(branch cond-optab2)
+++ gcc/expmed.c	(working copy)
@@ -5115,11 +5115,40 @@ expand_and (enum machine_mode mode, rtx 
 
 /* Helper function for emit_store_flag.  */
 static rtx
-emit_store_flag_1 (rtx target, rtx subtarget, enum machine_mode mode,
-		   int normalizep)
+emit_store_flag_1 (rtx target, enum insn_code icode, enum rtx_code code,
+		   enum machine_mode mode, enum machine_mode compare_mode,
+		   int unsignedp, rtx x, rtx y, int normalizep)
 {
-  rtx op0;
+  rtx op0, last, comparison, subtarget, pattern;
   enum machine_mode target_mode;
+  enum machine_mode result_mode = insn_data[(int) icode].operand[0].mode;
+
+  last = get_last_insn ();
+  x = prepare_operand (icode, x, 2, mode, compare_mode, unsignedp);
+  y = prepare_operand (icode, y, 3, mode, compare_mode, unsignedp);
+  comparison = gen_rtx_fmt_ee (code, result_mode, x, y);
+  if (!x || !y
+      || !insn_data[icode].operand[2].predicate
+	  (x, insn_data[icode].operand[2].mode)
+      || !insn_data[icode].operand[3].predicate
+	  (y, insn_data[icode].operand[3].mode)
+      || !insn_data[icode].operand[1].predicate (comparison, VOIDmode))
+    {
+      delete_insns_since (last);
+      return NULL_RTX;
+    }
+
+  if (!target
+      || optimize
+      || !(insn_data[(int) icode].operand[0].predicate (target, result_mode)))
+    subtarget = gen_reg_rtx (result_mode);
+  else
+    subtarget = target;
+
+  pattern = GEN_FCN (icode) (subtarget, comparison, x, y);
+  if (!pattern)
+    return NULL_RTX;
+  emit_insn (pattern);
 
   if (!target)
     target = gen_reg_rtx (GET_MODE (subtarget));
@@ -5133,15 +5162,15 @@ emit_store_flag_1 (rtx target, rtx subta
      If STORE_FLAG_VALUE does not have the sign bit set when
      interpreted in MODE, we can do this conversion as unsigned, which
      is usually more efficient.  */
-  if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (mode))
+  if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (result_mode))
     {
       convert_move (target, subtarget,
-		    (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+		    (GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT)
 		    && 0 == (STORE_FLAG_VALUE
 			     & ((HOST_WIDE_INT) 1
-				<< (GET_MODE_BITSIZE (mode) -1))));
+				<< (GET_MODE_BITSIZE (result_mode) -1))));
       op0 = target;
-      mode = target_mode;
+      result_mode = target_mode;
     }
   else
     op0 = subtarget;
@@ -5158,28 +5187,28 @@ emit_store_flag_1 (rtx target, rtx subta
   /* STORE_FLAG_VALUE might be the most negative number, so write
      the comparison this way to avoid a compiler-time warning.  */
   else if (- normalizep == STORE_FLAG_VALUE)
-    op0 = expand_unop (mode, neg_optab, op0, subtarget, 0);
+    op0 = expand_unop (result_mode, neg_optab, op0, subtarget, 0);
 
   /* We don't want to use STORE_FLAG_VALUE < 0 below since this makes
      it hard to use a value of just the sign bit due to ANSI integer
      constant typing rules.  */
-  else if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+  else if (GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT
 	   && (STORE_FLAG_VALUE
-	       & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))))
-    op0 = expand_shift (RSHIFT_EXPR, mode, op0,
-			size_int (GET_MODE_BITSIZE (mode) - 1), subtarget,
+	       & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (result_mode) - 1))))
+    op0 = expand_shift (RSHIFT_EXPR, result_mode, op0,
+			size_int (GET_MODE_BITSIZE (result_mode) - 1), subtarget,
 			normalizep == 1);
   else
     {
       gcc_assert (STORE_FLAG_VALUE & 1);
 
-      op0 = expand_and (mode, op0, const1_rtx, subtarget);
+      op0 = expand_and (result_mode, op0, const1_rtx, subtarget);
       if (normalizep == -1)
-	op0 = expand_unop (mode, neg_optab, op0, op0, 0);
+	op0 = expand_unop (result_mode, neg_optab, op0, op0, 0);
     }
 
   /* If we were converting to a smaller mode, do the conversion now.  */
-  if (target_mode != mode)
+  if (target_mode != result_mode)
     {
       convert_move (target, op0, 0);
       return target;
@@ -5213,12 +5242,13 @@ emit_store_flag (rtx target, enum rtx_co
   enum machine_mode target_mode = target ? GET_MODE (target) : VOIDmode;
   enum mode_class mclass;
   enum rtx_code rcode;
+  enum rtx_code scode;
   rtx tem, trueval;
   rtx last;
-  rtx pattern, comparison;
 
   if (unsignedp)
     code = unsigned_condition (code);
+  scode = swap_condition (code);
 
   /* If one operand is constant, make it the second one.  Only do this
      if the other operand is not constant as well.  */
@@ -5359,44 +5389,19 @@ emit_store_flag (rtx target, enum rtx_co
      icode = optab_handler (cstore_optab, optab_mode)->insn_code;
      if (icode != CODE_FOR_nothing)
 	{
-	  rtx x, y;
-	  enum machine_mode result_mode
-	    = insn_data[(int) icode].operand[0].mode;
-
 	  do_pending_stack_adjust ();
-	  last = get_last_insn ();
+	  tem = emit_store_flag_1 (target, icode, code, mode, compare_mode,
+				   unsignedp, op0, op1, normalizep);
+	  if (tem)
+	    return tem;
 
-          x = prepare_operand (icode, op0, 2, mode, compare_mode, unsignedp);
-          y = prepare_operand (icode, op1, 3, mode, compare_mode, unsignedp);
-	  comparison = gen_rtx_fmt_ee (code, result_mode, x, y);
-	  if (!x || !y
-	      || !insn_data[icode].operand[2].predicate
-		  (x, insn_data[icode].operand[2].mode)
-	      || !insn_data[icode].operand[3].predicate
-		  (y, insn_data[icode].operand[3].mode)
-	      || !insn_data[icode].operand[1].predicate (comparison, VOIDmode))
+	  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
 	    {
-	      delete_insns_since (last);
-	      continue;
-	    }
-
-	  if (!target
-	      || optimize
-	      || !(insn_data[(int) icode].operand[0].predicate (target, result_mode)))
-	    subtarget = gen_reg_rtx (result_mode);
-	  else
-	    subtarget = target;
-
-	  pattern = GEN_FCN (icode) (subtarget, comparison, x, y);
-
-	  if (pattern)
-	    {
-	      emit_insn (pattern);
-	      return emit_store_flag_1 (target, subtarget, result_mode,
-					normalizep);
+	      tem = emit_store_flag_1 (target, icode, scode, mode, compare_mode,
+				       unsignedp, op1, op0, normalizep);
+	      if (tem)
+	        return tem;
 	    }
-
-	  delete_insns_since (last);
 	  break;
 	}
     }
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(branch cond-optab2)
+++ gcc/optabs.c	(working copy)
@@ -4280,18 +4280,18 @@ emit_cmp_and_jump_insns (rtx x, rtx y, e
   rtx test;
 
   /* Swap operands and condition to ensure canonical RTL.  */
-  if (swap_commutative_operands_p (x, y))
+  if (swap_commutative_operands_p (x, y)
+      && can_compare_p (swap_condition (comparison), mode, ccp_jump))
     {
       op0 = y, op1 = x;
       comparison = swap_condition (comparison);
     }
 
-#ifdef HAVE_cc0
-  /* If OP0 is still a constant, then both X and Y must be constants.
-     Force X into a register to create canonical RTL.  */
+  /* If OP0 is still a constant, then both X and Y must be constants
+     or the opposite comparison is not supported.  Force X into a register
+     to create canonical RTL.  */
   if (CONSTANT_P (op0))
     op0 = force_reg (mode, op0);
-#endif
 
   if (unsignedp)
     comparison = unsigned_condition (comparison);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]