[PATCH] reorganize simplify_const_relational_operation

Eric Botcazou ebotcazou@libertysurf.fr
Wed Sep 19 15:03:00 GMT 2007


2007-09-04  Paolo Bonzini  <bonzini@gnu.org>

	* simplify-rtx.c (comparison_result): New.
	(simplify_const_relational_operation): Use it instead of the five
	"equal|op[01]ltu?" variables; consequently remove redundant "else"s.
	Remove POPCOUNT optimizations.  Extract nonzero_address_p optimizations
	into a Hoist test for ABS outside the final switch statement.

Glitch in the last line of the ChangeLog.


+enum cr_flags
+{
+  CR_EQ = 1,
+  CR_LT = 2,
+  CR_GT = 4,
+  CR_LTU = 8,
+  CR_GTU = 16
+};

As previously agreed, let's ditch the type name.


+/* Convert the known results for EQ, LT, GT, LTU, GTU contained in
+   KNOWN_RESULT to a CONST_INT, based on the requested comparison CODE.
+   For floating-point comparisons, assumes that the operands were ordered. */

superfluous 's' in 'assumes'.  I'm not very fond of this interface because 
it's a mix of bitmasks and enums: IIUC you must pass either exactly one of 
(CR_EQ, CR_LT, CR_GT) or one of (CR_EQ, CR_LTU, CR_GTU), but you're allowed 
to OR between the two sets, right?  Could you further document it?


+static rtx
+comparison_result (enum rtx_code code, enum cr_flags known_results)

int known_results


@@ -4024,19 +4084,21 @@ simplify_const_relational_operation (enu
       if (width != 0 && width <= HOST_BITS_PER_WIDE_INT)
 	h0u = h1u = 0, h0s = HWI_SIGN_EXTEND (l0s), h1s = HWI_SIGN_EXTEND (l1s);
 
-      equal = (h0u == h1u && l0u == l1u);
-      op0lt = (h0s < h1s || (h0s == h1s && l0u < l1u));
-      op1lt = (h1s < h0s || (h1s == h0s && l1u < l0u));
-      op0ltu = (h0u < h1u || (h0u == h1u && l0u < l1u));
-      op1ltu = (h1u < h0u || (h1u == h0u && l1u < l0u));
-    }
-
-  /* Otherwise, there are some code-specific tests we can make.  */
+      if (h0u == h1u && l0u == l1u)
+        return comparison_result (code, CR_EQ);
   else
     {
+	  int cr;
+          cr = (h0s < h1s || (h0s == h1s && l0u < l1u)) ? CR_LT : CR_GT;
+          cr |= (h0u < h1u || (h0u == h1u && l0u < l1u)) ? CR_LTU : CR_GTU;
+          return comparison_result (code, cr);
+	}
+    }

To be further simplified in a follow-up patch.


!   /* Optimize integer comparisons with zero.  */
!   if (trueop1 == const0_rtx)
  	{
!       if (code == LEU)
! 	code = EQ;
!       if (code == GTU)
! 	code = NE;
! 
!       /* Some addresses are known to be nonzero.  We don't know
!          their sign, but equality comparisons are known.  */
!       if (nonzero_address_p (trueop0))
!         {
! 	  if (code == EQ)
  	    return const0_rtx;
! 	  if (code == NE)
  	    return const_true_rtx;
!         }
!     }
  
+   /* Optimize comparison of ABS with zero.  */
+   if (trueop1 == CONST0_RTX (mode)

This is not safe, you're modifying 'code' without always returning.

if (trueop1 == const0_rtx && nonzero_address_p (op0))
{
  if (code == LEU || code == EQ)
    ...
}

is safer.


	case UNGE:
 	  /* Optimize ! (abs(x) < 0.0).  */
-	  if (trueop1 == CONST0_RTX (mode))
-	    {
-	      tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
-						       : trueop0;
-	      if (GET_CODE (tem) == ABS)
 		return const_true_rtx;
-	    }
-	  break;

What about 'UNLT'?

-- 
Eric Botcazou



More information about the Gcc-patches mailing list