The call to `gen_lowpart` in `store_bit_field_1` might copy the destination
register into a new one, which may lead to wrong code generation, as the bit
insertions update the new register instead of updating `str_rtx`.
This patch copies back the new destination register into `str_rtx` when needed.
gcc/ChangeLog:
* expmed.cc (store_bit_field_1): Copy back the new destination
register into `str_rtx` when needed.
Signed-off-by: Konstantinos Eleftheriou <[email protected]>
---
(no changes since v1)
gcc/expmed.cc | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index be427dca5d9a..2f4a88520d24 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -888,9 +888,25 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize,
poly_uint64 bitnum,
op0 = gen_lowpart (op0_mode.require (), op0);
}
- return store_integral_bit_field (op0, op0_mode, ibitsize, ibitnum,
- bitregion_start, bitregion_end,
- fieldmode, value, reverse, fallback_p);
+ bool result = store_integral_bit_field (op0, op0_mode, ibitsize, ibitnum,
+ bitregion_start, bitregion_end,
+ fieldmode, value, reverse,
+ fallback_p);
+
+ rtx op0_reg = op0;
+ rtx str_rtx_reg = str_rtx;
+ while (GET_CODE (op0_reg) == SUBREG)
+ op0_reg = SUBREG_REG (op0_reg);
+ while (GET_CODE (str_rtx_reg) == SUBREG)
+ str_rtx_reg = SUBREG_REG (str_rtx_reg);
+
+ /* If a new destination register has been generated, copy the value back
+ into str_rtx. */
+ if (GET_CODE (op0_reg) == REG && GET_CODE (str_rtx_reg) == REG
+ && (REGNO (op0_reg) != REGNO (str_rtx_reg)))
+ convert_move (str_rtx, op0, 0);
+
+ return result;
}
/* Subroutine of store_bit_field_1, with the same arguments, except
--
2.51.1