commit: ca74e5013ee7a20aefc727dade6cc0f6b0724940 Author: Sam James <sam <AT> gentoo <DOT> org> AuthorDate: Tue Sep 16 19:22:41 2025 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Tue Sep 16 19:22:41 2025 +0000 URL: https://gitweb.gentoo.org/proj/gcc-patches.git/commit/?id=ca74e501
16.0.0: add fix for forwprop hang Bug: https://gcc.gnu.org/PR121962 Signed-off-by: Sam James <sam <AT> gentoo.org> 16.0.0/gentoo/87_all_PR121962-forwprop-hang.patch | 161 ++++++++++++++++++++++ 16.0.0/gentoo/README.history | 4 + 2 files changed, 165 insertions(+) diff --git a/16.0.0/gentoo/87_all_PR121962-forwprop-hang.patch b/16.0.0/gentoo/87_all_PR121962-forwprop-hang.patch new file mode 100644 index 0000000..52d25d6 --- /dev/null +++ b/16.0.0/gentoo/87_all_PR121962-forwprop-hang.patch @@ -0,0 +1,161 @@ +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121962#c11 + +From 9463f1db7bc409b9a59dab1d11b6e82e423c4466 Mon Sep 17 00:00:00 2001 +From: Andrew Pinski <[email protected]> +Date: Tue, 16 Sep 2025 10:55:03 -0700 +Subject: [PATCH] forwprop: Fix up "nop" copies after recent changes [PR121962] + +After r16-3887-g597b50abb0d2fc, the check to see if the copy is +a nop copy becomes inefficient. The code going into an infinite +loop as the copy keeps on being propagated over and over again. + +That is if we have: +``` + struct s1 *b = &a.t; + a.t = *b; + p = *b; +``` + +This goes into an infinite loop propagating over and over again the +`MEM[&a]`. +To solve this a new function is needed for the comparison that is +similar to new_src_based_on_copy. + + PR tree-optimization/121962 + +gcc/ChangeLog: + + * tree-ssa-forwprop.cc (same_for_assignment): New function. + (optimize_agr_copyprop_1): Use same_for_assignment to check for + nop copies. + (optimize_agr_copyprop): Likewise. + +gcc/testsuite/ChangeLog: + + * gcc.dg/torture/pr121962-1.c: New test. + +Signed-off-by: Andrew Pinski <[email protected]> +--- + gcc/testsuite/gcc.dg/torture/pr121962-1.c | 21 ++++++++ + gcc/tree-ssa-forwprop.cc | 64 ++++++++++++++++++++++- + 2 files changed, 83 insertions(+), 2 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/torture/pr121962-1.c + +diff --git a/gcc/testsuite/gcc.dg/torture/pr121962-1.c b/gcc/testsuite/gcc.dg/torture/pr121962-1.c +new file mode 100644 +index 00000000000..97f88ad5734 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/torture/pr121962-1.c +@@ -0,0 +1,21 @@ ++/* PR tree-optimization/121962 */ ++struct s1 ++{ ++ int t; ++}; ++ ++struct s2 ++{ ++ struct s1 t; ++}; ++ ++struct s1 p; ++ ++void f(struct s2 a) ++{ ++ struct s1 *b = &a.t; ++ /* this is a nop load/store and should be ignored ++ by copy propagation for aggregates. */ ++ a.t = *b; ++ p = *b; ++} +diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc +index 9d389e1b9bf..833a354ce2c 100644 +--- a/gcc/tree-ssa-forwprop.cc ++++ b/gcc/tree-ssa-forwprop.cc +@@ -1528,6 +1528,66 @@ new_src_based_on_copy (tree src2, tree dest, tree src) + return fold_build1 (VIEW_CONVERT_EXPR,TREE_TYPE (src2), src); + } + ++/* Returns true if SRC and DEST are the same address such that ++ `SRC == DEST;` is conisdered a nop. This is more than an ++ operand_equal_p check as it needs to be similar to ++ new_src_based_on_copy. */ ++ ++static bool ++same_for_assignment (tree src, tree dest) ++{ ++ if (operand_equal_p (dest, src, 0)) ++ return true; ++ /* if both dest and src2 are decls, then we know these 2 ++ accesses can't be the same. */ ++ if (DECL_P (dest) && DECL_P (src)) ++ return false; ++ ++ tree core1, core2; ++ poly_int64 bytepos1, bytepos2; ++ poly_int64 bytesize1, bytesize2; ++ tree toffset1, toffset2; ++ int reversep1 = 0; ++ int reversep2 = 0; ++ poly_int64 diff = 0; ++ core1 = split_core_and_offset_size (dest, &bytesize1, &bytepos1, ++ &toffset1, &reversep1); ++ core2 = split_core_and_offset_size (src, &bytesize2, &bytepos2, ++ &toffset2, &reversep2); ++ if (!core1 || !core2) ++ return false; ++ if (reversep1 != reversep2) ++ return false; ++ /* The sizes of the 2 accesses need to be the same. */ ++ if (!known_eq (bytesize1, bytesize2)) ++ return false; ++ if (!operand_equal_p (core1, core2, 0)) ++ return false; ++ if (toffset1 && toffset2) ++ { ++ tree type = TREE_TYPE (toffset1); ++ if (type != TREE_TYPE (toffset2)) ++ toffset2 = fold_convert (type, toffset2); ++ ++ tree tdiff = fold_build2 (MINUS_EXPR, type, toffset1, toffset2); ++ if (!cst_and_fits_in_hwi (tdiff)) ++ return false; ++ ++ diff = int_cst_value (tdiff); ++ } ++ else if (toffset1 || toffset2) ++ { ++ /* If only one of the offsets is non-constant, the difference cannot ++ be a constant. */ ++ return false; ++ } ++ diff += bytepos1 - bytepos2; ++ /* The offset between the 2 need to be 0. */ ++ if (!known_eq (diff, 0)) ++ return false; ++ return true; ++} ++ + /* Helper function for optimize_agr_copyprop. + For aggregate copies in USE_STMT, see if DEST + is on the lhs of USE_STMT and replace it with SRC. */ +@@ -1542,7 +1602,7 @@ optimize_agr_copyprop_1 (gimple *stmt, gimple *use_stmt, + tree dest2 = gimple_assign_lhs (use_stmt); + tree src2 = gimple_assign_rhs1 (use_stmt); + /* If the new store is `src2 = src2;` skip over it. */ +- if (operand_equal_p (src2, dest2, 0)) ++ if (same_for_assignment (src2, dest2)) + return false; + src = new_src_based_on_copy (src2, dest, src); + if (!src) +@@ -1702,7 +1762,7 @@ optimize_agr_copyprop (gimple_stmt_iterator *gsip) + tree dest = gimple_assign_lhs (stmt); + tree src = gimple_assign_rhs1 (stmt); + /* If the statement is `src = src;` then ignore it. */ +- if (operand_equal_p (dest, src, 0)) ++ if (same_for_assignment (dest, src)) + return false; + + tree vdef = gimple_vdef (stmt); +-- +2.43.0 diff --git a/16.0.0/gentoo/README.history b/16.0.0/gentoo/README.history index 3a58f30..7db3c43 100644 --- a/16.0.0/gentoo/README.history +++ b/16.0.0/gentoo/README.history @@ -1,3 +1,7 @@ +15 ???? + + + 87_all_PR121962-forwprop-hang.patch + 14 7 September 2025 - 91_all_PR121699-mesa.patch
