https://gcc.gnu.org/g:2149eda29e2628d31faf44da060139a856c47b3f

commit r16-7277-g2149eda29e2628d31faf44da060139a856c47b3f
Author: Jakub Jelinek <[email protected]>
Date:   Wed Feb 4 11:25:01 2026 +0100

    bitint: Don't try to extend PHI in the min_prec == prec case [PR122689]
    
    The following testcase is miscompiled on aarch64-linux, the problem is that
    the PHI argument is lowered to
      VIEW_CONVERT_EXPR<unsigned long[196]>(y) = VIEW_CONVERT_EXPR<unsigned 
long[196]>(*.LC0);
      MEM <unsigned long[1]> [(unsigned _BitInt(12419) *)&y + 1568B] = {};
    on the edge, where for aarch64 unsigned _BitInt(12419) the size of the type
    is already 1568 bytes (aka 196 DImode limbs, 98 TImode ABI limbs), so the
    fir stmt copies everything and the second stmt clobbers random unrelated 
memory
    after it.
    
    Usually when min_prec == prec (otherwise we guarantee that min_prec is 
either 0,
    or a single limb (which doesn't have padding bits) or something without any
    padding bits (multiple of abi_limb_prec)) we take the
                      if (c)
                        {
                          if (VAR_P (v1) && min_prec == prec)
                            {
                              tree v2 = build1 (VIEW_CONVERT_EXPR,
                                                TREE_TYPE (v1), c);
                              g = gimple_build_assign (v1, v2);
                              gsi_insert_on_edge (e, g);
                              edge_insertions = true;
                              break;
                            }
    path and need nothing else, but in this case v1 is a PARM_DECL, so we need 
to
    take the code path with VCE on the lhs side as well.  But after the 
assignment
    we fall through into the handling of the extension, but for min_prec == prec
    that isn't needed and is actually harmful, we've already copied everything
    and the code later on assumes there are no padding bits and uses just
    TYPE_SIZE_UNIT.
    
    So, this patch just avoids the rest after we've copied all the bits for
    min_prec == prec.
    
    2026-02-04  Jakub Jelinek  <[email protected]>
    
            PR middle-end/122689
            * gimple-lower-bitint.cc (gimple_lower_bitint): For the PHI handling
            if min_prec == prec, break after emitting assignment from c.
    
            * gcc.dg/bitint-127.c: New test.

Diff:
---
 gcc/gimple-lower-bitint.cc        |  5 +++++
 gcc/testsuite/gcc.dg/bitint-127.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc
index 9d027c6a6a1a..b33a5b43dc86 100644
--- a/gcc/gimple-lower-bitint.cc
+++ b/gcc/gimple-lower-bitint.cc
@@ -7804,6 +7804,11 @@ gimple_lower_bitint (void)
                                                           vtype, c));
                        }
                      gsi_insert_on_edge (e, g);
