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 <ja...@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 <ja...@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 <ja...@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. 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,
commit 7f7f6f483863ad9e38cd08e26576b6b9281157d1 Author: Jakub Jelinek <ja...@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 <ja...@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 <ja...@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 <ja...@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);