This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix problematic folding
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 31 Jul 2008 19:46:49 +0200
- Subject: [PATCH] Fix problematic folding
Hi,
the recent conversion of GNAT to boolean_type_node for Standard.Boolean has
uncovered a problem in the constant folder, namely fold_binary:
/* A - B -> A + (-B) if B is easily negatable. */
if (negate_expr_p (arg1)
&& ((FLOAT_TYPE_P (type)
/* Avoid this transformation if B is a positive REAL_CST. */
&& (TREE_CODE (arg1) != REAL_CST
|| REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
|| INTEGRAL_TYPE_P (type)))
return fold_build2 (PLUS_EXPR, type,
fold_convert (type, arg0),
fold_convert (type, negate_expr (arg1)));
Suppose that the type is unsigned integral with precision 1 (and QImode), then
A-1 is turned into A+1 by this transformation, which changes the final code
since A+1 doesn't wrap around in QImode (255 would have been needed).
Hence the proposed fix, tested on i586-suse-linux, OK for mainline?
2008-07-31 Eric Botcazou <ebotcazou@adacore.com>
* fold-const.c (fold_binary) <MINUS_EXPR>: Turn it into a PLUS_EXPR
for integral types only if the sign bit of the mode is toggled.
2008-07-31 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/boolean_expr2.adb: New test.
--
Eric Botcazou
Index: fold-const.c
===================================================================
--- fold-const.c (revision 138424)
+++ fold-const.c (working copy)
@@ -10056,7 +10056,11 @@ fold_binary (enum tree_code code, tree t
/* Avoid this transformation if B is a positive REAL_CST. */
&& (TREE_CODE (arg1) != REAL_CST
|| REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1))))
- || INTEGRAL_TYPE_P (type)))
+ /* We can only do this if the sign bit of the mode is toggled
+ by the negation. */
+ || (INTEGRAL_TYPE_P (type)
+ && (TYPE_PRECISION (type)
+ == GET_MODE_BITSIZE (TYPE_MODE (type))))))
return fold_build2 (PLUS_EXPR, type,
fold_convert (type, arg0),
fold_convert (type, negate_expr (arg1)));
-- { dg-do run }
procedure Boolean_Expr2 is
function Ident_Bool (B : Boolean) return Boolean is
begin
return B;
end;
begin
if Boolean'Succ (Ident_Bool(False)) /= True then
raise Program_Error;
end if;
if Boolean'Pred (Ident_Bool(True)) /= False then
raise Program_Error;
end if;
end;