diff options
author | Peter Bergner <bergner@linux.ibm.com> | 2024-08-23 11:45:40 -0500 |
---|---|---|
committer | Peter Bergner <bergner@gcc.gnu.org> | 2024-08-23 11:45:40 -0500 |
commit | 6e68c3df1540c5bafbb47343698bf4e270333fdb (patch) | |
tree | 359ac4038dc641fcb04853f37d6ec3076fcec4cc /gcc | |
parent | cb51e0b236c7d492af2033582230e78d8b55290f (diff) | |
download | gcc-6e68c3df1540c5bafbb47343698bf4e270333fdb.zip gcc-6e68c3df1540c5bafbb47343698bf4e270333fdb.tar.gz gcc-6e68c3df1540c5bafbb47343698bf4e270333fdb.tar.bz2 |
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 <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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/rs6000/rs6000-p8swap.cc | 8 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 2 | ||||
-rw-r--r-- | 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 639f477..05fb760 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 703be90..d460eb0 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -986,6 +986,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 0000000..08cc282 --- /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; +} |