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

Reply via email to