https://gcc.gnu.org/g:8cc16190a694af2fb4c6d10456b6bea5adaa0ce8
commit 8cc16190a694af2fb4c6d10456b6bea5adaa0ce8 Author: Alexandre Oliva <ol...@adacore.com> Date: Tue Dec 10 06:49:32 2024 -0300 ifcombine field-merge: saturate align at inner object size A bootstrap on aarch64-linux-gnu revealed that sometimes (for example, when building shorten_branches in final.cc) we will find such things as MEM <unsigned int>, where unsigned int happen to be a variant of the original unsigned int type, given 64-bit alignment. This unusual alignment circumstance caused get_best_mode to choose DImode instead of SImode, and that failed gimple verification because there aren't that many bits in the unsigned int object. Arrange for alignment to saturate at the inner object size to avoid tripping this error. for gcc/ChangeLog * gimple-fold.cc (fold_truth_andor_for_ifcombine): Saturate align at inner object size. Diff: --- gcc/gimple-fold.cc | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index a31fc283d51b..8f45428dc5d9 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -8204,24 +8204,26 @@ fold_truth_andor_for_ifcombine (enum tree_code code, tree truth_type, to be relative to a field of that size. */ first_bit = MIN (ll_bitpos, rl_bitpos); end_bit = MAX (ll_bitpos + ll_bitsize, rl_bitpos + rl_bitsize); - if (get_best_mode (end_bit - first_bit, first_bit, 0, 0, - TYPE_ALIGN (TREE_TYPE (ll_inner)), BITS_PER_WORD, - volatilep, &lnmode)) + HOST_WIDE_INT ll_align = TYPE_ALIGN (TREE_TYPE (ll_inner)); + poly_uint64 ll_end_region = 0; + if (uniform_integer_cst_p (TYPE_SIZE (TREE_TYPE (ll_inner)))) + ll_end_region = tree_to_poly_uint64 (TYPE_SIZE (TREE_TYPE (ll_inner))); + if (get_best_mode (end_bit - first_bit, first_bit, 0, ll_end_region, + ll_align, BITS_PER_WORD, volatilep, &lnmode)) l_split_load = false; else { /* Consider the possibility of recombining loads if any of the fields straddles across an alignment boundary, so that either part can be loaded along with the other field. */ - HOST_WIDE_INT align = TYPE_ALIGN (TREE_TYPE (ll_inner)); HOST_WIDE_INT boundary = compute_split_boundary_from_align - (align, ll_bitpos, ll_bitsize, rl_bitpos, rl_bitsize); + (ll_align, ll_bitpos, ll_bitsize, rl_bitpos, rl_bitsize); if (boundary < 0 - || !get_best_mode (boundary - first_bit, first_bit, 0, 0, - align, BITS_PER_WORD, volatilep, &lnmode) - || !get_best_mode (end_bit - boundary, boundary, 0, 0, - align, BITS_PER_WORD, volatilep, &lnmode2)) + || !get_best_mode (boundary - first_bit, first_bit, 0, ll_end_region, + ll_align, BITS_PER_WORD, volatilep, &lnmode) + || !get_best_mode (end_bit - boundary, boundary, 0, ll_end_region, + ll_align, BITS_PER_WORD, volatilep, &lnmode2)) return 0; /* If we can't have a single load, but can with two, figure out whether @@ -8368,16 +8370,18 @@ fold_truth_andor_for_ifcombine (enum tree_code code, tree truth_type, and then we use two separate compares. */ first_bit = MIN (lr_bitpos, rr_bitpos); end_bit = MAX (lr_bitpos + lr_bitsize, rr_bitpos + rr_bitsize); - if (!get_best_mode (end_bit - first_bit, first_bit, 0, 0, - TYPE_ALIGN (TREE_TYPE (lr_inner)), BITS_PER_WORD, - volatilep, &rnmode)) + HOST_WIDE_INT lr_align = TYPE_ALIGN (TREE_TYPE (lr_inner)); + poly_uint64 lr_end_region = 0; + if (uniform_integer_cst_p (TYPE_SIZE (TREE_TYPE (lr_inner)))) + lr_end_region = tree_to_poly_uint64 (TYPE_SIZE (TREE_TYPE (lr_inner))); + if (!get_best_mode (end_bit - first_bit, first_bit, 0, lr_end_region, + lr_align, BITS_PER_WORD, volatilep, &rnmode)) { /* Consider the possibility of recombining loads if any of the fields straddles across an alignment boundary, so that either part can be loaded along with the other field. */ - HOST_WIDE_INT align = TYPE_ALIGN (TREE_TYPE (lr_inner)); HOST_WIDE_INT boundary = compute_split_boundary_from_align - (align, lr_bitpos, lr_bitsize, rr_bitpos, rr_bitsize); + (lr_align, lr_bitpos, lr_bitsize, rr_bitpos, rr_bitsize); if (boundary < 0 /* If we're to split both, make sure the split point is @@ -8385,10 +8389,11 @@ fold_truth_andor_for_ifcombine (enum tree_code code, tree truth_type, || (l_split_load && (boundary - lr_bitpos != (lnbitpos + GET_MODE_BITSIZE (lnmode)) - ll_bitpos)) - || !get_best_mode (boundary - first_bit, first_bit, 0, 0, - align, BITS_PER_WORD, volatilep, &rnmode) - || !get_best_mode (end_bit - boundary, boundary, 0, 0, - align, BITS_PER_WORD, volatilep, &rnmode2)) + || !get_best_mode (boundary - first_bit, first_bit, + 0, lr_end_region, + lr_align, BITS_PER_WORD, volatilep, &rnmode) + || !get_best_mode (end_bit - boundary, boundary, 0, lr_end_region, + lr_align, BITS_PER_WORD, volatilep, &rnmode2)) return 0; r_split_load = true;