rs6000: MMA test case emits wrong code when building a vector pair [PR102976]

PR102976 shows a test case where we generate wrong code when building
a vector pair from 2 vector registers.  The bug here is that with unlucky
register assignments, we can clobber one of the input operands before
we write both registers of the output operand.  The solution is to use
early-clobbers in the assemble pair and accumulator patterns.

2021-11-16  Peter Bergner  <bergner@linux.ibm.com>

gcc/
	PR target/102976
	* config/rs6000/mma.md (*vsx_assemble_pair): Add early-clobber for
	output operand.
	(*mma_assemble_acc): Likewise.

gcc/testsuite/
	PR target/102976
	* gcc.target/powerpc/pr102976.c: New test.
This commit is contained in:
Peter Bergner 2021-11-16 12:14:22 -06:00
parent 48a8c5be5b
commit 4cdf7db9a3
2 changed files with 22 additions and 2 deletions

View File

@ -338,8 +338,11 @@
DONE;
})
;; We cannot update the two output registers atomically, so mark the output
;; as an early clobber so we don't accidentally clobber the input operands. */
(define_insn_and_split "*vsx_assemble_pair"
[(set (match_operand:OO 0 "vsx_register_operand" "=wa")
[(set (match_operand:OO 0 "vsx_register_operand" "=&wa")
(unspec:OO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")]
UNSPEC_MMA_ASSEMBLE))]
@ -404,8 +407,11 @@
DONE;
})
;; We cannot update the four output registers atomically, so mark the output
;; as an early clobber so we don't accidentally clobber the input operands. */
(define_insn_and_split "*mma_assemble_acc"
[(set (match_operand:XO 0 "fpr_reg_operand" "=d")
[(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
(unspec:XO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 3 "mma_assemble_input_operand" "mwa")

View File

@ -0,0 +1,14 @@
/* { dg-require-effective-target power10_ok } */
/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
#include <altivec.h>
void
bug (__vector_pair *dst)
{
register vector unsigned char vec0 asm ("vs44");
register vector unsigned char vec1 asm ("vs32");
__builtin_vsx_build_pair (dst, vec0, vec1);
}
/* { dg-final { scan-assembler-times {(?p)\mxxlor \d+,44,44\M} 1 } } */
/* { dg-final { scan-assembler-times {(?p)\mxxlor \d+,32,32\M} 1 } } */