diff options
author | Richard Henderson <rth@redhat.com> | 2002-06-14 17:06:18 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2002-06-14 17:06:18 -0700 |
commit | fa4a5557dd8f2e4a57bd30bfdf55115c302fc189 (patch) | |
tree | 3ce76f54a4557c8ffdfc9a085936ab7f4e482770 /gcc | |
parent | d95eb49f76442102a21330652340889b4d1af9ee (diff) | |
download | gcc-fa4a5557dd8f2e4a57bd30bfdf55115c302fc189.zip gcc-fa4a5557dd8f2e4a57bd30bfdf55115c302fc189.tar.gz gcc-fa4a5557dd8f2e4a57bd30bfdf55115c302fc189.tar.bz2 |
fold-const.c (fold): Move X>=C / X<C transfomation earlier.
* fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
earlier. Re-factor comparisons vs extrema.
From-SVN: r54626
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/fold-const.c | 189 |
2 files changed, 99 insertions, 95 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 320605f..197ac51 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2002-06-14 Richard Henderson <rth@redhat.com> + * fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation + earlier. Re-factor comparisons vs extrema. + +2002-06-14 Richard Henderson <rth@redhat.com> + * config/alpha/alpha.md (builtin_zapnot): Fix op2 mode. 2002-06-14 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 1c29ad5..31bcddb 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6013,9 +6013,34 @@ fold (expr) } } + /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0. + This transformation affects the cases which are handled in later + optimizations involving comparisons with non-negative constants. */ + if (TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (arg0) != INTEGER_CST + && tree_int_cst_sgn (arg1) > 0) + { + switch (code) + { + case GE_EXPR: + code = GT_EXPR; + arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); + t = build (code, type, TREE_OPERAND (t, 0), arg1); + break; + + case LT_EXPR: + code = LE_EXPR; + arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); + t = build (code, type, TREE_OPERAND (t, 0), arg1); + break; + + default: + break; + } + } + /* Comparisons with the highest or lowest possible integer of - the specified size will have known values and an unsigned - <= 0x7fffffff can be simplified. */ + the specified size will have known values. */ { int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1))); @@ -6025,43 +6050,76 @@ fold (expr) && (INTEGRAL_TYPE_P (TREE_TYPE (arg1)) || POINTER_TYPE_P (TREE_TYPE (arg1)))) { + unsigned HOST_WIDE_INT signed_max; + unsigned HOST_WIDE_INT max, min; + + signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1; + + if (TREE_UNSIGNED (TREE_TYPE (arg1))) + { + max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1; + min = 0; + } + else + { + max = signed_max; + min = ((unsigned HOST_WIDE_INT) -1 << (width - 1)); + } + if (TREE_INT_CST_HIGH (arg1) == 0 - && (TREE_INT_CST_LOW (arg1) - == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1) - && ! TREE_UNSIGNED (TREE_TYPE (arg1))) - switch (TREE_CODE (t)) + && TREE_INT_CST_LOW (arg1) == max) + switch (code) { case GT_EXPR: return omit_one_operand (type, convert (type, integer_zero_node), arg0); case GE_EXPR: + code = EQ_EXPR; TREE_SET_CODE (t, EQ_EXPR); break; - case LE_EXPR: return omit_one_operand (type, convert (type, integer_one_node), arg0); case LT_EXPR: + code = NE_EXPR; TREE_SET_CODE (t, NE_EXPR); break; + /* The GE_EXPR and LT_EXPR cases above are not normally + reached because of previous transformations. */ + default: break; } - - else if (TREE_INT_CST_HIGH (arg1) == -1 - && (TREE_INT_CST_LOW (arg1) - == ((unsigned HOST_WIDE_INT) -1 << (width - 1))) - && ! TREE_UNSIGNED (TREE_TYPE (arg1))) - switch (TREE_CODE (t)) + else if (TREE_INT_CST_HIGH (arg1) == 0 + && TREE_INT_CST_LOW (arg1) == max - 1) + switch (code) + { + case GT_EXPR: + code = EQ_EXPR; + arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0); + t = build (code, type, TREE_OPERAND (t, 0), arg1); + break; + case LE_EXPR: + code = NE_EXPR; + arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0); + t = build (code, type, TREE_OPERAND (t, 0), arg1); + break; + default: + break; + } + else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0) + && TREE_INT_CST_LOW (arg1) == min) + switch (code) { case LT_EXPR: return omit_one_operand (type, convert (type, integer_zero_node), arg0); case LE_EXPR: + code = EQ_EXPR; TREE_SET_CODE (t, EQ_EXPR); break; @@ -6070,112 +6128,53 @@ fold (expr) convert (type, integer_one_node), arg0); case GT_EXPR: + code = NE_EXPR; TREE_SET_CODE (t, NE_EXPR); break; default: break; } + else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0) + && TREE_INT_CST_LOW (arg1) == min + 1) + switch (code) + { + case GE_EXPR: + code = NE_EXPR; + arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); + t = build (code, type, TREE_OPERAND (t, 0), arg1); + break; + case LT_EXPR: + code = EQ_EXPR; + arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); + t = build (code, type, TREE_OPERAND (t, 0), arg1); + break; + default: + break; + } else if (TREE_INT_CST_HIGH (arg1) == 0 - && (TREE_INT_CST_LOW (arg1) - == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1) + && TREE_INT_CST_LOW (arg1) == signed_max && TREE_UNSIGNED (TREE_TYPE (arg1)) /* signed_type does not work on pointer types. */ && INTEGRAL_TYPE_P (TREE_TYPE (arg1))) { - if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR) + /* The following case also applies to X < signed_max+1 + and X >= signed_max+1 because previous transformations. */ + if (code == LE_EXPR || code == GT_EXPR) { tree st0, st1; st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0)); st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1)); return fold - (build (TREE_CODE (t) == LE_EXPR ? GE_EXPR: LT_EXPR, + (build (code == LE_EXPR ? GE_EXPR: LT_EXPR, type, convert (st0, arg0), convert (st1, integer_zero_node))); } } - else if (TREE_INT_CST_HIGH (arg1) == 0 - && (TREE_INT_CST_LOW (arg1) - == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1) - && TREE_UNSIGNED (TREE_TYPE (arg1))) - switch (TREE_CODE (t)) - { - case GT_EXPR: - return omit_one_operand (type, - convert (type, integer_zero_node), - arg0); - case GE_EXPR: - TREE_SET_CODE (t, EQ_EXPR); - break; - - case LE_EXPR: - return omit_one_operand (type, - convert (type, integer_one_node), - arg0); - case LT_EXPR: - TREE_SET_CODE (t, NE_EXPR); - break; - - default: - break; - } } } - /* Change X >= C to X > C-1 and X < C to X <= C-1 if C is positive. */ - if (TREE_CODE (arg1) == INTEGER_CST - && TREE_CODE (arg0) != INTEGER_CST - && tree_int_cst_sgn (arg1) > 0) - { - switch (TREE_CODE (t)) - { - case GE_EXPR: - code = GT_EXPR; - arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); - t = build (code, type, TREE_OPERAND (t, 0), arg1); - break; - - case LT_EXPR: - code = LE_EXPR; - arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0); - t = build (code, type, TREE_OPERAND (t, 0), arg1); - break; - - default: - break; - } - } - - /* An unsigned comparison against 0 can be simplified. */ - if (integer_zerop (arg1) - && (INTEGRAL_TYPE_P (TREE_TYPE (arg1)) - || POINTER_TYPE_P (TREE_TYPE (arg1))) - && TREE_UNSIGNED (TREE_TYPE (arg1))) - { - switch (TREE_CODE (t)) - { - case GT_EXPR: - code = NE_EXPR; - TREE_SET_CODE (t, NE_EXPR); - break; - case LE_EXPR: - code = EQ_EXPR; - TREE_SET_CODE (t, EQ_EXPR); - break; - case GE_EXPR: - return omit_one_operand (type, - convert (type, integer_one_node), - arg0); - case LT_EXPR: - return omit_one_operand (type, - convert (type, integer_zero_node), - arg0); - default: - break; - } - } - /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or a MINUS_EXPR of a constant, we can convert it into a comparison with a revised constant as long as no overflow occurs. */ |