Backport PR106878 fixes to GCC 12

Message ID ZTZ1wAAwCWg0hFMH@arm.com
State Unresolved
Headers
Series Backport PR106878 fixes to GCC 12 |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Alex Coplan Oct. 23, 2023, 1:31 p.m. UTC
  Hi,

I'd like to submit the attached three patches from Jakub for backporting to GCC 12.
These are the backports proposed at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106878#c18 i.e.:

r13-2658-g645ef01a463f15fc230e2155719c7a12cec89acf without the gimple verifier changes.
r13-2709-g9ac9fde961f76879f0379ff3b2494a2f9ac915f7
r13-2891-gcb8f25c5dc9f6d5207c826c2dafe25f68458ceaf

For the first patch, I was thinking of backporting it with the cover letter as
follows:

Disallow pointer operands for |, ^ and partly & [PR106878]

This is a backport of 645ef01a463f15fc230e2155719c7a12cec89acf without the
changes to verify_gimple_assign_binary from the original patch.  The original
cover letter for the patch is as follows:

My change to match.pd (that added the two simplifications this patch
touches) results in more |/^/& assignments with pointer arguments,
but since r12-1608 we reject pointer operands for BIT_NOT_EXPR.

Disallowing them for BIT_NOT_EXPR and allowing for BIT_{IOR,XOR,AND}_EXPR
leads to a match.pd maintainance nightmare (see one of the patches in the
PR), so either we want to allow pointer operand on BIT_NOT_EXPR (but then
we run into issues e.g. with the ranger which expects it can emulate
BIT_NOT_EXPR ~X as - 1 - X which doesn't work for pointers which don't
support MINUS_EXPR), or the following patch disallows pointer arguments
for all of BIT_{IOR,XOR,AND}_EXPR with the exception of BIT_AND_EXPR
with INTEGER_CST last operand (for simpler pointer realignment).
I had to tweak one reassoc optimization and the two match.pd
simplifications.

2022-09-14  Jakub Jelinek  <jakub@redhat.com>

        PR tree-optimization/106878
        * match.pd ((type) X op CST -> (type) (X op ((type-x) CST)),
        (type) (((type2) X) op Y) -> (X op (type) Y)): Punt for
        POINTER_TYPE_P or OFFSET_TYPE.
        * tree-ssa-reassoc.cc (optimize_range_tests_cmp_bitwise): For
        pointers cast them to pointer sized integers first.

        * gcc.c-torture/compile/pr106878.c: New test.

------

The other two patches can then be simple cherry picks.  (Or we could squash them
into a single patch, if that's deemed preferable).

I've bootstrapped and tested these on top of the GCC 12 branch on both
x86_64-linux-gnu and aarch64-linux-gnu, and there were no regressions.

OK for the GCC 12 branch?

Thanks,
Alex
commit 557c126f9fbdcde256f134d4ed34ff305387fd41
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Sep 14 11:36:36 2022

    Disallow pointer operands for |, ^ and partly & [PR106878]
    
    This is a backport of 645ef01a463f15fc230e2155719c7a12cec89acf without the
    changes to verify_gimple_assign_binary from the original patch.  The original
    cover letter for the patch is as follows:
    
    My change to match.pd (that added the two simplifications this patch
    touches) results in more |/^/& assignments with pointer arguments,
    but since r12-1608 we reject pointer operands for BIT_NOT_EXPR.
    
    Disallowing them for BIT_NOT_EXPR and allowing for BIT_{IOR,XOR,AND}_EXPR
    leads to a match.pd maintainance nightmare (see one of the patches in the
    PR), so either we want to allow pointer operand on BIT_NOT_EXPR (but then
    we run into issues e.g. with the ranger which expects it can emulate
    BIT_NOT_EXPR ~X as - 1 - X which doesn't work for pointers which don't
    support MINUS_EXPR), or the following patch disallows pointer arguments
    for all of BIT_{IOR,XOR,AND}_EXPR with the exception of BIT_AND_EXPR
    with INTEGER_CST last operand (for simpler pointer realignment).
    I had to tweak one reassoc optimization and the two match.pd
    simplifications.
    
    2022-09-14  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/106878
            * match.pd ((type) X op CST -> (type) (X op ((type-x) CST)),
            (type) (((type2) X) op Y) -> (X op (type) Y)): Punt for
            POINTER_TYPE_P or OFFSET_TYPE.
            * tree-ssa-reassoc.cc (optimize_range_tests_cmp_bitwise): For
            pointers cast them to pointer sized integers first.
    
            * gcc.c-torture/compile/pr106878.c: New test.
commit 7f7f6f483863ad9e38cd08e26576b6b9281157d1
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Sat Sep 17 07:18:24 2022

    reassoc: Fix up recent regression in optimize_range_tests_cmp_bitwise [PR106958]
    
    As the following testcase reduced from glibc fmtmsg.c shows
    (it doesn't ICE on x86_64/i686 unfortunately, but does on various other
    arches), my last optimize_range_tests_cmp_bitwise change wasn't fully
    correct.  The intent was to let all pointer operands be cast to
    pointer_sized_int_node first in addition to the other casts (to type1)
    which are done for id >= l cases.
    But one spot I've touched used always cast to type1 (note, the (b % 4) == 3
    case is impossible for pointer operands because that is for !TYPE_UNSIGNED
    operands and pointers are TYPE_UNSIGNED) and in the other spot the cast
    would be done only for id >= l if not useless, but for pointers we need
    to cast it always.
    
    2022-09-17  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/106958
            * tree-ssa-reassoc.cc (optimize_range_tests_cmp_bitwise): If
            id >= l, cast op to type1, otherwise to pointer_sized_int_node.
            If type has pointer type, cast exp to pointer_sized_int_node
            even when id < l.
    
            * gcc.c-torture/compile/pr106958.c: New test.
    
    (cherry picked from commit 9ac9fde961f76879f0379ff3b2494a2f9ac915f7)

