This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]