Launchpad has imported 14 comments from the remote bug at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123002.
If you reply to an imported comment from within Launchpad, your comment will be sent to the remote bug automatically. Read more about Launchpad's inter-bugtracker facilities at https://documentation.ubuntu.com/launchpad/user/reference/bugs/multi-project-bugs/about-multi-project-bugs/#bugs-in-external-trackers. ------------------------------------------------------------------------ On 2025-12-04T14:05:54+00:00 6-liam wrote: The vectorization tree optimization has a bug that leads to gcc producing incorrect code for widening multiplications. Incorrect code is produced for C inputs as simple as: main.c: ``` static unsigned int const enc_table_32[8][3] = { {513735U, 77223048U, 437087610U }, {0U, 78508U, 646269101U }, {0U, 0U, 11997U, }, {0U, 0U, 0U, }, {0U, 0U, 0U, }, {0U, 0U, 0U, }, {0U, 0U, 0U, }, {0U, 0U, 0U, }}; int main() { unsigned long intermediate[3] = {0}; for (unsigned long i = 0UL; i < 8; i++) { intermediate[0] += 2 * (unsigned long)(enc_table_32)[i][0]; intermediate[1] += 2 * (unsigned long)(enc_table_32)[i][1]; intermediate[2] += 2 * (unsigned long)(enc_table_32)[i][2]; } if (intermediate[0] == 0xfad8e && intermediate[1] == 0x9370e68 && intermediate[2] == 0x8125ca08) { return 0; } else { return 1; } } ``` `gcc-14 -mavx2 -O3 main.c` will correctly produce an a.out that returns 0 when run: ``` main: xor eax, eax ret ``` `gcc-15 -mavx2 -O3 main.c` however, will produce incorrect machine code, where `./a.out` return 1. ``` main: mov eax, 1 ret ``` This and the faulty pass are conveniently inspectable side-by-side here: https://godbolt.org/z/bbssefq39 The problem can be narrowed down to the vectorization tree optimization pass, where it selects WIDEN_MULT_LO_EXPR and WIDEN_MULT_HI_EXPR for a "reduction", in a way that is only generally valid for a scalar result, not for an array/vector. Essentially, it confuses the cases described here: https://gcc.gnu.org/cgit/gcc/tree/gcc/tree-vect-stmts.cc?id=d3e71b99194bff878d3bf3b35f9528a350d10df9#n14154 ``` ... vect__1.9_46 = MEM <const vector(8) unsigned int> [(unsigned int *)vectp_enc_table_32.7_54]; vectp_enc_table_32.7_45 = vectp_enc_table_32.7_54 + 32; vect__1.10_44 = MEM <const vector(8) unsigned int> [(unsigned int *)vectp_enc_table_32.7_45]; vectp_enc_table_32.7_43 = vectp_enc_table_32.7_54 + 64; vect__1.11_42 = MEM <const vector(8) unsigned int> [(unsigned int *)vectp_enc_table_32.7_43]; vect_patt_57.12_41 = WIDEN_MULT_LO_EXPR <vect__1.9_46, { 2, 2, 2, 2, 2, 2, 2, 2 }>; vect_patt_57.12_40 = WIDEN_MULT_HI_EXPR <vect__1.9_46, { 2, 2, 2, 2, 2, 2, 2, 2 }>; vect_patt_57.12_39 = WIDEN_MULT_LO_EXPR <vect__1.10_44, { 2, 2, 2, 2, 2, 2, 2, 2 }>; vect_patt_57.12_37 = WIDEN_MULT_HI_EXPR <vect__1.10_44, { 2, 2, 2, 2, 2, 2, 2, 2 }>; vect_patt_57.12_35 = WIDEN_MULT_LO_EXPR <vect__1.11_42, { 2, 2, 2, 2, 2, 2, 2, 2 }>; vect_patt_57.12_32 = WIDEN_MULT_HI_EXPR <vect__1.11_42, { 2, 2, 2, 2, 2, 2, 2, 2 }>; vect__4.14_13 = vect_patt_57.12_41 + vect_intermediate$0_38.13_31; vect__4.14_51 = vect_patt_57.12_40 + vect_intermediate$0_38.13_30; vect__4.14_52 = vect_patt_57.12_39 + vect_intermediate$0_38.13_18; vect__4.14_49 = vect_patt_57.12_37 + vect_intermediate$0_38.13_17; vect__4.14_50 = vect_patt_57.12_35 + vect_intermediate$0_38.13_16; vect__4.14_47 = vect_patt_57.12_32 + vect_intermediate$0_38.13_14; ... _68 = BIT_FIELD_REF <vect__4.14_48, 64, 0>; _69 = BIT_FIELD_REF <vect__4.14_48, 64, 64>; _70 = BIT_FIELD_REF <vect__4.14_48, 64, 128>; _71 = BIT_FIELD_REF <vect__4.14_48, 64, 192>; _72 = BIT_FIELD_REF <vect__4.14_63, 64, 0>; _73 = BIT_FIELD_REF <vect__4.14_63, 64, 64>; _74 = BIT_FIELD_REF <vect__4.14_63, 64, 128>; _75 = BIT_FIELD_REF <vect__4.14_63, 64, 192>; _76 = BIT_FIELD_REF <vect__4.14_64, 64, 0>; _77 = BIT_FIELD_REF <vect__4.14_64, 64, 64>; _78 = BIT_FIELD_REF <vect__4.14_64, 64, 128>; _79 = BIT_FIELD_REF <vect__4.14_64, 64, 192>; _80 = BIT_FIELD_REF <vect__4.14_65, 64, 0>; _81 = BIT_FIELD_REF <vect__4.14_65, 64, 64>; _82 = BIT_FIELD_REF <vect__4.14_65, 64, 128>; _83 = BIT_FIELD_REF <vect__4.14_65, 64, 192>; _84 = BIT_FIELD_REF <vect__4.14_66, 64, 0>; _85 = BIT_FIELD_REF <vect__4.14_66, 64, 64>; _86 = BIT_FIELD_REF <vect__4.14_66, 64, 128>; _87 = BIT_FIELD_REF <vect__4.14_66, 64, 192>; _88 = BIT_FIELD_REF <vect__4.14_67, 64, 0>; _89 = BIT_FIELD_REF <vect__4.14_67, 64, 64>; _90 = BIT_FIELD_REF <vect__4.14_67, 64, 128>; _91 = BIT_FIELD_REF <vect__4.14_67, 64, 192>; _92 = _68 + _71; _93 = _69 + _72; _94 = _70 + _73; _95 = _92 + _74; _96 = _93 + _75; _97 = _94 + _76; _98 = _95 + _77; _99 = _96 + _78; _100 = _97 + _79; _101 = _98 + _80; _102 = _99 + _81; _103 = _100 + _82; _104 = _101 + _83; _105 = _102 + _84; _106 = _103 + _85; _107 = _104 + _86; _108 = _105 + _87; _109 = _106 + _88; _110 = _107 + _89; _111 = _108 + _90; _112 = _109 + _91; _25 = _111 == 154603112; _24 = _110 == 1027470; _23 = _24 & _25; _26 = _112 == 2166737416; _27 = _23 & _26; _28 = ~_27; _29 = (int) _28; return _29; ``` This lines up with the bisect result where the bug is first triggered on this commit: d3e71b99194bff878d3bf3b35f9528a350d10df9 / https://inbox.sourceware.org/gcc- patches/[email protected]/T/ Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/0 ------------------------------------------------------------------------ On 2025-12-04T14:40:49+00:00 Rguenth wrote: Confirmed. I'm not sure we have a bug for this but I have a patch in my tree in this area but did not have a testcase for the wrong-code issue (thanks for providing it!). My patch notes the issue (but does not fix it): @@ -5215,10 +5216,32 @@ vectorizable_conversion (vec_info *vinfo, gcc_assert (!(multi_step_cvt && op_type == binary_op)); break; } - if (supportable_widening_operation (vinfo, code, stmt_info, - vectype_out, vectype_in, &code1, - &code2, &multi_step_cvt, - &interm_types)) + /* Elements in a vector with vect_used_by_reduction property cannot + be reordered if the use chain with this property does not have the + same operation. One such an example is s += a * b, where elements + in a and b cannot be reordered. Here we check if the vector defined + by STMT is only directly used in the reduction statement. */ + if (loop_vinfo + && !nested_in_vect_loop_p (LOOP_VINFO_LOOP (loop_vinfo), stmt_info)) + { + tree lhs = gimple_get_lhs (vect_orig_stmt (stmt_info)->stmt); + stmt_vec_info use_stmt_info + = lhs ? loop_vinfo->lookup_single_use (lhs) : NULL; + /* ??? This isn't a sufficient check - the reduction path + could have more than a single operation. Also for a SLP + reduction we cannot swizzle lanes, only for a reduction + chain or a reduction group of size one. We cannot rely + on the reduction being analyzed yet, so there is no good + way to check whether this is safe, apart from a very + conservative SLP_TREE_LANES == 1. This should have been + detected as WIDEN_MULT_PLUS_EXPR reduction instead. */ + if (use_stmt_info && STMT_VINFO_REDUC_DEF (use_stmt_info)) + evenodd_ok = true; + } + if (supportable_widening_operation (code, vectype_out, vectype_in, + evenodd_ok, &code1, + &code2, &multi_step_cvt, + &interm_types)) { Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/1 ------------------------------------------------------------------------ On 2025-12-04T14:42:38+00:00 Rguenth wrote: Created attachment 62993 patch from my tree This is the full patch, as said I do not expect it to fix the issue. I'll work on this from here. Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/2 ------------------------------------------------------------------------ On 2025-12-05T08:24:56+00:00 Rguenth wrote: Note I cannot reproduce the issue on trunk where we no longer recognize a widen_mult pattern, but the principle issue is still there IMO. I wonder what fixed it on trunk. Better testcase: static unsigned int const enc_table_32[8][3] = { {513735U, 77223048U, 437087610U }, {0U, 78508U, 646269101U }, {0U, 0U, 11997U, }, {0U, 0U, 0U, }, {0U, 0U, 0U, }, {0U, 0U, 0U, }, {0U, 0U, 0U, }, {0U, 0U, 0U, }}; int __attribute__((noipa)) foo() { unsigned long intermediate[3] = {0}; for (unsigned long i = 0UL; i < 8; i++) { intermediate[0] += 2 * (unsigned long)(enc_table_32)[i][0]; intermediate[1] += 2 * (unsigned long)(enc_table_32)[i][1]; intermediate[2] += 2 * (unsigned long)(enc_table_32)[i][2]; } if (intermediate[0] == 0xfad8e && intermediate[1] == 0x9370e68 && intermediate[2] == 0x8125ca08) { return 0; } else { return 1; } } int main() { if (foo ()) __builtin_abort (); return 0; } Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/3 ------------------------------------------------------------------------ On 2025-12-05T11:34:08+00:00 Cvs-commit wrote: The master branch has been updated by Richard Biener <[email protected]>: https://gcc.gnu.org/g:1da0e5c1405e87e9f2a11ed358b40dff21085657 commit r16-5902-g1da0e5c1405e87e9f2a11ed358b40dff21085657 Author: Richard Biener <[email protected]> Date: Thu Aug 21 13:46:06 2025 +0200 Move even/odd validity check from supportable_widening_operation to caller The following moves the incomplete validity check to use WIDEN_MULT_{EVEN,ODD} to the caller of supportable_widening_operation where we have access to more (but not enough) information. I have made the test conservative enough I hope. For the testcase what was broken is that it uses a SLP reduction where lane-swizzling isn't valid. PR tree-optimization/123002 * tree-vectorizer.h (supportable_widening_operation): Remove vinfo and stmt_info parameters, add flag to indicate whether the context would allow OP_{EVEN,ODD}. * tree-vect-patterns.cc (vect_recog_abd_pattern): Adjust and pass false. (vect_recog_widen_op_pattern): Likewise. (vect_recog_widen_abd_pattern): Likewise. * tree-vect-stmts.cc (vectorizable_conversion): Move even/odd validity check here, from supportable_widening_operation. Adjust it to be conservative. (supportable_widening_operation): Get flag whether even/odd is OK to use and remove then unused parameters and code. * gcc.dg/vect/vect-pr123002.c: New testcase. Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/4 ------------------------------------------------------------------------ On 2025-12-05T11:34:25+00:00 Rguenth wrote: Oh, and the issue was introduced by r0-117751-g6ae6116f1985d4 which didn't even add a testcase showing that we want the even/odd widening multiplication on reductions :/ Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/5 ------------------------------------------------------------------------ On 2025-12-05T11:35:10+00:00 Rguenth wrote: Fixed on trunk sofar. I have verified the fix also works on the branch, will backport after a few days of burn-in. Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/6 ------------------------------------------------------------------------ On 2025-12-05T12:16:33+00:00 Sjames-j wrote: (In reply to Richard Biener from comment #3) > Note I cannot reproduce the issue on trunk where we no longer recognize a > widen_mult pattern, but the principle issue is still there IMO. I wonder > what fixed it on trunk. > I started bisecting and then realised it was obvious (and confirmed to be sure): r16-5887-g27d9cefeebc255. i.e. foo gets compiled down to just: 0000000000000510 <foo>: } 510: 31 c0 xor %eax,%eax 512: c3 ret foo is noipa'd but that's not enough here. Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/7 ------------------------------------------------------------------------ On 2025-12-05T12:17:24+00:00 Sjames-j wrote: so, on trunk (not rebuilt with your commit), e.g. --param vrp-cstload- limit=0 hits it again. Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/8 ------------------------------------------------------------------------ On 2025-12-05T12:23:14+00:00 Rguenth wrote: Or simply make the array non-constant, non-static I guess. Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/9 ------------------------------------------------------------------------ On 2025-12-05T12:27:11+00:00 Cvs-commit wrote: The master branch has been updated by Richard Biener <[email protected]>: https://gcc.gnu.org/g:973a32e1c6e1f470969ebf16375d6c91131fbdb8 commit r16-5910-g973a32e1c6e1f470969ebf16375d6c91131fbdb8 Author: Richard Biener <[email protected]> Date: Fri Dec 5 13:25:02 2025 +0100 Make gcc.dg/vect/vect-pr123002.c trigger on unfixed trunk The following avoids VRP to access the constant initializer. PR tree-optimization/123002 * gcc.dg/vect/vect-pr123002.c: Make global data non-const and non-static. Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/10 ------------------------------------------------------------------------ On 2026-04-22T12:56:15+00:00 Cvs-commit wrote: The releases/gcc-15 branch has been updated by Richard Biener <[email protected]>: https://gcc.gnu.org/g:d7d71194bf4ff209d0601ee28be35970c3667f15 commit r15-11104-gd7d71194bf4ff209d0601ee28be35970c3667f15 Author: Richard Biener <[email protected]> Date: Thu Aug 21 13:46:06 2025 +0200 Move even/odd validity check from supportable_widening_operation to caller The following moves the incomplete validity check to use WIDEN_MULT_{EVEN,ODD} to the caller of supportable_widening_operation where we have access to more (but not enough) information. I have made the test conservative enough I hope. For the testcase what was broken is that it uses a SLP reduction where lane-swizzling isn't valid. PR tree-optimization/123002 * tree-vectorizer.h (supportable_widening_operation): Remove vinfo and stmt_info parameters, add flag to indicate whether the context would allow OP_{EVEN,ODD}. * tree-vect-patterns.cc (vect_recog_abd_pattern): Adjust and pass false. (vect_recog_widen_op_pattern): Likewise. (vect_recog_widen_abd_pattern): Likewise. * tree-vect-stmts.cc (vectorizable_conversion): Move even/odd validity check here, from supportable_widening_operation. Adjust it to be conservative. (supportable_widening_operation): Get flag whether even/odd is OK to use and remove then unused parameters and code. * gcc.dg/vect/vect-pr123002.c: New testcase. (cherry picked from commit 1da0e5c1405e87e9f2a11ed358b40dff21085657) Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/11 ------------------------------------------------------------------------ On 2026-04-22T12:56:25+00:00 Cvs-commit wrote: The releases/gcc-15 branch has been updated by Richard Biener <[email protected]>: https://gcc.gnu.org/g:41c778b954a9a584a42dca5bc1794b70cfc5bbad commit r15-11105-g41c778b954a9a584a42dca5bc1794b70cfc5bbad Author: Richard Biener <[email protected]> Date: Fri Dec 5 13:25:02 2025 +0100 Make gcc.dg/vect/vect-pr123002.c trigger on unfixed trunk The following avoids VRP to access the constant initializer. PR tree-optimization/123002 * gcc.dg/vect/vect-pr123002.c: Make global data non-const and non-static. (cherry picked from commit 973a32e1c6e1f470969ebf16375d6c91131fbdb8) Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/12 ------------------------------------------------------------------------ On 2026-04-22T12:56:57+00:00 Rguenth wrote: Fixed. Reply at: https://bugs.launchpad.net/ubuntu/+source/gcc-15/+bug/2163070/comments/13 ** Changed in: gcc Status: Unknown => Fix Released ** Changed in: gcc Importance: Unknown => Medium -- You received this bug notification because you are a member of Ubuntu Bugs, which is subscribed to Ubuntu. https://bugs.launchpad.net/bugs/2163070 Title: Miscompile in GCC 15.2.0 (x86) To manage notifications about this bug go to: https://bugs.launchpad.net/gcc/+bug/2163070/+subscriptions -- ubuntu-bugs mailing list [email protected] https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs
