]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
asf: Fix offset check in base reg initialization for big-endian targets
authorKonstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
Tue, 3 Jun 2025 07:16:17 +0000 (09:16 +0200)
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>
Tue, 15 Jul 2025 14:16:12 +0000 (16:16 +0200)
During the base register initialization, in the case that we are
eliminating the load instruction, we are using `offset == 0` in order
to find the store instruction that has the same offset as the
load. This would not work on big-endian targets where byte 0 would be
the MS byte.

This patch updates the condition to take into account the target's
endianness.

We are, also, removing the adjustment of the starting position for the
bitfield insertion, when BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN. This is
supposed to be handled inside `store_bit_field` and it's not needed
anymore after the offset fix.

Bootstrapped/regtested on AArch64 LE, x86_64 and PowerPC LE.

gcc/ChangeLog:

* avoid-store-forwarding.cc (generate_bit_insert_sequence):
Remove adjustment of bitfield insertion's starting position
when BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN.
(process_store_forwarding): Update offset check in base reg
initialization to take into account the target's endianness.

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/avoid-store-forwarding-be.c: New test.

gcc/avoid-store-forwarding.cc
gcc/testsuite/gcc.target/aarch64/avoid-store-forwarding-be.c [new file with mode: 0644]

index 37e095316c93a003209a59a48db4fce92daec3f8..785efd22606f245fa404c27b501b93682a7f5a42 100644 (file)
@@ -119,17 +119,6 @@ generate_bit_insert_sequence (store_fwd_info *store_info, rtx dest)
   unsigned HOST_WIDE_INT bitsize = store_size * BITS_PER_UNIT;
   unsigned HOST_WIDE_INT start = store_info->offset * BITS_PER_UNIT;
 
-  /* Adjust START for machines with BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN.
-     Given that the bytes will be reversed in this case, we need to
-     calculate the starting position from the end of the destination
-     register.  */
-  if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
-    {
-      unsigned HOST_WIDE_INT load_mode_bitsize
-       = (GET_MODE_BITSIZE (GET_MODE (dest))).to_constant ();
-      start = load_mode_bitsize - bitsize - start;
-    }
-
   rtx mov_reg = store_info->mov_reg;
   store_bit_field (dest, bitsize, start, 0, 0, GET_MODE (mov_reg), mov_reg,
                   false, false);
@@ -248,11 +237,14 @@ process_store_forwarding (vec<store_fwd_info> &stores, rtx_insn *load_insn,
     {
       it->mov_reg = gen_reg_rtx (GET_MODE (it->store_mem));
       rtx_insn *insns = NULL;
-      const bool has_zero_offset = it->offset == 0;
+      const bool has_base_offset
+       = known_eq (poly_uint64 (it->offset),
+                   subreg_size_lowpart_offset (MEM_SIZE (it->store_mem),
+                                               load_size));
 
       /* If we're eliminating the load then find the store with zero offset
         and use it as the base register to avoid a bit insert if possible.  */
-      if (load_elim && has_zero_offset)
+      if (load_elim && has_base_offset)
        {
          start_sequence ();
 
diff --git a/gcc/testsuite/gcc.target/aarch64/avoid-store-forwarding-be.c b/gcc/testsuite/gcc.target/aarch64/avoid-store-forwarding-be.c
new file mode 100644 (file)
index 0000000..2e8946b
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-require-effective-target aarch64_big_endian } */
+/* { dg-options "-O2 -favoid-store-forwarding" } */
+
+typedef union {
+    char arr[2];
+    short value;
+} DataUnion;
+
+short __attribute__ ((noinline))
+ssll (DataUnion *data, char x, char y)
+{
+  data->arr[0] = x;
+  data->arr[1] = y;
+  return data->value;
+}
+
+int main () {
+  DataUnion data = {};
+  short value = ssll (&data, 0, 1);
+  if (value != 1)
+    __builtin_abort ();
+}
\ No newline at end of file