https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118862
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- One would need to rewrite gfc_conv_powi to work on wide_ints. Another option is just punt at trying to optimize it, if (lhs_prec > HOST_BITS_PER_WIDE_INT) return 0; Though, maybe in such case the n & mask could be just n, because the mask in infinite precision would have all the low 64-bits set and perhaps some more. So perhaps --- gcc/trans-expr.cc.jj 2025-02-08 08:49:56.573946067 +0100 +++ gcc/trans-expr.cc 2025-02-13 22:57:05.373836717 +0100 @@ -3604,7 +3604,7 @@ gfc_conv_cst_int_power (gfc_se * se, tre if (bit_size(rhs) < bit_size(lhs)) ! Checked here. return lhs ** rhs; - mask = (1 < bit_size(a) - 1) / 2; + mask = 1 << (bit_size(a) - 1) / 2; return lhs ** (n & rhs); } if (rhs > bit_size(lhs)) ! Checked here. @@ -3624,13 +3624,13 @@ gfc_conv_cst_uint_power (gfc_se * se, tr tree vartmp_odd[POWI_TABLE_SIZE], vartmp_even[POWI_TABLE_SIZE]; /* Anything ** 0 is one. */ - if (tree_int_cst_sgn (rhs) == 0) + if (integer_zerop (rhs) == 0) { se->expr = build_int_cst (type, 1); return 1; } - if (!wi::fits_shwi_p (wrhs)) + if (!wi::fits_uhwi_p (wrhs)) return 0; n = wrhs.to_uhwi (); @@ -3642,19 +3642,19 @@ gfc_conv_cst_uint_power (gfc_se * se, tr tmp, build_int_cst (type, 1)); lhs_prec = TYPE_PRECISION (type); - rhs_prec = TYPE_PRECISION (TREE_TYPE(rhs)); + rhs_prec = TYPE_PRECISION (TREE_TYPE (rhs)); - if (rhs_prec >= lhs_prec) + if (rhs_prec >= lhs_prec && lhs_prec < HOST_BITS_PER_WIDE_INT) { - unsigned HOST_WIDE_INT mask; - mask = (((unsigned HOST_WIDE_INT) 1) << (lhs_prec - 1)) - 1; + unsigned HOST_WIDE_INT mask + = (HOST_WIDE_INT_1U << (lhs_prec - 1)) - 1; n_odd = n & mask; } else n_odd = n; memset (vartmp_odd, 0, sizeof (vartmp_odd)); - vartmp_odd[0] = build_int_cst(type, 1); + vartmp_odd[0] = build_int_cst (type, 1); vartmp_odd[1] = lhs; odd_branch = gfc_conv_powi (se, n_odd, vartmp_odd); even_branch = NULL_TREE; @@ -3666,7 +3666,7 @@ gfc_conv_cst_uint_power (gfc_se * se, tr if (n_odd != n) { memset (vartmp_even, 0, sizeof (vartmp_even)); - vartmp_even[0] = build_int_cst(type, 1); + vartmp_even[0] = build_int_cst (type, 1); vartmp_even[1] = lhs; even_branch = gfc_conv_powi (se, n, vartmp_even); } Completely untested.