diff --git a/gcc/testsuite/gcc.c-torture/compile/pr106958.c b/gcc/testsuite/gcc.c-torture/compile/pr106958.c
new file mode 100644
index 00000000000..98e6554c736
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr106958.c
@@ -0,0 +1,13 @@
+/* PR tree-optimization/106958 */
+
+int a;
+void bar (int);
+
+void
+foo (char *x, char *y)
+{
+  int b = a != 0;
+  int c = x != 0;
+  int d = y != 0;
+  bar (b | c | d);
+}
diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
index 6baef476471..a4fcd0f35d9 100644
--- a/gcc/tree-ssa-reassoc.cc
+++ b/gcc/tree-ssa-reassoc.cc
@@ -3689,15 +3689,18 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 	    if (id == l || POINTER_TYPE_P (TREE_TYPE (op)))
 	      {
 		code = (b % 4) == 3 ? BIT_NOT_EXPR : NOP_EXPR;
-		g = gimple_build_assign (make_ssa_name (type1), code, op);
+		tree type3 = id >= l ? type1 : pointer_sized_int_node;
+		g = gimple_build_assign (make_ssa_name (type3), code, op);
 		gimple_seq_add_stmt_without_update (&seq, g);
 		op = gimple_assign_lhs (g);
 	      }
 	    tree type = TREE_TYPE (r->exp);
 	    tree exp = r->exp;
-	    if (id >= l && !useless_type_conversion_p (type1, type))
+	    if (POINTER_TYPE_P (type)
+		|| (id >= l && !useless_type_conversion_p (type1, type)))
 	      {
-		g = gimple_build_assign (make_ssa_name (type1), NOP_EXPR, exp);
+		tree type3 = id >= l ? type1 : pointer_sized_int_node;
+		g = gimple_build_assign (make_ssa_name (type3), NOP_EXPR, exp);
 		gimple_seq_add_stmt_without_update (&seq, g);
 		exp = gimple_assign_lhs (g);
 	      }
