]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
bitintlower: Padding bit fixes, part 3 [PR123635]
authorJakub Jelinek <jakub@redhat.com>
Mon, 20 Apr 2026 07:11:24 +0000 (09:11 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 20 Apr 2026 07:11:24 +0000 (09:11 +0200)
I've debugged the rest of the failures on riscv64-linux (in particular
torture/bitint-{87,89}.c FAILs at -O2).
This is on top of https://gcc.gnu.org/pipermail/gcc-patches/2026-April/713242.html
patch.
One problem was that the lower_shift_stmt RSHIFT_EXPR change to iterate
until p2 rather than p (where p2 is p + 1 if bitint_ext_full and there is
full limb of padding bits), the loop is emitted with a condition before the
header and another condition before the latch edge and I've mistakenly fixed
just the latter and not the former.
ANother problem was that in all the 3 RSHIFT_EXPRs added meant to set
a full limb to 0 or all ones based on most significant bit I've mistakenly used
unsigned type rather than signed, so it was set to 0 or 1 instead (this
was twice in lower_shift_stmt, for the LSHIFT_EXPR case in both cases and
once in lower_float_conv_stmt).
And finally, because unsigned MULT_EXPR doesn't have overflow undefined, we
actually don't need to just clear the full padding bit limb (if any) but
even the padding bits in the partial limb (if any; and this actually doesn't
affect just arm and riscv, but also affects s390x and loongarch).

2026-04-20  Jakub Jelinek  <jakub@redhat.com>

PR middle-end/123635
* gimple-lower-bitint.cc (bitint_large_huge::lower_shift_stmt): In the
RSHIFT_EXPR case, use p2 in two LE_EXPR conditions rather than just
one.  In LSHIFT_EXPR case, use signed RSHIFT_EXPR instead of unsigned.
(bitint_large_huge::lower_muldiv_stmt): For unsigned MULT_EXPR with
bitint_extended if prec is not multiple of limb_prec, clear padding
bits after libgcc call.
(bitint_large_huge::lower_float_conv_stmt): Use signed RSHIFT_EXPR
instead of unsigned.

Reviewed-by: Jeffrey Law <jeffrey.law@oss.qualcomm.com>
gcc/gimple-lower-bitint.cc

index e211faf800195deb9fafb4cc6cc3e8b494ec531a..24645aac243b3835a9d0688e882b371751b54058 100644 (file)
@@ -3798,6 +3798,7 @@ bitint_large_huge::lower_shift_stmt (tree obj, gimple *stmt)
                               bitint_big_endian
                               ? size_int (-1) : size_one_node);
       insert_before (g);
+      tree p2 = p;
       if (bitint_big_endian)
        {
          tree new_idx = gimple_assign_lhs (g);
@@ -3807,8 +3808,13 @@ bitint_large_huge::lower_shift_stmt (tree obj, gimple *stmt)
        }
       else
        {
+         if (bitint_extended == bitint_ext_full
+             && abi_limb_prec > limb_prec)
+           p2 = build_int_cst (sizetype,
+                               CEIL (prec, abi_limb_prec)
+                               * abi_limb_prec / limb_prec - 1);
          idx = gimple_assign_lhs (g);
-         g = gimple_build_cond (LE_EXPR, idx, p, NULL_TREE, NULL_TREE);
+         g = gimple_build_cond (LE_EXPR, idx, p2, NULL_TREE, NULL_TREE);
        }
       if_then (g, profile_probability::likely (), edge_true, edge_false);
       idx = create_loop (idx, &idx_next);
@@ -3822,16 +3828,8 @@ bitint_large_huge::lower_shift_stmt (tree obj, gimple *stmt)
       if (bitint_big_endian)
        g = gimple_build_cond (NE_EXPR, idx, size_zero_node,
                               NULL_TREE, NULL_TREE);
-      else if (bitint_extended == bitint_ext_full
-              && abi_limb_prec > limb_prec)
-       {
-         tree p2 = build_int_cst (sizetype,
-                                  CEIL (prec, abi_limb_prec)
-                                  * abi_limb_prec / limb_prec - 1);
-         g = gimple_build_cond (LE_EXPR, idx_next, p2, NULL_TREE, NULL_TREE);
-       }
       else
