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