Sometimes, `store_bit_field` copies the destination register into a new one,
which leads to the old register being used in the instructions that follow
the ones generated by `store_bit_field`, while the bit field insertion is
performed on the new register.

This patch copies back the new destination register into the old one when
needed.

gcc/ChangeLog:

        * avoid-store-forwarding.cc (generate_bit_insert_sequence):
        Copy back the new destination register into the old one when needed.

Signed-off-by: Konstantinos Eleftheriou <[email protected]>
---

Changes in v3:
- Add `avoid_store_forwarding_reorder_cost_p` function
- Add `asf-default-cost-value` parameter
- Use `avoid_store_forwarding_reorder_cost_p` for each store in ASF.
- Update x86_64 testcases.
- Update assembly patterns in `bitfield-bitint-abi-align16.c` and
`bitfield-bitint-abi-align8.c`.
- Fix bug where the result of `store_bit_field` is not used in the
following instructions.

Changes in v2:
- Update assembly patterns in `bitfield-bitint-abi-align16.c` and
`bitfield-bitint-abi-align8.c`.

Changes in v1:
- Enable asf by default at O2 or higher.

 gcc/avoid-store-forwarding.cc | 39 +++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/gcc/avoid-store-forwarding.cc b/gcc/avoid-store-forwarding.cc
index c940b4ad98de..9a00c3266c7d 100644
--- a/gcc/avoid-store-forwarding.cc
+++ b/gcc/avoid-store-forwarding.cc
@@ -40,6 +40,7 @@
 #include "memmodel.h"
 #include "emit-rtl.h"
 #include "vec.h"
+#include "rtl-iter.h"
 
 /* This pass tries to detect and avoid cases of store forwarding.
    On many processors there is a large penalty when smaller stores are
@@ -124,6 +125,44 @@ generate_bit_insert_sequence (store_fwd_info *store_info, 
rtx dest)
                   false, false);
 
   rtx_insn *insns = get_insns ();
+
+  /* Check if dest is used as a destination in any instruction of those
+  that store_bit_field generated.  */
+  bool dest_found = false;
+  for (const rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
+    {
+      subrtx_iterator::array_type array;
+      FOR_EACH_SUBRTX (iter, array, insn, ALL)
+       {
+         const_rtx subexpr = *iter;
+
+         if (!subexpr || !single_set ((const rtx_insn*) subexpr))
+           continue;
+
+         dest_found = reg_mentioned_p (dest, XEXP (PATTERN (subexpr), 0));
+
+         if (dest_found)
+           break;
+       }
+
+      if (dest_found)
+       break;
+    }
+
+  /* If dest is not updated in the bitfield insertion instructions, generate
+     a mov instruction in order to copy the new destination register back into
+     dest.  */
+  if (!dest_found)
+    {
+      rtx new_dest = XEXP (PATTERN (insns), 0);
+
+      if (GET_MODE (dest) == GET_MODE (new_dest))
+       {
+         emit_move_insn (dest, new_dest);
+         insns = get_insns ();
+       }
+    }
+
   unshare_all_rtl_in_chain (insns);
   end_sequence ();
 
-- 
2.50.1

Reply via email to