This avoids simplifying 2 * (a * (__INT_MAX__/2 + 1))
to a * INT_MIN which introduces undefined overflow for a == -1.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2015-10-29  Richard Biener  <rguent...@suse.de>

        PR middle-end/68142
        * fold-const.c (extract_muldiv_1): Avoid introducing undefined
        overflow.

        * c-c++-common/ubsan/pr68142.c: New testcase.

Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c    (revision 229517)
--- gcc/fold-const.c    (working copy)
*************** extract_muldiv_1 (tree t, tree c, enum t
*** 6008,6015 ****
         or (for divide and modulus) if it is a multiple of our constant.  */
        if (code == MULT_EXPR
          || wi::multiple_of_p (t, c, TYPE_SIGN (type)))
!       return const_binop (code, fold_convert (ctype, t),
!                           fold_convert (ctype, c));
        break;
  
      CASE_CONVERT: case NON_LVALUE_EXPR:
--- 6015,6031 ----
         or (for divide and modulus) if it is a multiple of our constant.  */
        if (code == MULT_EXPR
          || wi::multiple_of_p (t, c, TYPE_SIGN (type)))
!       {
!         tree tem = const_binop (code, fold_convert (ctype, t),
!                                 fold_convert (ctype, c));
!         /* If the multiplication overflowed to INT_MIN then we lost sign
!            information on it and a subsequent multiplication might
!            spuriously overflow.  See PR68142.  */
!         if (TREE_OVERFLOW (tem)
!             && wi::eq_p (tem, wi::min_value (TYPE_PRECISION (ctype), SIGNED)))
!           return NULL_TREE;
!         return tem;
!       }
        break;
  
      CASE_CONVERT: case NON_LVALUE_EXPR:
Index: gcc/testsuite/c-c++-common/ubsan/pr68142.c
===================================================================
*** gcc/testsuite/c-c++-common/ubsan/pr68142.c  (revision 0)
--- gcc/testsuite/c-c++-common/ubsan/pr68142.c  (working copy)
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do run } */
+ /* { dg-options "-fsanitize=undefined -fsanitize-undefined-trap-on-error" } */
+ 
+ int __attribute__((noinline,noclone))
+ h(int a)
+ {
+   return 2 * (a * (__INT_MAX__/2 + 1));
+ }
+ int __attribute__((noinline,noclone))
+ i(int a)
+ {
+   return (2 * a) * (__INT_MAX__/2 + 1);
+ }
+ int __attribute__((noinline,noclone))
+ j(int a, int b)
+ {
+   return (b * a) * (__INT_MAX__/2 + 1);
+ }
+ int __attribute__((noinline,noclone))
+ k(int a, int b)
+ {
+   return (2 * a) * b;
+ }
+ int main()
+ {
+   volatile int tem = h(-1);
+   tem = i(-1);
+   tem = j(-1, 2);
+   tem = k(-1, __INT_MAX__/2 + 1);
+   return 0;
+ }

Reply via email to