From cd8b4fae52d02541c2d8bd2200caad3812f37368 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 20 Feb 2023 22:07:57 +0100 Subject: [PATCH] powerpc: Another umaddditi4 fix [PR108862] The following testcase is miscompiled on powerpc64le-linux with -O2 -mcpu=power9. The problem is that gen_umaddditi4 is called with the same TImode register for both op0 and op3, and maddlddi4 overwrites the low half of op0 before the low half of op3 is read, so when they are the same register it reads the result of maddlddi4. The following patch fixes that by swapping maddlddi4 and umadddi4_highpart{,_le} during expansion, as the latter writes into a temporary pseudo and so can't change anything maddlddi4 depends on. 2023-02-20 Jakub Jelinek PR target/108862 * config/rs6000/rs6000.md (umaddditi4): Swap gen_maddlddi4 with gen_umadddi4_highpart{,_le}. * gcc.dg/pr108862.c: New test. * gcc.target/powerpc/pr108862.c: New test. --- gcc/config/rs6000/rs6000.md | 4 ++-- gcc/testsuite/gcc.dg/pr108862.c | 27 +++++++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr108862.c | 6 ++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr108862.c create mode 100644 gcc/testsuite/gcc.target/powerpc/pr108862.c diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 162340b..81bffb0 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -3249,8 +3249,6 @@ rtx op3_hi = gen_rtx_SUBREG (DImode, operands[3], BYTES_BIG_ENDIAN ? 0 : 8); rtx hi_temp = gen_reg_rtx (DImode); - emit_insn (gen_maddlddi4 (op0_lo, operands[1], operands[2], op3_lo)); - if (BYTES_BIG_ENDIAN) emit_insn (gen_umadddi4_highpart (hi_temp, operands[1], operands[2], op3_lo)); @@ -3258,6 +3256,8 @@ emit_insn (gen_umadddi4_highpart_le (hi_temp, operands[1], operands[2], op3_lo)); + emit_insn (gen_maddlddi4 (op0_lo, operands[1], operands[2], op3_lo)); + emit_insn (gen_adddi3 (op0_hi, hi_temp, op3_hi)); DONE; diff --git a/gcc/testsuite/gcc.dg/pr108862.c b/gcc/testsuite/gcc.dg/pr108862.c new file mode 100644 index 0000000..065099e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr108862.c @@ -0,0 +1,27 @@ +/* PR target/108862 */ +/* { dg-do run { target int128 } } */ +/* { dg-options "-O2" } */ + +unsigned long long a[2] = { 0x04a13945d898c296ULL, 0x0000100000000fffULL }; +unsigned long long b[4] = { 0x04a13945d898c296ULL, 0, 0, 0x0000100000000fffULL }; + +__attribute__((noipa)) unsigned __int128 +foo (int x, unsigned long long *y, unsigned long long *z) +{ + unsigned __int128 w = 0; + for (int i = 0; i < x; i++) + w += (unsigned __int128)*y++ * (unsigned __int128)*z--; + return w; +} + +int +main () +{ + unsigned __int128 x = foo (1, &a[0], &a[1]); + unsigned __int128 y = foo (2, &b[0], &b[3]); + if ((unsigned long long) (x >> 64) != 0x0000004a13945dd3ULL + || (unsigned long long) x != 0x9b1c8443b3909d6aULL + || x != y) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr108862.c b/gcc/testsuite/gcc.target/powerpc/pr108862.c new file mode 100644 index 0000000..89bbb08 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr108862.c @@ -0,0 +1,6 @@ +/* PR target/108862 */ +/* { dg-do run { target int128 } } */ +/* { dg-require-effective-target p9vector_hw } */ +/* { dg-options "-O2 -mdejagnu-cpu=power9" } */ + +#include "../../gcc.dg/pr108862.c" -- 2.7.4