aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2010-10-18 19:12:07 -0700
committerRichard Henderson <rth@gcc.gnu.org>2010-10-18 19:12:07 -0700
commit5c822194254910c3a04cf470a9a6469958447c1f (patch)
tree3565cd8c24aa466a4cd83d5bc718350c9919d8a6 /gcc
parent89509419968e2be6c7880a97968f07fab6b0e3b2 (diff)
downloadgcc-5c822194254910c3a04cf470a9a6469958447c1f.zip
gcc-5c822194254910c3a04cf470a9a6469958447c1f.tar.gz
gcc-5c822194254910c3a04cf470a9a6469958447c1f.tar.bz2
simplify-rtx.c (simplify_ternary_operation): Simplify (fma (neg a) (neg b) c) and (fma a (neg b) c).
* simplify-rtx.c (simplify_ternary_operation) [FMA]: Simplify (fma (neg a) (neg b) c) and (fma a (neg b) c). From-SVN: r165677
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/simplify-rtx.c27
2 files changed, 29 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8f1595d..d044941 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
2010-10-18 Richard Henderson <rth@redhat.com>
+ * simplify-rtx.c (simplify_ternary_operation) [FMA]: Simplify
+ (fma (neg a) (neg b) c) and (fma a (neg b) c).
+
+2010-10-18 Richard Henderson <rth@redhat.com>
+
* config/i386/i386.c (IX86_BUILTIN_VFMSUBSS, IX86_BUILTIN_VFMSUBSD,
IX86_BUILTIN_VFMSUBPS, IX86_BUILTIN_VFMSUBPD,
IX86_BUILTIN_VFMSUBADDPS, IX86_BUILTIN_VFMSUBADDPD,
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index f700958..e45917f 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -4705,6 +4705,8 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
rtx op2)
{
unsigned int width = GET_MODE_BITSIZE (mode);
+ bool any_change = false;
+ rtx tem;
/* VOIDmode means "infinite" precision. */
if (width == 0)
@@ -4712,10 +4714,29 @@ simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
switch (code)
{
- /* At present, don't simplify fused multiply and add ops, because we need
- to make sure there are no intermediate rounding steps used, and that
- we get the right sign if negative 0 would be returned. */
case FMA:
+ /* Simplify negations around the multiplication. */
+ /* -a * -b + c => a * b + c. */
+ if (GET_CODE (op0) == NEG)
+ {
+ tem = simplify_unary_operation (NEG, mode, op1, mode);
+ if (tem)
+ op1 = tem, op0 = XEXP (op0, 0), any_change = true;
+ }
+ else if (GET_CODE (op1) == NEG)
+ {
+ tem = simplify_unary_operation (NEG, mode, op0, mode);
+ if (tem)
+ op0 = tem, op1 = XEXP (op1, 0), any_change = true;
+ }
+
+ /* Canonicalize the two multiplication operands. */
+ /* a * -b + c => -b * a + c. */
+ if (swap_commutative_operands_p (op0, op1))
+ tem = op0, op0 = op1, op1 = tem, any_change = true;
+
+ if (any_change)
+ return gen_rtx_FMA (mode, op0, op1, op2);
return NULL_RTX;
case SIGN_EXTRACT: