summaryrefslogtreecommitdiff
path: root/gcc/combine.c
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2010-08-25 14:14:59 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2010-08-25 14:14:59 +0000
commitdcbd909c20b0f045f606448f068d75ac1bd3ee8f (patch)
treefc7abd9a5867b5301f6c577a01296f62b18e5e16 /gcc/combine.c
parent24621f7a9d1f9fce6e3d7bb72c273adb02f392d0 (diff)
downloadgcc-dcbd909c20b0f045f606448f068d75ac1bd3ee8f.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163547 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/combine.c')
-rw-r--r--gcc/combine.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/gcc/combine.c b/gcc/combine.c
index f144d1e8f28..94e68392d98 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. */