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

Reply via email to