]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rs6000: Fix PTImode handling in power8 swap optimization pass [PR116415]
authorPeter Bergner <bergner@linux.ibm.com>
Fri, 23 Aug 2024 16:45:40 +0000 (11:45 -0500)
committerPeter Bergner <bergner@linux.ibm.com>
Tue, 29 Oct 2024 03:38:48 +0000 (22:38 -0500)
Our power8 swap optimization pass has some special handling for optimizing
swaps of TImode variables.  The test case reported in bugzilla uses a call
to  __atomic_compare_exchange, which introduces a variable of PTImode and
that does not get the same treatment as TImode leading to wrong code
generation.  The simple fix is to treat PTImode identically to TImode.

2024-08-23  Peter Bergner  <bergner@linux.ibm.com>

gcc/
PR target/116415
* config/rs6000/rs6000.h (TI_OR_PTI_MODE): New define.
* config/rs6000/rs6000-p8swap.cc (rs6000_analyze_swaps): Use it to
handle PTImode identically to TImode.

gcc/testsuite/
PR target/116415
* gcc.target/powerpc/pr116415.c: New test.

(cherry picked from commit 6e68c3df1540c5bafbb47343698bf4e270333fdb)

gcc/config/rs6000/rs6000-p8swap.cc
gcc/config/rs6000/rs6000.h
gcc/testsuite/gcc.target/powerpc/pr116415.c [new file with mode: 0644]

index 62f5ca5bff4a060919232a38ec4e739d1eb09b6b..e97a32b4c2367a1419b9980a60ef5c5fc6e853f2 100644 (file)
@@ -2467,10 +2467,10 @@ rs6000_analyze_swaps (function *fun)
                    mode = V4SImode;
                }
 
-             if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
+             if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || TI_OR_PTI_MODE (mode))
                {
                  insn_entry[uid].is_relevant = 1;
-                 if (mode == TImode || mode == V1TImode
+                 if (TI_OR_PTI_MODE (mode) || mode == V1TImode
                      || FLOAT128_VECTOR_P (mode))
                    insn_entry[uid].is_128_int = 1;
                  if (DF_REF_INSN_INFO (mention))
@@ -2495,10 +2495,10 @@ rs6000_analyze_swaps (function *fun)
                  && ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (SET_DEST (insn))))
                mode = GET_MODE (SET_DEST (insn));
 
-             if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
+             if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || TI_OR_PTI_MODE (mode))
                {
                  insn_entry[uid].is_relevant = 1;
-                 if (mode == TImode || mode == V1TImode
+                 if (TI_OR_PTI_MODE (mode) || mode == V1TImode
                      || FLOAT128_VECTOR_P (mode))
                    insn_entry[uid].is_128_int = 1;
                  if (DF_REF_INSN_INFO (mention))
index 5588a4bae02732a6e6e5e3ecfb73a0e21579427d..48ba4df1da5cf400098c925f56811b6aec751e70 100644 (file)
@@ -1051,6 +1051,8 @@ enum data_align { align_abi, align_opt, align_both };
   (ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)                        \
    || (MODE) == V2DImode || (MODE) == V1TImode)
 
+#define TI_OR_PTI_MODE(mode) ((mode) == TImode || (mode) == PTImode)
+
 /* Post-reload, we can't use any new AltiVec registers, as we already
    emitted the vrsave mask.  */
 
diff --git a/gcc/testsuite/gcc.target/powerpc/pr116415.c b/gcc/testsuite/gcc.target/powerpc/pr116415.c
new file mode 100644 (file)
index 0000000..08cc282
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do run } */
+/* { dg-require-effective-target p8vector_hw } */
+/* { dg-require-effective-target int128 } */
+/* { dg-options "-O2 -mdejagnu-cpu=power8" } */
+
+/* PR 116415: Verify our Power8 swap optimization pass doesn't incorrectly swap
+   PTImode values.  They should be handled identically to TImode values.  */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef union {
+  struct {
+    uint64_t a;
+    uint64_t b;
+  } t;
+  __uint128_t data;
+} Value;
+Value value, next;
+
+void
+bug (Value *val, Value *nxt)
+{
+  for (;;) {
+    nxt->t.a = val->t.a + 1;
+    nxt->t.b = val->t.b + 2;
+    if (__atomic_compare_exchange (&val->data, &val->data, &nxt->data,
+                                  0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE))
+      break;
+  }
+}
+
+int
+main (void)
+{
+  bug (&value, &next);
+  printf ("%lu %lu\n", value.t.a, value.t.b);
+  if (value.t.a != 1 || value.t.b != 2)
+    abort ();
+  return 0;
+}