commit 3d6914b0dfd595a091723d95aba1641b0bdbe4fb
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Tue Sep 27 07:26:18 2022

    reassoc: Handle OFFSET_TYPE like POINTER_TYPE in optimize_range_tests_cmp_bitwise [PR107029[
    
    As the testcase shows, OFFSET_TYPE needs the same treatment as
    POINTER_TYPE/REFERENCE_TYPE, otherwise we fail the same during the
    newly added verification.  OFFSET_TYPE is signed though, so unlike
    POINTER_TYPE/REFERENCE_TYPE it can also trigger with the
    x < 0 && y < 0 && z < 0 to (x | y | z) < 0
    optimization.
    
    2022-09-27  Jakub Jelinek  <jakub@redhat.com>
    
            PR tree-optimization/107029
            * tree-ssa-reassoc.cc (optimize_range_tests_cmp_bitwise): Treat
            OFFSET_TYPE like POINTER_TYPE, except that OFFSET_TYPE may be
            signed and so can trigger even the (b % 4) == 3 case.
    
            * g++.dg/torture/pr107029.C: New test.
    
    (cherry picked from commit cb8f25c5dc9f6d5207c826c2dafe25f68458ceaf)

diff --git a/gcc/testsuite/g++.dg/torture/pr107029.C b/gcc/testsuite/g++.dg/torture/pr107029.C
new file mode 100644
index 00000000000..93c7f28fb4c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr107029.C
@@ -0,0 +1,19 @@
+// PR tree-optimization/107029
+// { dg-do compile }
+
+struct S { long long a; int b; };
+long long S::*a;
+int S::*b;
+struct A { void foo (bool, bool); void bar (); int c; };
+
+void
+A::foo (bool a, bool b)
+{
+  c = a || b;
+}
+
+void
+A::bar()
+{
+  foo (a, b);
+}
diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
index a4fcd0f35d9..61d718aa46a 100644
--- a/gcc/tree-ssa-reassoc.cc
+++ b/gcc/tree-ssa-reassoc.cc
@@ -3617,13 +3617,13 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 	tree type2 = NULL_TREE;
 	bool strict_overflow_p = false;
 	candidates.truncate (0);
-	if (POINTER_TYPE_P (type1))
+	if (POINTER_TYPE_P (type1) || TREE_CODE (type1) == OFFSET_TYPE)
 	  type1 = pointer_sized_int_node;
 	for (j = i; j; j = chains[j - 1])
 	  {
 	    tree type = TREE_TYPE (ranges[j - 1].exp);
 	    strict_overflow_p |= ranges[j - 1].strict_overflow_p;
-	    if (POINTER_TYPE_P (type))
+	    if (POINTER_TYPE_P (type) || TREE_CODE (type) == OFFSET_TYPE)
 	      type = pointer_sized_int_node;
 	    if ((b % 4) == 3)
 	      {
@@ -3655,7 +3655,7 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 	    tree type = TREE_TYPE (ranges[j - 1].exp);
 	    if (j == k)
 	      continue;
-	    if (POINTER_TYPE_P (type))
+	    if (POINTER_TYPE_P (type) || TREE_CODE (type) == OFFSET_TYPE)
 	      type = pointer_sized_int_node;
 	    if ((b % 4) == 3)
 	      {
@@ -3686,10 +3686,20 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 		op = r->exp;
 		continue;
 	      }
-	    if (id == l || POINTER_TYPE_P (TREE_TYPE (op)))
+	    if (id == l
+		|| POINTER_TYPE_P (TREE_TYPE (op))
+		|| TREE_CODE (TREE_TYPE (op)) == OFFSET_TYPE)
 	      {
 		code = (b % 4) == 3 ? BIT_NOT_EXPR : NOP_EXPR;
 		tree type3 = id >= l ? type1 : pointer_sized_int_node;
+		if (code == BIT_NOT_EXPR
+		    && TREE_CODE (TREE_TYPE (op)) == OFFSET_TYPE)
+		  {
+		    g = gimple_build_assign (make_ssa_name (type3),
+					     NOP_EXPR, op);
+		    gimple_seq_add_stmt_without_update (&seq, g);
+		    op = gimple_assign_lhs (g);
+		  }
 		g = gimple_build_assign (make_ssa_name (type3), code, op);
 		gimple_seq_add_stmt_without_update (&seq, g);
 		op = gimple_assign_lhs (g);
@@ -3697,6 +3707,7 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 	    tree type = TREE_TYPE (r->exp);
 	    tree exp = r->exp;
 	    if (POINTER_TYPE_P (type)
+		|| TREE_CODE (type) == OFFSET_TYPE
 		|| (id >= l && !useless_type_conversion_p (type1, type)))
 	      {
 		tree type3 = id >= l ? type1 : pointer_sized_int_node;
@@ -3714,7 +3725,7 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 	    op = gimple_assign_lhs (g);
 	  }
 	type1 = TREE_TYPE (ranges[k - 1].exp);
-	if (POINTER_TYPE_P (type1))
+	if (POINTER_TYPE_P (type1) || TREE_CODE (type1) == OFFSET_TYPE)
 	  {
 	    gimple *g
 	      = gimple_build_assign (make_ssa_name (type1), NOP_EXPR, op);
  

Patch

diff --git a/gcc/match.pd b/gcc/match.pd
index a9aae484b2b..cbae09dfb28 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1663,6 +1663,8 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 	 && (int_fits_type_p (@1, TREE_TYPE (@0))
 	     || tree_nop_conversion_p (TREE_TYPE (@0), type)))
 	|| types_match (@0, @1))
+       && !POINTER_TYPE_P (TREE_TYPE (@0))
+       && TREE_CODE (TREE_TYPE (@0)) != OFFSET_TYPE
        /* ???  This transform conflicts with fold-const.cc doing
 	  Convert (T)(x & c) into (T)x & (T)c, if c is an integer
 	  constants (if x has signed type, the sign bit cannot be set
@@ -1699,7 +1701,9 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (GIMPLE
        && TREE_CODE (@1) != INTEGER_CST
        && tree_nop_conversion_p (type, TREE_TYPE (@2))
-       && types_match (type, @0))
+       && types_match (type, @0)
+       && !POINTER_TYPE_P (TREE_TYPE (@0))
+       && TREE_CODE (TREE_TYPE (@0)) != OFFSET_TYPE)
    (bitop @0 (convert @1)))))
 
 (for bitop (bit_and bit_ior)
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr106878.c b/gcc/testsuite/gcc.c-torture/compile/pr106878.c
new file mode 100644
index 00000000000..c8457189437
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr106878.c
@@ -0,0 +1,15 @@ 
+/* PR tree-optimization/106878 */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
+int a;
+
+int
+foo (const int *c)
+{
+  uintptr_t d = ((intptr_t) c | (intptr_t) &a) & 65535 << 16;
+  intptr_t e = (intptr_t) c;
+  if (d != (e & 65535 << 16))
+    return 1;
+  return 0;
+}
diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
index e3d521e3267..6baef476471 100644
--- a/gcc/tree-ssa-reassoc.cc
+++ b/gcc/tree-ssa-reassoc.cc
@@ -3617,10 +3617,14 @@  optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 	tree type2 = NULL_TREE;
 	bool strict_overflow_p = false;
 	candidates.truncate (0);
+	if (POINTER_TYPE_P (type1))
+	  type1 = pointer_sized_int_node;
 	for (j = i; j; j = chains[j - 1])
 	  {
 	    tree type = TREE_TYPE (ranges[j - 1].exp);
 	    strict_overflow_p |= ranges[j - 1].strict_overflow_p;
+	    if (POINTER_TYPE_P (type))
+	      type = pointer_sized_int_node;
 	    if ((b % 4) == 3)
 	      {
 		/* For the signed < 0 cases, the types should be
@@ -3651,6 +3655,8 @@  optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 	    tree type = TREE_TYPE (ranges[j - 1].exp);
 	    if (j == k)
 	      continue;
+	    if (POINTER_TYPE_P (type))
+	      type = pointer_sized_int_node;
 	    if ((b % 4) == 3)
 	      {
 		if (!useless_type_conversion_p (type1, type))
@@ -3680,7 +3686,7 @@  optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 		op = r->exp;
 		continue;
 	      }
-	    if (id == l)
+	    if (id == l || POINTER_TYPE_P (TREE_TYPE (op)))
 	      {
 		code = (b % 4) == 3 ? BIT_NOT_EXPR : NOP_EXPR;
 		g = gimple_build_assign (make_ssa_name (type1), code, op);
@@ -3704,6 +3710,14 @@  optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
 	    gimple_seq_add_stmt_without_update (&seq, g);
 	    op = gimple_assign_lhs (g);
 	  }
+	type1 = TREE_TYPE (ranges[k - 1].exp);
+	if (POINTER_TYPE_P (type1))
+	  {
+	    gimple *g
+	      = gimple_build_assign (make_ssa_name (type1), NOP_EXPR, op);
+	    gimple_seq_add_stmt_without_update (&seq, g);
+	    op = gimple_assign_lhs (g);
+	  }
 	candidates.pop ();
 	if (update_range_test (&ranges[k - 1], NULL, candidates.address (),
 			       candidates.length (), opcode, ops, op,