aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBill Schmidt <wschmidt@linux.ibm.com>2021-07-15 10:16:17 -0500
committerBill Schmidt <wschmidt@linux.ibm.com>2021-07-15 10:16:17 -0500
commitad5f8ac1d2f2dc92d43663243b52f9e9eb3cf7c0 (patch)
tree7fa76213f53a04aa4fcaec4420bc6d71aca3c224 /gcc
parent92acae5047e4b8c5be035f067099942a93e55d0c (diff)
downloadgcc-ad5f8ac1d2f2dc92d43663243b52f9e9eb3cf7c0.zip
gcc-ad5f8ac1d2f2dc92d43663243b52f9e9eb3cf7c0.tar.gz
gcc-ad5f8ac1d2f2dc92d43663243b52f9e9eb3cf7c0.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000-p8swap.c19
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr101129.c35
2 files changed, 54 insertions, 0 deletions
diff --git a/gcc/config/rs6000/rs6000-p8swap.c b/gcc/config/rs6000/rs6000-p8swap.c
index 21cbcb2..6b559aa 100644
--- a/gcc/config/rs6000/rs6000-p8swap.c
+++ b/gcc/config/rs6000/rs6000-p8swap.c
@@ -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;
}
diff --git a/gcc/testsuite/gcc.target/powerpc/pr101129.c b/gcc/testsuite/gcc.target/powerpc/pr101129.c
new file mode 100644
index 0000000..1abc124
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr101129.c
@@ -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;
+}