https://gcc.gnu.org/g:ab74b2d86471cdb5b8a327e734630f1288125d9e

commit r14-10849-gab74b2d86471cdb5b8a327e734630f1288125d9e
Author: Peter Bergner <berg...@linux.ibm.com>
Date:   Fri Aug 23 11:45:40 2024 -0500

    rs6000: Fix PTImode handling in power8 swap optimization pass [PR116415]
    
    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  <berg...@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)

Diff:
---
 gcc/config/rs6000/rs6000-p8swap.cc          |  8 +++---
 gcc/config/rs6000/rs6000.h                  |  2 ++
 gcc/testsuite/gcc.target/powerpc/pr116415.c | 42 +++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-p8swap.cc 
b/gcc/config/rs6000/rs6000-p8swap.cc
index 639f477d7822..05fb76057f93 100644
--- a/gcc/config/rs6000/rs6000-p8swap.cc
+++ b/gcc/config/rs6000/rs6000-p8swap.cc
@@ -2469,10 +2469,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))
@@ -2497,10 +2497,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))
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 197922fbb847..9b5cf321876b 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1005,6 +1005,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
index 000000000000..08cc282e2c27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr116415.c
@@ -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;
+}

Reply via email to