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.
This passed bootstrap and regtesting on powerpc64le-linux with no regressions. I also confirmed the testcase is correctly not run on -m32 BE and passes on -m64 BE. Ok for trunk? This is broken back to GCC 12, so ok for the releases branches after some bake-in time on trunk? Peter gcc/ PR target/116415 * config/rs6000/rs6000-p8swap.cc (rs6000_analyze_swaps): Handle PTImode identically to TImode. gcc/testsuite/ PR target/116415 * gcc.target/powerpc/pr116415.c: New test. diff --git a/gcc/config/rs6000/rs6000-p8swap.cc b/gcc/config/rs6000/rs6000-p8swap.cc index 639f477d782..15e44bb63a6 100644 --- a/gcc/config/rs6000/rs6000-p8swap.cc +++ b/gcc/config/rs6000/rs6000-p8swap.cc @@ -2469,10 +2469,11 @@ rs6000_analyze_swaps (function *fun) mode = V4SImode; } - if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode) + if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode + || mode == PTImode) { insn_entry[uid].is_relevant = 1; - if (mode == TImode || mode == V1TImode + if (mode == TImode || mode == PTImode || mode == V1TImode || FLOAT128_VECTOR_P (mode)) insn_entry[uid].is_128_int = 1; if (DF_REF_INSN_INFO (mention)) @@ -2497,10 +2498,11 @@ 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) || mode == TImode + || mode == PTImode) { insn_entry[uid].is_relevant = 1; - if (mode == TImode || mode == V1TImode + if (mode == TImode || mode == PTImode || mode == V1TImode || FLOAT128_VECTOR_P (mode)) insn_entry[uid].is_128_int = 1; if (DF_REF_INSN_INFO (mention)) diff --git a/gcc/testsuite/gcc.target/powerpc/pr116415.c b/gcc/testsuite/gcc.target/powerpc/pr116415.c new file mode 100644 index 00000000000..5fad810ceb0 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr116415.c @@ -0,0 +1,43 @@ +/* { dg-do run } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } } */ +/* { 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; +}