This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Eliminate signed sizetypes (1/3)
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 13 Apr 2010 11:50:08 +0200
- Subject: [patch] Eliminate signed sizetypes (1/3)
Every compiler in the GNU collection can choose to use either signed or
unsigned sizetypes (exclusively, mixed signedness isn't allowed); the Ada
compiler uses signed ones, all the other compilers (including LTO) use
unsigned ones. As a consequence, LTO doesn't really work with Ada, even
intra-language LTO.
So I'm proposing to eliminate signed sizetypes from the middle-end altogether,
so that people aren't tempted to make the wrong choice anymore :-), switching
the Ada compiler over to unsigned sizetypes in the process. As a bonus, this
will also fix bugs in some corner cases for Ada.
The delicate part is converting the Ada compiler because it is still relying
heavily on subtle overflow handling for sizetypes and flipping the signedness
changes the semantics. This dependency should probably be reworked at some
point, but this won't be easy at all and is not planned yet.
The attached first patch contains changes to the constant folder necessary to
properly support overflow in unsigned sizetypes; nothing new, this support is
already there, but it has been slightly damaged, especially by the fix for PR
middle-end/32628, so the patch undoes it and fixes the problem differently.
The second patch will be the gigi patch and the third patch the one really
eliminating signed sizetypes from the middle-end.
Tested on x86_64-suse-linux and i586-suse-linux, OK for mainline?
2010-04-13 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/32628
* c-common.c (pointer_int_sum): Disregard overflow that occured only
because of sign-extension change when converting to sizetype here...
* fold-const.c (fold_convert_const_int_from_int): ...and not here.
* fold-const.c (fold_binary_op_with_conditional_arg): Do not restrict
the folding to constants. Remove redundant final conversion.
(fold_binary) <associate>: Do not associate if the re-association of
constants alone overflows.
(fold_binary) <FLOOR_MOD_EXPR>: Move transformation into BIT_AND_EXPR
to the end of the list.
(multiple_of_p) <COND_EXPR>: New case.
--
Eric Botcazou
Index: c-common.c
===================================================================
--- c-common.c (revision 158246)
+++ c-common.c (working copy)
@@ -3806,12 +3806,17 @@ pointer_int_sum (location_t loc, enum tr
TYPE_UNSIGNED (sizetype)), intop);
/* Replace the integer argument with a suitable product by the object size.
- Do this multiplication as signed, then convert to the appropriate
- type for the pointer operation. */
- intop = convert (sizetype,
- build_binary_op (loc,
- MULT_EXPR, intop,
- convert (TREE_TYPE (intop), size_exp), 1));
+ Do this multiplication as signed, then convert to the appropriate type
+ for the pointer operation and disregard an overflow that occured only
+ because of the sign-extension change in the latter conversion. */
+ {
+ tree t = build_binary_op (loc,
+ MULT_EXPR, intop,
+ convert (TREE_TYPE (intop), size_exp), 1);
+ intop = convert (sizetype, t);
+ if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
+ TREE_OVERFLOW (intop) = 0;
+ }
/* Create the sum or difference. */
if (resultcode == MINUS_EXPR)
Index: fold-const.c
===================================================================
--- fold-const.c (revision 158246)
+++ fold-const.c (working copy)
@@ -2252,23 +2252,7 @@ fold_convert_const_int_from_int (tree ty
appropriately sign-extended or truncated. */
t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1),
TREE_INT_CST_HIGH (arg1),
- /* Don't set the overflow when
- converting from a pointer, */
- !POINTER_TYPE_P (TREE_TYPE (arg1))
- /* or to a sizetype with same signedness
- and the precision is unchanged.
- ??? sizetype is always sign-extended,
- but its signedness depends on the
- frontend. Thus we see spurious overflows
- here if we do not check this. */
- && !((TYPE_PRECISION (TREE_TYPE (arg1))
- == TYPE_PRECISION (type))
- && (TYPE_UNSIGNED (TREE_TYPE (arg1))
- == TYPE_UNSIGNED (type))
- && ((TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (TREE_TYPE (arg1)))
- || (TREE_CODE (type) == INTEGER_TYPE
- && TYPE_IS_SIZETYPE (type)))),
+ !POINTER_TYPE_P (TREE_TYPE (arg1)),
(TREE_INT_CST_HIGH (arg1) < 0
&& (TYPE_UNSIGNED (type)
< TYPE_UNSIGNED (TREE_TYPE (arg1))))
@@ -6731,12 +6715,6 @@ fold_binary_op_with_conditional_arg (loc
tree lhs = NULL_TREE;
tree rhs = NULL_TREE;
- /* This transformation is only worthwhile if we don't have to wrap
- arg in a SAVE_EXPR, and the operation can be simplified on at least
- one of the branches once its pushed inside the COND_EXPR. */
- if (!TREE_CONSTANT (arg))
- return NULL_TREE;
-
if (TREE_CODE (cond) == COND_EXPR)
{
test = TREE_OPERAND (cond, 0);
@@ -6758,6 +6736,14 @@ fold_binary_op_with_conditional_arg (loc
false_value = constant_boolean_node (false, testtype);
}
+ /* This transformation is only worthwhile if we don't have to wrap ARG
+ in a SAVE_EXPR and the operation can be simplified on at least one
+ of the branches once its pushed inside the COND_EXPR. */
+ if (!TREE_CONSTANT (arg)
+ && (TREE_SIDE_EFFECTS (arg)
+ || TREE_CONSTANT (true_value) || TREE_CONSTANT (false_value)))
+ return NULL_TREE;
+
arg = fold_convert_loc (loc, arg_type, arg);
if (lhs == 0)
{
@@ -6776,8 +6762,11 @@ fold_binary_op_with_conditional_arg (loc
rhs = fold_build2_loc (loc, code, type, arg, false_value);
}
- test = fold_build3_loc (loc, COND_EXPR, type, test, lhs, rhs);
- return fold_convert_loc (loc, type, test);
+ /* Check that we have simplified at least one of the branches. */
+ if (!TREE_CONSTANT (arg) && !TREE_CONSTANT (lhs) && !TREE_CONSTANT (rhs))
+ return NULL_TREE;
+
+ return fold_build3_loc (loc, COND_EXPR, type, test, lhs, rhs);
}
@@ -10628,23 +10617,39 @@ fold_binary_loc (location_t loc,
var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
code == MINUS_EXPR);
- /* With undefined overflow we can only associate constants
- with one variable. */
- if (((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
- || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
- && var0 && var1)
- {
- tree tmp0 = var0;
- tree tmp1 = var1;
-
- if (TREE_CODE (tmp0) == NEGATE_EXPR)
- tmp0 = TREE_OPERAND (tmp0, 0);
- if (TREE_CODE (tmp1) == NEGATE_EXPR)
- tmp1 = TREE_OPERAND (tmp1, 0);
- /* The only case we can still associate with two variables
- is if they are the same, modulo negation. */
- if (!operand_equal_p (tmp0, tmp1, 0))
- ok = false;
+ /* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
+ if (code == MINUS_EXPR)
+ code = PLUS_EXPR;
+
+ /* With undefined overflow we can only associate constants with one
+ variable, and constants whose association doesn't overflow. */
+ if ((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
+ || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
+ {
+ if (var0 && var1)
+ {
+ tree tmp0 = var0;
+ tree tmp1 = var1;
+
+ if (TREE_CODE (tmp0) == NEGATE_EXPR)
+ tmp0 = TREE_OPERAND (tmp0, 0);
+ if (TREE_CODE (tmp1) == NEGATE_EXPR)
+ tmp1 = TREE_OPERAND (tmp1, 0);
+ /* The only case we can still associate with two variables
+ is if they are the same, modulo negation. */
+ if (!operand_equal_p (tmp0, tmp1, 0))
+ ok = false;
+ }
+
+ if (ok && lit0 && lit1)
+ {
+ tree tmp0 = fold_convert (type, lit0);
+ tree tmp1 = fold_convert (type, lit1);
+
+ if (!TREE_OVERFLOW (tmp0) && !TREE_OVERFLOW (tmp1)
+ && TREE_OVERFLOW (fold_build2 (code, type, tmp0, tmp1)))
+ ok = false;
+ }
}
/* Only do something if we found more than two objects. Otherwise,
@@ -10655,10 +10660,6 @@ fold_binary_loc (location_t loc,
+ (lit0 != 0) + (lit1 != 0)
+ (minus_lit0 != 0) + (minus_lit1 != 0))))
{
- /* Recombine MINUS_EXPR operands by using PLUS_EXPR. */
- if (code == MINUS_EXPR)
- code = PLUS_EXPR;
-
var0 = associate_trees (loc, var0, var1, code, type);
con0 = associate_trees (loc, con0, con1, code, type);
lit0 = associate_trees (loc, lit0, lit1, code, type);
@@ -12222,34 +12223,6 @@ fold_binary_loc (location_t loc,
&& TREE_INT_CST_HIGH (arg1) == -1)
return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
- /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
- i.e. "X % C" into "X & (C - 1)", if X and C are positive. */
- strict_overflow_p = false;
- if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
- && (TYPE_UNSIGNED (type)
- || tree_expr_nonnegative_warnv_p (op0, &strict_overflow_p)))
- {
- tree c = arg1;
- /* Also optimize A % (C << N) where C is a power of 2,
- to A & ((C << N) - 1). */
- if (TREE_CODE (arg1) == LSHIFT_EXPR)
- c = TREE_OPERAND (arg1, 0);
-
- if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
- {
- tree mask = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (arg1), arg1,
- build_int_cst (TREE_TYPE (arg1), 1));
- if (strict_overflow_p)
- fold_overflow_warning (("assuming signed overflow does not "
- "occur when simplifying "
- "X % (power of two)"),
- WARN_STRICT_OVERFLOW_MISC);
- return fold_build2_loc (loc, BIT_AND_EXPR, type,
- fold_convert_loc (loc, type, arg0),
- fold_convert_loc (loc, type, mask));
- }
- }
-
/* X % -C is the same as X % C. */
if (code == TRUNC_MOD_EXPR
&& !TYPE_UNSIGNED (type)
@@ -12273,6 +12246,7 @@ fold_binary_loc (location_t loc,
fold_convert_loc (loc, type,
TREE_OPERAND (arg1, 0)));
+ strict_overflow_p = false;
if (TREE_CODE (arg1) == INTEGER_CST
&& 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
&strict_overflow_p)))
@@ -12284,6 +12258,34 @@ fold_binary_loc (location_t loc,
return fold_convert_loc (loc, type, tem);
}
+ /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
+ i.e. "X % C" into "X & (C - 1)", if X and C are positive. */
+ if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
+ && (TYPE_UNSIGNED (type)
+ || tree_expr_nonnegative_warnv_p (op0, &strict_overflow_p)))
+ {
+ tree c = arg1;
+ /* Also optimize A % (C << N) where C is a power of 2,
+ to A & ((C << N) - 1). */
+ if (TREE_CODE (arg1) == LSHIFT_EXPR)
+ c = TREE_OPERAND (arg1, 0);
+
+ if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
+ {
+ tree mask
+ = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (arg1), arg1,
+ build_int_cst (TREE_TYPE (arg1), 1));
+ if (strict_overflow_p)
+ fold_overflow_warning (("assuming signed overflow does not "
+ "occur when simplifying "
+ "X % (power of two)"),
+ WARN_STRICT_OVERFLOW_MISC);
+ return fold_build2_loc (loc, BIT_AND_EXPR, type,
+ fold_convert_loc (loc, type, arg0),
+ fold_convert_loc (loc, type, mask));
+ }
+ }
+
return NULL_TREE;
case LROTATE_EXPR:
@@ -14820,6 +14822,10 @@ multiple_of_p (tree type, const_tree top
case SAVE_EXPR:
return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
+ case COND_EXPR:
+ return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
+ && multiple_of_p (type, TREE_OPERAND (top, 2), bottom));
+
case INTEGER_CST:
if (TREE_CODE (bottom) != INTEGER_CST
|| integer_zerop (bottom)