Hi!

My earlier patch to demote arguments of __builtin_*_overflow unfortunately
caused a wrong-code regression.  The builtins operate on infinite precision
arguments, outer_prec > inner_prec signed -> signed, unsigned -> unsigned
promotions there are just repeating the sign or 0s and can be demoted,
similarly unsigned -> signed which also is repeating 0s, but as the
testcase shows, signed -> unsigned promotions need to be preserved (unless
we'd know the inner arguments can't be negative), because for negative
numbers such promotion sets the outer_prec -> inner_prec bits to 1 bit the
bits above that to 0 in the infinite precision.

So, the following patch avoids the demotions for the signed -> unsigned
promotions.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2021-09-06  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/102207
        * match.pd: Don't demote operands of IFN_{ADD,SUB,MUL}_OVERFLOW if they
        were promoted from signed to wider unsigned type.

        * gcc.dg/pr102207.c: New test.

--- gcc/match.pd.jj     2021-09-02 22:49:34.963322655 +0200
+++ gcc/match.pd        2021-09-05 12:23:23.878476233 +0200
@@ -5593,13 +5593,15 @@ (define_operator_list COND_TERNARY
   (ovf (convert@2 @0) @1)
   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
        && INTEGRAL_TYPE_P (TREE_TYPE (@2))
-       && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0)))
+       && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+       && (!TYPE_UNSIGNED (TREE_TYPE (@2)) || TYPE_UNSIGNED (TREE_TYPE (@0))))
    (ovf @0 @1)))
  (simplify
   (ovf @1 (convert@2 @0))
   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
        && INTEGRAL_TYPE_P (TREE_TYPE (@2))
-       && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0)))
+       && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+       && (!TYPE_UNSIGNED (TREE_TYPE (@2)) || TYPE_UNSIGNED (TREE_TYPE (@0))))
    (ovf @1 @0))))
 
 /* Simplification of math builtins.  These rules must all be optimizations
--- gcc/testsuite/gcc.dg/pr102207.c.jj  2021-09-05 12:31:38.967509895 +0200
+++ gcc/testsuite/gcc.dg/pr102207.c     2021-09-05 12:31:12.136887427 +0200
@@ -0,0 +1,24 @@
+/* PR tree-optimization/102207 */
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O2" } */
+
+typedef unsigned __int128 u128;
+
+u128
+foo (unsigned short a)
+{
+  u128 g;
+  __builtin_sub_overflow ((unsigned long long) -a, 1, &g);
+  return g;
+}
+
+int
+main ()
+{
+  if (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ != 64
+      || __SIZEOF_SHORT__ * __CHAR_BIT__ != 16)
+    return 0;
+  if (foo (1) != 0xfffffffffffffffeULL)
+    __builtin_abort ();
+  return 0;
+}

        Jakub

Reply via email to