+                     if (min_prec == prec)
+                       {
+                         edge_insertions = true;
+                         break;
+                       }
                    }
                  if (ext == 0)
                    {
diff --git a/gcc/testsuite/gcc.dg/bitint-127.c 
b/gcc/testsuite/gcc.dg/bitint-127.c
new file mode 100644
index 000000000000..b0f69bdc2d8c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-127.c
@@ -0,0 +1,28 @@
+/* PR middle-end/122689 */
+/* { dg-do run { target { bitint } } } */
+/* { dg-options "-O" } */
+
+#if __BITINT_MAXWIDTH__ >= 12419
+const _BitInt(12419) n = 
0xfe65f7aff85d0095103ee4d1c3b9ca50eed67abd838cdc5b53c776c8dd19b0be6eeb21aa421395fc16cf018858c9c2a03b6a013546f938e5af4c286c0456a2f5e09ad52921a4f98ce6cfbdc1beee7b860507f9fbed6640a9ce12aab6ca7e54afa6113fefe2e91a2822e9f32e04c038bb2993f25afd9489117ba43f6d1389a527c0823fd096848c9ae857fac18d08ec59b8dc73df77213ec9d0b0fba9cb38213ac625a864ffe0d4c994be6692af55bdef84699596becccc0b48d6b306bed100e78defd85477a5d7eb57af5b84e70de61141f0e725b23bd26ee239fa91a8816a3b37480f8782564bb91dfc23277303553d302a0b67dbc914fab7f54ca91548bfe66eb9daa9e524509d96e94c502b7df14acf44ef09e9c4f50ad436a504f33e51210f5c4693fdbeb3a486ce7ec50ce18939936ca91e05afc11145461832f007622d19959c4dd5f508d8d60dfc9c79b7b504e5becbc0e09cef83b9a28aadb50bd3b3d071a688455831a697d7ebaa9f64fc106e2f4eb9f8edad3b5937e157d6a3d11f6c3f8a83cc2b737b8bbde90960eec3c1d629a2af864b25c9db8edee90d99e42b9948b247cd04052465da8a647ff3a4cfaa9c5cca2b4ead7e60c6b31cfcd6a5f62fe14d3ea6a914adbd7015ea3240faf3f453e5e135067bf71d4fc625a4318afeb0ba625a42
 
e0294ffadbf356f149775ea67b9652d45cba63210becd0b8bca390c68c2be31842354eeff63e1b49b989d4de4ee11a12c812077e0062229749fd2fb0b129a8fe319a049d45baadd7e72dabe4a5276440468e78dca8ec8a129f6ce2da1a212fcc6610f1dd9eab2258492794fa6209a4a6e889e7a907f951eafe983bdda8dedf1d56af16909ce4281904c3035a8b2d3f4f3b2395f6f153da639a0265154f7fc51a3b4bada7aa6255a40544288348c4049e8d8507eada1ea5526aadfe23385bd72b1e4c0214ee962132c692ee13868e1ea4e5c53a5ff428ecda98e82c60fa01e8ced36edaee0740e19490f0c2c9912198041d0c6af7d327d1df022f6a21f2ce65395f8b5eeff47b475056e6d6debcdee65a220bc705ac235d1e10f25a47642b09bbcbe4509ffc1e621c61f2df88d2a9575692bf1fa8456060347e05fd3b41e369caecaa979c6c3d9fadac24385e871e73c907bf3d0a8d452f85c963e5230791e68e2d8264b854745f9f227b43c8f18e6f1d4060f96a227030880c6f8e2bccda5911bedceb5d2c65640fab851345932e35db4795a41d72ea0d0b4abcdfe0bfe237bf0ae087d517c03bed58bd115cf93c28f3c04a04879e449950043928e439a08e3e6708f1b5a7b99441270793f85f77299edbe8fbc3e4956f6cce8d6babf19939900c68b0dfb5e607ecd59ba7747868ad3495e72
 
7fac4daff7d69d9b0f72bc7d73c769bbf5af2135a4832ca205a936f322307ef510992987b8f712c388e72122b0bb633dcb12325d1121657649b7813a0f3952b37156918b65eccce34d0c1219cef72e9326f12920e983a46edfd30b572593e1657194e0c41d1e1830c55ac5dfc3e63dc69d9006eba308f0c85e66da89ddf81a65e6027b3144ea9e000e5d4e6f6354c405e0a47c7be23fd94bb38e7dd2f89e886212d9d6d76dafc173268716d3dc9a4fcca6f623a1df279418b147ea79b08c9eca5c723a949047690d84b6ddaebd2b69100f74d9e4323d15bb410c7dc77a74e646a9949a44a9ab2b697eedcbf060655ded990fdf157cf4ec3d7d1b6cdb50ecc27a3558660df90c993a32fb16771e9ba5f9cddb51edaa1b4592172a0daca839e09f55cf9ea1bb2659eddf52ec2ba75ac27b5c9e82524410f3a0886921235b22ee74319719d0c5b61f0e8dbd7de6533ba8a2e3d7e19ac6bf4036515ffc88ef3b02b85d8abad0e413bd56b1b4f404fa59b73cdc02cab7bf572565767b80ff87bd2bc2772349d122951b84248d406c4e1351d869c12430dc350b51896a0968867396293c7d267514e3fc80dafe5d578b6fbbbe015720942e46be881dd6ece5f131269e326b3be18292846d96cf9dc782d9b5ae8e44549ac9d3ce89347338c2949225bbdddfcf8faeb5cdbb7582fb66eec0cdfb3b21f
 
fe61794a07a066080d1af3d90121a09c62583512a75df831bfbd4b039568197f683d0043d350b688dbe947c92b5cedcd7a64803791bd1a2dc6e0df0b9fb6a294d728e026dc9wb;
+
+unsigned g;
+
+_BitInt(6)
+foo (unsigned a, unsigned b, unsigned c, unsigned _BitInt(256) z,
+     unsigned _BitInt(12419) y)
+{
+  y /= b;
+  unsigned _BitInt(12419) ay = a * y;
+  g -= (n >= ay ? n : ay) % c;
+  return z;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 12419
+  if (foo (0, 5, 5, 2, 0) != 2)
+    __builtin_abort ();
+#endif
+}

Reply via email to