rs6000: Don't let swaps pass break multiply low-part (PR101129)
2021-07-15 Bill Schmidt <wschmidt@linux.ibm.com> gcc/ PR target/101129 * config/rs6000/rs6000-p8swap.c (has_part_mult): New. (rs6000_analyze_swaps): Insns containing a subreg of a mult are not swappable. gcc/testsuite/ PR target/101129 * gcc.target/powerpc/pr101129.c: New.
This commit is contained in:
parent
92acae5047
commit
ad5f8ac1d2
2 changed files with 54 additions and 0 deletions
|
@ -1523,6 +1523,22 @@ replace_swap_with_copy (swap_web_entry *insn_entry, unsigned i)
|
|||
insn->set_deleted ();
|
||||
}
|
||||
|
||||
/* INSN is known to contain a SUBREG, which we can normally handle,
|
||||
but if the SUBREG itself contains a MULT then we need to leave it alone
|
||||
to avoid turning a mult_hipart into a mult_lopart, for example. */
|
||||
static bool
|
||||
has_part_mult (rtx_insn *insn)
|
||||
{
|
||||
rtx body = PATTERN (insn);
|
||||
if (GET_CODE (body) != SET)
|
||||
return false;
|
||||
rtx src = SET_SRC (body);
|
||||
if (GET_CODE (src) != SUBREG)
|
||||
return false;
|
||||
rtx inner = XEXP (src, 0);
|
||||
return (GET_CODE (inner) == MULT);
|
||||
}
|
||||
|
||||
/* Make NEW_MEM_EXP's attributes and flags resemble those of
|
||||
ORIGINAL_MEM_EXP. */
|
||||
static void
|
||||
|
@ -2501,6 +2517,9 @@ rs6000_analyze_swaps (function *fun)
|
|||
insn_entry[uid].is_swappable = 0;
|
||||
else if (special != SH_NONE)
|
||||
insn_entry[uid].special_handling = special;
|
||||
else if (insn_entry[uid].contains_subreg
|
||||
&& has_part_mult (insn))
|
||||
insn_entry[uid].is_swappable = 0;
|
||||
else if (insn_entry[uid].contains_subreg)
|
||||
insn_entry[uid].special_handling = SH_SUBREG;
|
||||
}
|
||||
|
|
35
gcc/testsuite/gcc.target/powerpc/pr101129.c
Normal file
35
gcc/testsuite/gcc.target/powerpc/pr101129.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-require-effective-target p8vector_hw } */
|
||||
/* { dg-options "-mdejagnu-cpu=power8 -O " } */
|
||||
|
||||
/* PR101129: The swaps pass was turning a mult-lopart into a mult-hipart.
|
||||
Make sure we aren't doing that anymore. */
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned char __attribute__((__vector_size__ (8))) U;
|
||||
typedef unsigned char __attribute__((__vector_size__ (16))) V;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
typedef __int128 u128;
|
||||
|
||||
u8 g;
|
||||
U u;
|
||||
|
||||
void
|
||||
foo0 (u32 u32_0, U *ret)
|
||||
{
|
||||
u128 u128_2 = u32_0 * (u128)((V){ 5 } > (u32_0 & 4));
|
||||
u64 u64_r = u128_2 >> 64;
|
||||
u8 u8_r = u64_r + g;
|
||||
*ret = u + u8_r;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
U x;
|
||||
foo0 (7, &x);
|
||||
for (unsigned i = 0; i < sizeof (x); i++)
|
||||
if (x[i] != 0) __builtin_abort();
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue