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.

Reply via email to