This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RS6000] lqarx and stqcx. registers
- From: Alan Modra <amodra at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: David Edelsohn <dje dot gcc at gmail dot com>, Michael Meissner <mrmeissn at us dot ibm dot com>
- Date: Mon, 1 Feb 2016 08:58:04 +1030
- Subject: [RS6000] lqarx and stqcx. registers
- Authentication-results: sourceware.org; auth=none
lqarx RT and stqcx. RS are valid only with even numbered gprs. The
predicate to enforce this happens to allow a loophole, closed by this
patch.
This pattern created by combine:
Trying 8 -> 9:
Successfully matched this instruction:
(set (subreg:PTI (reg:TI 155 [ D.2357 ]) 0)
(unspec_volatile:PTI [
(mem/v:TI (reg/v/f:DI 157 [ mptr ]) [-1 S16 A128])
] UNSPECV_LL))
is seen by reload as needing to reload pseudo 155 in TI mode, which
has no requirement that the reg be even. Apparently, nothing checks
the predicate again after reload.
We only see this problem on gcc-5 and gcc-4.9, because on gcc-6 we
don't define WORD_REGISTER_OPERATIONS and combine happens to have a
bug in simplify_set that prevents it creating the problem subregs.
See https://gcc.gnu.org/ml/gcc-patches/2016-01/msg02377.html
Bootstrapped and regression tested powerpc64-linux biarch on master
both with and without the combine bug, and on gcc-5. OK for master
and active branches?
gcc/
PR target/69548
* config/rs6000/predicates.md (quad_int_reg_operand): Don't
allow subregs.
gcc/testsuite/
* gcc.target/powerpc/pr69548.c: New test.
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index b8f14fd..302303c 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -375,20 +375,19 @@
;; Return 1 if op is a general purpose register that is an even register
;; which suitable for a load/store quad operation
+;; Subregs are not allowed here because when they are combine can
+;; create (subreg:PTI (reg:TI pseudo)) which will cause reload to
+;; think the innermost reg needs reloading, in TImode instead of
+;; PTImode. So reload will choose a reg in TImode which has no
+;; requirement that the reg be even.
(define_predicate "quad_int_reg_operand"
- (match_operand 0 "register_operand")
+ (match_code "reg")
{
HOST_WIDE_INT r;
if (!TARGET_QUAD_MEMORY && !TARGET_QUAD_MEMORY_ATOMIC)
return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- if (!REG_P (op))
- return 0;
-
r = REGNO (op);
if (r >= FIRST_PSEUDO_REGISTER)
return 1;
diff --git a/gcc/testsuite/gcc.target/powerpc/pr69548.c b/gcc/testsuite/gcc.target/powerpc/pr69548.c
new file mode 100644
index 0000000..439f588
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr69548.c
@@ -0,0 +1,11 @@
+/* { dg-do assemble { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -Os -mbig" } */
+
+__int128
+quad_exchange (__int128 *ptr, __int128 newval)
+{
+ return __atomic_exchange_n (ptr, newval, __ATOMIC_RELAXED);
+}
--
Alan Modra
Australia Development Lab, IBM