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; +}