aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2010-08-25 14:14:59 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2010-08-25 14:14:59 +0000
commit0cdf7b49f10deeba7d5ba2ab3cedd4625718efef (patch)
treefc7abd9a5867b5301f6c577a01296f62b18e5e16
parent4942fc569c5ba8ab9bebfad2d9cc9630a69c2579 (diff)
downloadgcc-0cdf7b49f10deeba7d5ba2ab3cedd4625718efef.zip
gcc-0cdf7b49f10deeba7d5ba2ab3cedd4625718efef.tar.gz
gcc-0cdf7b49f10deeba7d5ba2ab3cedd4625718efef.tar.bz2
combine.c (find_split_point): Undo canonicalization of multiply-add to (minus x (mult)) when...
* combine.c (find_split_point): Undo canonicalization of multiply-add to (minus x (mult)) when it seems likely that this will increase the chances of a split. * gcc.target/i386/combine-mul.c: New test. From-SVN: r163547
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/combine.c17
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/i386/combine-mul.c23
4 files changed, 48 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e13577d..551e93b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -4,6 +4,10 @@
* combine.c (try_combine): Use reg_overlap_mentioned_p rather than
dead_or_set_p when computing i0_feeds_i2_n.
+ * combine.c (find_split_point): Undo canonicalization of multiply-add
+ to (minus x (mult)) when it seems likely that this will increase the
+ chances of a split.
+
2010-08-25 Richard Guenther <rguenther@suse.de>
PR lto/44562
diff --git a/gcc/combine.c b/gcc/combine.c
index f144d1e..94e6839 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -4771,6 +4771,23 @@ find_split_point (rtx *loc, rtx insn, bool set_src)
case PLUS:
case MINUS:
+ /* Canonicalization can produce (minus A (mult B C)), where C is a
+ constant. It may be better to try splitting (plus (mult B -C) A)
+ instead if this isn't a multiply by a power of two. */
+ if (set_src && code == MINUS && GET_CODE (XEXP (x, 1)) == MULT
+ && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
+ && exact_log2 (INTVAL (XEXP (XEXP (x, 1), 1))) < 0)
+ {
+ enum machine_mode mode = GET_MODE (x);
+ unsigned HOST_WIDE_INT this_int = INTVAL (XEXP (XEXP (x, 1), 1));
+ HOST_WIDE_INT other_int = trunc_int_for_mode (-this_int, mode);
+ SUBST (*loc, gen_rtx_PLUS (mode, gen_rtx_MULT (mode,
+ XEXP (XEXP (x, 1), 0),
+ GEN_INT (other_int)),
+ XEXP (x, 0)));
+ return find_split_point (loc, insn, set_src);
+ }
+
/* Split at a multiply-accumulate instruction. However if this is
the SET_SRC, we likely do not have such an instruction and it's
worthless to try this split. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6e8b140..a3153af 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2010-08-25 Bernd Schmidt <bernds@codesourcery.com>
+
+ * gcc.target/i386/combine-mul.c: New test.
+
2010-08-25 Richard Guenther <rguenther@suse.de>
PR lto/44562
diff --git a/gcc/testsuite/gcc.target/i386/combine-mul.c b/gcc/testsuite/gcc.target/i386/combine-mul.c
new file mode 100644
index 0000000..4ef80e8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/combine-mul.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "12345" } } */
+
+static inline unsigned int myrnd (void)
+{
+ static unsigned int s = 1388815473;
+ s *= 1103515245;
+ s += 12345;
+}
+
+struct __attribute__ ((packed)) A {
+ unsigned short i:1, l:1, j:3, k:11;
+};
+
+struct A sA;
+void testA (void)
+{
+ char *p = (char *) &sA;
+ *p++ = myrnd ();
+ *p++ = myrnd ();
+ sA.k = -1;
+}