https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124041
--- Comment #15 from Robin Dapp <rdapp at gcc dot gnu.org> ---
(In reply to Robin Dapp from comment #14)
> Just for the record, this is what I tried (and what causes miscompiles):
>
> diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
> index 8c8c9d69a96..a7ef1402267 100644
> --- a/gcc/lra-constraints.cc
> +++ b/gcc/lra-constraints.cc
> @@ -4369,11 +4369,19 @@ curr_insn_transform (bool check_only_p)
> continue;
>
> old = op = *curr_id->operand_loc[i];
> + machine_mode outer_mode = GET_MODE (old);
> + bool subreg_p = false;
> if (GET_CODE (old) == SUBREG)
> - old = SUBREG_REG (old);
> + {
> + old = SUBREG_REG (old);
> + subreg_p = true;
> + }
> subst = get_equiv_with_elimination (old, curr_insn);
> original_subreg_reg_mode[i] = VOIDmode;
> equiv_substition_p[i] = false;
> + if (subreg_p && HARD_REGISTER_P (subst)
> + && !targetm.hard_regno_mode_ok (REGNO (subst), outer_mode))
> + continue;
> if (subst != old)
> {
> equiv_substition_p[i] = true;
What does work (passing bootstrap and regtest) is
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 8c8c9d69a96..a7ef1402267 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -4369,11 +4369,19 @@ curr_insn_transform (bool check_only_p)
continue;
old = op = *curr_id->operand_loc[i];
+ machine_mode outer_mode = GET_MODE (old);
+ bool subreg_p = false;
if (GET_CODE (old) == SUBREG)
- old = SUBREG_REG (old);
+ {
+ old = SUBREG_REG (old);
+ subreg_p = true;
+ }
subst = get_equiv_with_elimination (old, curr_insn);
original_subreg_reg_mode[i] = VOIDmode;
equiv_substition_p[i] = false;
+ if (subreg_p && REG_P (subst) && HARD_REGISTER_P (subst)
+ && !targetm.hard_regno_mode_ok (REGNO (subst), outer_mode))
+ continue;
if (subst != old)
{
equiv_substition_p[i] = true;
The only difference is REG_P before the HARD_REGISTER_P check.