public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r10-10705] fold-const: Fix up make_range_step [PR105189]
@ 2022-05-10  8:26 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2022-05-10  8:26 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:a954df6a075d5d1e91f98e3c686e5da62c829cf9

commit r10-10705-ga954df6a075d5d1e91f98e3c686e5da62c829cf9
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Apr 8 09:14:44 2022 +0200

    fold-const: Fix up make_range_step [PR105189]
    
    The following testcase is miscompiled, because fold_truth_andor
    incorrectly folds
    (unsigned) foo () >= 0U && 1
    into
    foo () >= 0
    For the unsigned comparison (which is useless in this case,
    as >= 0U is always true, but hasn't been folded yet), previous
    make_range_step derives exp (unsigned) foo () and +[0U, -]
    range for it.  Next we process the NOP_EXPR.  We have special code
    for unsigned to signed casts, already earlier punt if low or high
    aren't representable in arg0_type or if it is a narrowing conversion.
    For the signed to unsigned casts, I think if high is specified we
    are still fine, as we punt for non-representable values in arg0_type,
    n_high is then still representable and so was smaller or equal to
    signed maximum and either low is not present (equivalent to 0U), or
    low must be smaller or equal to high and so for unsigned exp
    +[low, high] the signed exp +[n_low, n_high] will be correct.
    Similarly, if both low and high aren't specified (always true or
    always false), it is ok too.
    But if we have for unsigned exp +[low, -] or -[low, -], using
    +[n_low, -] or -[n_high, -] is incorrect.  Because low is smaller
    or equal to signed maximum and high is unspecified (i.e. unsigned
    maximum), when signed that range is a union of +[n_low, -] and
    +[-, -1] which is equivalent to -[0, n_low-1], unless low
    is 0, in that case we can treat it as [-, -].
    
    2022-04-08  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/105189
            * fold-const.c (make_range_step): Fix up handling of
            (unsigned) x +[low, -] ranges for signed x if low fits into
            typeof (x).
    
            * g++.dg/torture/pr105189.C: New test.
    
    (cherry picked from commit 5e6597064b0c7eb93b8f720afc4aa970eefb0628)

Diff:
---
 gcc/fold-const.c                        | 28 +++++++++++++++++++++++++++-
 gcc/testsuite/g++.dg/torture/pr105189.C | 19 +++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e2384d81ea2..94f92e63893 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -5119,7 +5119,7 @@ make_range_step (location_t loc, enum tree_code code, tree arg0, tree arg1,
 	n_high = fold_convert_loc (loc, arg0_type, n_high);
 
       /* If we're converting arg0 from an unsigned type, to exp,
-	 a signed type,  we will be doing the comparison as unsigned.
+	 a signed type, we will be doing the comparison as unsigned.
 	 The tests above have already verified that LOW and HIGH
 	 are both positive.
 
@@ -5181,6 +5181,32 @@ make_range_step (location_t loc, enum tree_code code, tree arg0, tree arg1,
 	    }
 	}
 
+      /* Otherwise, if we are converting arg0 from signed type, to exp,
+	 an unsigned type, we will do the comparison as signed.  If
+	 high is non-NULL, we punt above if it doesn't fit in the signed
+	 type, so if we get through here, +[-, high] or +[low, high] are
+	 equivalent to +[-, n_high] or +[n_low, n_high].  Similarly,
+	 +[-, -] or -[-, -] are equivalent too.  But if low is specified and
+	 high is not, the +[low, -] range is equivalent to union of
+	 +[n_low, -] and +[-, -1] ranges, so +[low, -] is equivalent to
+	 -[0, n_low-1] and similarly -[low, -] to +[0, n_low-1], except for
+	 low being 0, which should be treated as [-, -].  */
+      else if (TYPE_UNSIGNED (exp_type)
+	       && !TYPE_UNSIGNED (arg0_type)
+	       && low
+	       && !high)
+	{
+	  if (integer_zerop (low))
+	    n_low = NULL_TREE;
+	  else
+	    {
+	      n_high = fold_build2_loc (loc, PLUS_EXPR, arg0_type,
+					n_low, build_int_cst (arg0_type, -1));
+	      n_low = build_zero_cst (arg0_type);
+	      in_p = !in_p;
+	    }
+	}
+
       *p_low = n_low;
       *p_high = n_high;
       *p_in_p = in_p;
diff --git a/gcc/testsuite/g++.dg/torture/pr105189.C b/gcc/testsuite/g++.dg/torture/pr105189.C
new file mode 100644
index 00000000000..a3870772cfe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr105189.C
@@ -0,0 +1,19 @@
+// PR tree-optimization/105189
+// { dg-do run }
+
+int
+foo ()
+{
+  return -1;
+}
+
+int
+main ()
+{
+  int c = foo () >= 0U && 1;
+  if (c != 1)
+    __builtin_abort ();
+  int d = foo () >= 3U && 1;
+  if (d != 1)
+    __builtin_abort ();
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-10  8:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-10  8:26 [gcc r10-10705] fold-const: Fix up make_range_step [PR105189] Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).