[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