https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121251
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Well, because conversion between say 32-bit INTEGER_TYPE and 32-bit
ENUMERAL_TYPE or 32-bit BITINT_TYPE is useless, you can get there any of those.
There is no problem to have BITINT_TYPE in the second operand of
shifts/rotates, the problem is only if they are large/huge BITINT_TYPEs (so
larger than normally supported types).
In C/C++ FE we do:
/* We used to convert the right operand of a shift-expression
to an integer_type_node in the FEs. But it is unnecessary
and not desirable for diagnostics and sanitizers. We keep
this here to not pessimize the code, but we convert to an
unsigned type, because negative shift counts are undefined
anyway.
We should get rid of this conversion when we have a proper
type demotion/promotion pass. */
tree *op1_p = &TREE_OPERAND (*expr_p, 1);
if (!error_operand_p (*op1_p)
&& !VECTOR_TYPE_P (TREE_TYPE (*op1_p))
&& !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
unsigned_type_node)
&& !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
integer_type_node))
/* Make sure to unshare the result, tree sharing is invalid
during gimplification. */
*op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
and I guess that is what probably Rust should do too (or we should do during
gimplification)?
So even
__int128
foo (__int128 x, __int128 y)
{
return x << y;
}
is actually return x << (unsigned) y; after gimplification.