-       g = gimple_build_cond (LE_EXPR, idx_next, p, NULL_TREE, NULL_TREE);
+       g = gimple_build_cond (LE_EXPR, idx_next, p2, NULL_TREE, NULL_TREE);
       insert_before (g);
     }
   else
@@ -4028,12 +4026,13 @@ bitint_large_huge::lower_shift_stmt (tree obj, gimple *stmt)
                v = build_zero_cst (m_limb_type);
              else
                {
-                 g = gimple_build_assign (make_ssa_name (m_limb_type),
+                 v = add_cast (signed_type_for (m_limb_type), v);
+                 g = gimple_build_assign (make_ssa_name (TREE_TYPE (v)),
                                           RSHIFT_EXPR, v,
                                           build_int_cst (unsigned_type_node,
                                                          limb_prec - 1));
-                 v = gimple_assign_lhs (g);
                  insert_before (g);
+                 v = add_cast (m_limb_type, gimple_assign_lhs (g));
                }
              l = limb_access (TREE_TYPE (lhs), obj, p2, true);
              g = gimple_build_assign (l, v);
@@ -4058,12 +4057,13 @@ bitint_large_huge::lower_shift_stmt (tree obj, gimple *stmt)
              v = make_ssa_name (m_limb_type);
              g = gimple_build_assign (v, l);
              insert_before (g);
-             g = gimple_build_assign (make_ssa_name (m_limb_type),
+             v = add_cast (signed_type_for (m_limb_type), v);
+             g = gimple_build_assign (make_ssa_name (TREE_TYPE (v)),
                                       RSHIFT_EXPR, v,
                                       build_int_cst (unsigned_type_node,
                                                      limb_prec - 1));
-             v = gimple_assign_lhs (g);
              insert_before (g);
+             v = add_cast (m_limb_type, gimple_assign_lhs (g));
            }
          tree l = limb_access (TREE_TYPE (lhs), obj, p2, true);
          g = gimple_build_assign (l, v);
@@ -4166,6 +4166,26 @@ bitint_large_huge::lower_muldiv_stmt (tree obj, gimple *stmt)
          add_eh_edge (e2->src, e1);
        }
     }
+  if (bitint_extended
+      && rhs_code == MULT_EXPR
+      && TYPE_UNSIGNED (type)
+      && (prec % limb_prec) != 0)
+    {
+      /* Unsigned multiplication wraps, but libgcc function will return the
+        bits beyond prec within the top limb as another limb of the full
+        multiplication.  So, clear the padding bits here.  */
+      tree idx = size_int (bitint_big_endian ? 0 : prec / limb_prec);
+      tree l = limb_access (type, obj, idx, true);
+      tree ctype = limb_access_type (type, idx);
+      tree v = make_ssa_name (m_limb_type);
+      g = gimple_build_assign (v, l);
+      insert_before (g);
+      v = add_cast (ctype, v);
+      l = limb_access (type, obj, idx, true);
+      v = add_cast (m_limb_type, v);
+      g = gimple_build_assign (l, v);
+      insert_before (g);
+    }
   if (zero_ms_limb)
     {
       unsigned int i = CEIL (prec, abi_limb_prec) * abi_limb_prec / limb_prec;
@@ -4242,12 +4262,14 @@ bitint_large_huge::lower_float_conv_stmt (tree obj, gimple *stmt)
                                                    size_int (i - 2),
                                                    true));
              insert_before (g);
-             g = gimple_build_assign (make_ssa_name (m_limb_type),
-                                      RSHIFT_EXPR, gimple_assign_lhs (g),
+             val = add_cast (signed_type_for (m_limb_type),
+                             gimple_assign_lhs (g));
+             g = gimple_build_assign (make_ssa_name (TREE_TYPE (val)),
+                                      RSHIFT_EXPR, val,
                                       build_int_cst (unsigned_type_node,
                                                      limb_prec - 1));
              insert_before (g);
-             val = gimple_assign_lhs (g);
+             val = add_cast (m_limb_type, gimple_assign_lhs (g));
            }
          else
            val = build_zero_cst (m_limb_type);