* config/aarch64/aarch64.md (multi3): New expander.
        (madd<GPI>): Remove leading * from name.
---
 gcc/config/aarch64/aarch64.md | 27 ++++++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 0b3943d..0f76cd1 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1968,7 +1968,7 @@
   [(set_attr "type" "mul")]
 )
 
-(define_insn "*madd<mode>"
+(define_insn "madd<mode>"
   [(set (match_operand:GPI 0 "register_operand" "=r")
        (plus:GPI (mult:GPI (match_operand:GPI 1 "register_operand" "r")
                            (match_operand:GPI 2 "register_operand" "r"))
@@ -2095,6 +2095,31 @@
   DONE;
 })
 
+;; The default expansion of multi3 using umuldi3_highpart will perform
+;; the additions in an order that fails to combine into two madd insns.
+(define_expand "multi3"
+  [(set (match_operand:TI 0 "register_operand")
+       (mult:TI (match_operand:TI 1 "register_operand")
+                (match_operand:TI 2 "register_operand")))]
+  ""
+{
+  rtx l0 = gen_reg_rtx (DImode);
+  rtx l1 = gen_lowpart (DImode, operands[1]);
+  rtx l2 = gen_lowpart (DImode, operands[2]);
+  rtx h0 = gen_reg_rtx (DImode);
+  rtx h1 = gen_highpart (DImode, operands[1]);
+  rtx h2 = gen_highpart (DImode, operands[2]);
+
+  emit_insn (gen_muldi3 (l0, l1, l2));
+  emit_insn (gen_umuldi3_highpart (h0, l1, l2));
+  emit_insn (gen_madddi (h0, h1, l2, h0));
+  emit_insn (gen_madddi (h0, l1, h2, h0));
+
+  emit_move_insn (gen_lowpart (DImode, operands[0]), l0);
+  emit_move_insn (gen_highpart (DImode, operands[0]), h0);
+  DONE;
+})
+
 (define_insn "<su>muldi3_highpart"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (truncate:DI
-- 
1.8.4.2

Reply via email to