bitintlower: Padding bit fixes, part 6 [PR123635]

I've missed torture/bitint-{93,94}.c FAILs on s390x-linux (i.e. big endian).
For __builtin_mul_overflow, the code to extend the partial most significant
limb is done before memmoving it down, so that limb actually isn't on big
endian at offset 0 but is nelts - obj_nelts.  The following patch computes
obj_nelts first, uses it on big-endian and so that the offset checking
asserts don't trigger, on big-endian also uses NULL_TREE first argument to
limb_access.

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

	PR middle-end/123635
	* gimple-lower-bitint.cc (bitint_large_huge::finish_arith_overflow):
	Move obj_nelts/atype computation before bitint_extended handling.  For
	bitint_big_endian in the bitint_extended handling use size_zero_node
	only for limb_access_type calls, otherwise use
	size_int (nelts - obj_nelts) and pass NULL_TREE as first argument to
	limb_access calls.

Reviewed-by: Richard Biener <rguenth@suse.de>
This commit is contained in:
Jakub Jelinek
2026-04-29 11:12:47 +02:00
committed by Jakub Jelinek
parent 685f665a6c
commit 32160061ca

View File

@@ -4478,6 +4478,13 @@ bitint_large_huge::finish_arith_overflow (tree var, tree obj, tree type,
{
unsigned HOST_WIDE_INT obj_nelts = 0;
tree atype = NULL_TREE;
if (obj)
{
obj_nelts = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (obj))) / limb_prec;
if (orig_obj == NULL_TREE)
obj_nelts >>= 1;
atype = build_array_type_nelts (m_limb_type, obj_nelts);
}
if (bitint_extended && (var || obj))
{
unsigned prec = TYPE_PRECISION (type);
@@ -4492,9 +4499,13 @@ bitint_large_huge::finish_arith_overflow (tree var, tree obj, tree type,
if ((code == MULT_EXPR && (prec % limb_prec) != 0)
|| (ext_ms_limb && !TYPE_UNSIGNED (type)))
{
tree plm1idx = size_int (bitint_big_endian ? 0 : prec_limbs - 1);
tree plm1type = limb_access_type (type, plm1idx);
tree l = limb_access (type, var ? var : obj, plm1idx, true);
tree plm1idx = size_int (bitint_big_endian
? nelts - obj_nelts : prec_limbs - 1);
tree plm1type
= limb_access_type (type, bitint_big_endian
? size_zero_node : plm1idx);
tree l = limb_access (bitint_big_endian ? NULL_TREE : type,
var ? var : obj, plm1idx, true);
tree rhs = make_ssa_name (TREE_TYPE (l));
g = gimple_build_assign (rhs, l);
insert_before (g);
@@ -4505,7 +4516,8 @@ bitint_large_huge::finish_arith_overflow (tree var, tree obj, tree type,
if (!useless_type_conversion_p (TREE_TYPE (l),
TREE_TYPE (rhs)))
rhs = add_cast (TREE_TYPE (l), rhs);
l = limb_access (type, var ? var : obj, plm1idx, true);
l = limb_access (bitint_big_endian ? NULL_TREE : type,
var ? var : obj, plm1idx, true);
g = gimple_build_assign (l, rhs);
insert_before (g);
}
@@ -4537,13 +4549,6 @@ bitint_large_huge::finish_arith_overflow (tree var, tree obj, tree type,
insert_before (g);
}
}
if (obj)
{
obj_nelts = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (obj))) / limb_prec;
if (orig_obj == NULL_TREE)
obj_nelts >>= 1;
atype = build_array_type_nelts (m_limb_type, obj_nelts);
}
if (var && obj)
{
tree v1, v2;