re PR sanitizer/81281 (UBSAN: false positive, dropped promotion to long type.)
authorJakub Jelinek <jakub@redhat.com>
Fri, 15 Dec 2017 14:36:26 +0000 (15:36 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 15 Dec 2017 14:36:26 +0000 (15:36 +0100)
PR sanitizer/81281
* match.pd ((T)(P + A) - (T)P -> (T) A): Use @@0 instead of @0 and
convert? on @0 instead of convert.  Check type of @1, not @0.
((T)P - (T)(P + A) -> -(T) A): Use @@0 instead of @0 and
convert? on @0 instead of convert.  Check type of @1, not @0.
((T)(P + A) - (T)(P + B) -> (T)A - (T)B): Use @@0 instead of @0,
only optimize if either both @1 and @2 types are narrower
precision, or both are wider or equal precision, and in the former
case only if both have undefined overflow.

* gcc.dg/pr81281-3.c: New test.

From-SVN: r255696

gcc/ChangeLog
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr81281-3.c [new file with mode: 0644]

index 3282f489370807c3a96c7f2181dcd23beb95e497..8d655acf2c8aee599d0e7514b9d27748e67b6aa2 100644 (file)
@@ -1,3 +1,15 @@
+2017-12-15  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/81281
+       * match.pd ((T)(P + A) - (T)P -> (T) A): Use @@0 instead of @0 and
+       convert? on @0 instead of convert.  Check type of @1, not @0.
+       ((T)P - (T)(P + A) -> -(T) A): Use @@0 instead of @0 and
+       convert? on @0 instead of convert.  Check type of @1, not @0.
+       ((T)(P + A) - (T)(P + B) -> (T)A - (T)B): Use @@0 instead of @0,
+       only optimize if either both @1 and @2 types are narrower
+       precision, or both are wider or equal precision, and in the former
+       case only if both have undefined overflow.
+
 2017-12-15  Richard Biener  <rguenther@suse.de>
 
        PR lto/83388
index 0a4ff6bb8df1a5f477e8df2101fadec420792c7f..3943aceb05967eba1063009b3a4a0fb9952321e2 100644 (file)
@@ -1784,8 +1784,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
   /* (T)(P + A) - (T)P -> (T) A */
   (simplify
-   (minus (convert (plus:c @0 @1))
-    (convert @0))
+   (minus (convert (plus:c @@0 @1))
+    (convert? @0))
    (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
        /* For integer types, if A has a smaller type
           than T the result depends on the possible
@@ -1794,8 +1794,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
           However, if an overflow in P + A would cause
           undefined behavior, we can assume that there
           is no overflow.  */
-       || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
-           && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
+       || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+           && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))))
     (convert @1)))
   (simplify
    (minus (convert (pointer_plus @@0 @1))
@@ -1818,8 +1818,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
   /* (T)P - (T)(P + A) -> -(T) A */
   (simplify
-   (minus (convert @0)
-    (convert (plus:c @0 @1)))
+   (minus (convert? @0)
+    (convert (plus:c @@0 @1)))
    (if (INTEGRAL_TYPE_P (type)
        && TYPE_OVERFLOW_UNDEFINED (type)
        && element_precision (type) <= element_precision (TREE_TYPE (@1)))
@@ -1833,8 +1833,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
            However, if an overflow in P + A would cause
            undefined behavior, we can assume that there
            is no overflow.  */
-        || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
-            && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
+        || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+            && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))))
      (negate (convert @1)))))
   (simplify
    (minus (convert @0)
@@ -1862,23 +1862,28 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 
   /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */
   (simplify
-   (minus (convert (plus:c @0 @1))
+   (minus (convert (plus:c @@0 @1))
     (convert (plus:c @0 @2)))
    (if (INTEGRAL_TYPE_P (type)
        && TYPE_OVERFLOW_UNDEFINED (type)
-       && element_precision (type) <= element_precision (TREE_TYPE (@1)))
+       && element_precision (type) <= element_precision (TREE_TYPE (@1))
+       && element_precision (type) <= element_precision (TREE_TYPE (@2)))
     (with { tree utype = unsigned_type_for (type); }
      (convert (minus (convert:utype @1) (convert:utype @2))))
-    (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
-        /* For integer types, if A has a smaller type
-           than T the result depends on the possible
-           overflow in P + A.
-           E.g. T=size_t, A=(unsigned)429497295, P>0.
-           However, if an overflow in P + A would cause
-           undefined behavior, we can assume that there
-           is no overflow.  */
-        || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
-            && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
+    (if (((element_precision (type) <= element_precision (TREE_TYPE (@1)))
+         == (element_precision (type) <= element_precision (TREE_TYPE (@2))))
+        && (element_precision (type) <= element_precision (TREE_TYPE (@1))
+            /* For integer types, if A has a smaller type
+               than T the result depends on the possible
+               overflow in P + A.
+               E.g. T=size_t, A=(unsigned)429497295, P>0.
+               However, if an overflow in P + A would cause
+               undefined behavior, we can assume that there
+               is no overflow.  */
+            || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+                && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+                && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))
+                && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@2)))))
      (minus (convert @1) (convert @2)))))
   (simplify
    (minus (convert (pointer_plus @@0 @1))
index 176a7b9c44f8f86f611831b95d3a2a14ca65d8fd..e1196919a3c4b94aed037d50b89a6c70de4be6ce 100644 (file)
@@ -1,3 +1,8 @@
+2017-12-15  Jakub Jelinek  <jakub@redhat.com>
+
+       PR sanitizer/81281
+       * gcc.dg/pr81281-3.c: New test.
+
 2017-12-15  Justin Squirek  <squirek@adacore.com>
 
        * gnat.dg/aliasing4.adb: New testcase.
diff --git a/gcc/testsuite/gcc.dg/pr81281-3.c b/gcc/testsuite/gcc.dg/pr81281-3.c
new file mode 100644 (file)
index 0000000..e491835
--- /dev/null
@@ -0,0 +1,105 @@
+/* PR sanitizer/81281 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "\[+=-] \?123\[ ;]" "optimized" } } */
+
+#ifdef __SIZEOF_INT128__
+__int128
+f1 (int a, long long b)
+{
+  __int128 f = 123 + a;
+  __int128 g = 123 + b;
+  return f - g;
+}
+#endif
+
+signed char
+f2 (int a, long long b)
+{
+  signed char f = 123 + a;
+  signed char g = 123 + b;
+  return f - g;
+}
+
+signed char
+f3 (unsigned int a, unsigned long long b)
+{
+  signed char f = 123 + a;
+  signed char g = 123 + b;
+  return f - g;
+}
+
+unsigned char
+f4 (unsigned int a, unsigned long long b)
+{
+  unsigned char f = 123 + a;
+  unsigned char g = 123 + b;
+  return f - g;
+}
+
+/* This isn't optimized yet.  */
+#if 0
+long long
+f5 (int a)
+{
+  long long f = 123 + a;
+  long long g = 123;
+  return f - g;
+}
+#endif
+
+signed char
+f6 (long long a)
+{
+  signed char f = 123 + a;
+  signed char g = 123;
+  return f - g;
+}
+
+signed char
+f7 (unsigned int a)
+{
+  signed char f = 123 + a;
+  signed char g = 123;
+  return f - g;
+}
+
+unsigned char
+f8 (unsigned long int a)
+{
+  unsigned char f = 123 + a;
+  unsigned char g = 123;
+  return f - g;
+}
+
+long long
+f9 (int a)
+{
+  long long f = 123;
+  long long g = 123 + a;
+  return f - g;
+}
+
+signed char
+f10 (long long a)
+{
+  signed char f = 123;
+  signed char g = 123 + a;
+  return f - g;
+}
+
+signed char
+f11 (unsigned int a)
+{
+  signed char f = 123;
+  signed char g = 123 + a;
+  return f - g;
+}
+
+unsigned char
+f12 (unsigned long int a)
+{
+  unsigned char f = 123;
+  unsigned char g = 123 + a;
+  return f - g;
+}