Cleanup 64-bit multiplies.  Combine the expanders using iterators.
Merge the signed/unsigned multiplies as well as the pre-Armv6 and Armv6
variants.  Split DImode operands early into parallel sets inside the
MULL/MLAL instructions - this improves register allocation and avoids
subreg issues due to other DImode operations splitting early.

Bootstrap OK on armhf, regress passes.

ChangeLog:
2019-09-03  Wilco Dijkstra  <wdijk...@arm.com>

        * config/arm/arm.md (maddsidi4): Remove expander.
        (mulsidi3adddi): Remove pattern.
        (mulsidi3adddi_v6): Likewise.
        (mulsidi3_nov6): Likewise.
        (mulsidi3_v6): Likewise.
        (umulsidi3): Remove expander.
        (umulsidi3_nov6): Remove pattern.
        (umulsidi3_v6): Likewise.
        (umulsidi3adddi): Likewise.
        (umulsidi3adddi_v6): Likewise.
        (<Us>mulsidi3): Add combined expander.
        (<Us>maddsidi4): Likewise.
        (<US>mull): Add combined umull and smull pattern.
        (<US>mlal): Likewise.
        * config/arm/iterators.md (Us): Add new iterator.
--
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
1ab203810bf143927a8afa0d00d82537cd7c75ed..c1fea4abdbccedbbbed9a25cab133de5cacb1afb
 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -1636,144 +1636,80 @@ (define_insn "*mls"
    (set_attr "predicable" "yes")]
 )
 
-(define_expand "maddsidi4"
-  [(set (match_operand:DI 0 "s_register_operand")
-       (plus:DI
-        (mult:DI
-         (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
-         (sign_extend:DI (match_operand:SI 2 "s_register_operand")))
-        (match_operand:DI 3 "s_register_operand")))]
-  "TARGET_32BIT"
-  "")
-
-(define_insn "*mulsidi3adddi"
-  [(set (match_operand:DI 0 "s_register_operand" "=&r")
-       (plus:DI
-        (mult:DI
-         (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
-         (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
-        (match_operand:DI 1 "s_register_operand" "0")))]
-  "TARGET_32BIT && !arm_arch6"
-  "smlal%?\\t%Q0, %R0, %3, %2"
-  [(set_attr "type" "smlal")
-   (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulsidi3adddi_v6"
-  [(set (match_operand:DI 0 "s_register_operand" "=r")
-       (plus:DI
-        (mult:DI
-         (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
-         (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
-        (match_operand:DI 1 "s_register_operand" "0")))]
-  "TARGET_32BIT && arm_arch6"
-  "smlal%?\\t%Q0, %R0, %3, %2"
-  [(set_attr "type" "smlal")
-   (set_attr "predicable" "yes")]
-)
-
 ;; 32x32->64 widening multiply.
-;; As with mulsi3, the only difference between the v3-5 and v6+
-;; versions of these patterns is the requirement that the output not
-;; overlap the inputs, but that still means we have to have a named
-;; expander and two different starred insns.
+;; The only difference between the v3-5 and v6+ versions is the requirement
+;; that the output does not overlap with either input.
 
-(define_expand "mulsidi3"
+(define_expand "<Us>mulsidi3"
   [(set (match_operand:DI 0 "s_register_operand")
        (mult:DI
-        (sign_extend:DI (match_operand:SI 1 "s_register_operand"))
-        (sign_extend:DI (match_operand:SI 2 "s_register_operand"))))]
+        (SE:DI (match_operand:SI 1 "s_register_operand"))
+        (SE:DI (match_operand:SI 2 "s_register_operand"))))]
   "TARGET_32BIT"
-  ""
-)
-
-(define_insn "*mulsidi3_nov6"
-  [(set (match_operand:DI 0 "s_register_operand" "=&r")
-       (mult:DI
-        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
-        (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
-  "TARGET_32BIT && !arm_arch6"
-  "smull%?\\t%Q0, %R0, %1, %2"
-  [(set_attr "type" "smull")
-   (set_attr "predicable" "yes")]
-)
-
-(define_insn "*mulsidi3_v6"
-  [(set (match_operand:DI 0 "s_register_operand" "=r")
-       (mult:DI
-        (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
-        (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
-  "TARGET_32BIT && arm_arch6"
-  "smull%?\\t%Q0, %R0, %1, %2"
-  [(set_attr "type" "smull")
-   (set_attr "predicable" "yes")]
+  {
+      emit_insn (gen_<US>mull (gen_lowpart (SImode, operands[0]),
+                              gen_highpart (SImode, operands[0]),
+                              operands[1], operands[2]));
+      DONE;
+  }
 )
 
-(define_expand "umulsidi3"
-  [(set (match_operand:DI 0 "s_register_operand")
-       (mult:DI
-        (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
-        (zero_extend:DI (match_operand:SI 2 "s_register_operand"))))]
+(define_insn "<US>mull"
+  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
+       (mult:SI
+        (match_operand:SI 2 "s_register_operand" "%r,r")
+        (match_operand:SI 3 "s_register_operand" "r,r")))
+   (set (match_operand:SI 1 "s_register_operand" "=r,&r")
+       (truncate:SI
+        (lshiftrt:DI
+         (mult:DI (SE:DI (match_dup 2)) (SE:DI (match_dup 3)))
+         (const_int 32))))]
   "TARGET_32BIT"
-  ""
-)
-
-(define_insn "*umulsidi3_nov6"
-  [(set (match_operand:DI 0 "s_register_operand" "=&r")
-       (mult:DI
-        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
-        (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
-  "TARGET_32BIT && !arm_arch6"
-  "umull%?\\t%Q0, %R0, %1, %2"
-  [(set_attr "type" "umull")
-   (set_attr "predicable" "yes")]
-)
-
-(define_insn "*umulsidi3_v6"
-  [(set (match_operand:DI 0 "s_register_operand" "=r")
-       (mult:DI
-        (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r"))
-        (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
-  "TARGET_32BIT && arm_arch6"
-  "umull%?\\t%Q0, %R0, %1, %2"
+  "<US>mull%?\\t%0, %1, %2, %3"
   [(set_attr "type" "umull")
-   (set_attr "predicable" "yes")]
+   (set_attr "predicable" "yes")
+   (set_attr "arch" "v6,nov6")]
 )
 
-(define_expand "umaddsidi4"
+(define_expand "<Us>maddsidi4"
   [(set (match_operand:DI 0 "s_register_operand")
        (plus:DI
         (mult:DI
-         (zero_extend:DI (match_operand:SI 1 "s_register_operand"))
-         (zero_extend:DI (match_operand:SI 2 "s_register_operand")))
+         (SE:DI (match_operand:SI 1 "s_register_operand"))
+         (SE:DI (match_operand:SI 2 "s_register_operand")))
         (match_operand:DI 3 "s_register_operand")))]
   "TARGET_32BIT"
-  "")
-
-(define_insn "*umulsidi3adddi"
-  [(set (match_operand:DI 0 "s_register_operand" "=&r")
-       (plus:DI
-        (mult:DI
-         (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
-         (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
-        (match_operand:DI 1 "s_register_operand" "0")))]
-  "TARGET_32BIT && !arm_arch6"
-  "umlal%?\\t%Q0, %R0, %3, %2"
-  [(set_attr "type" "umlal")
-   (set_attr "predicable" "yes")]
+  {
+      emit_insn (gen_<US>mlal (gen_lowpart (SImode, operands[0]),
+                              gen_lowpart (SImode, operands[3]),
+                              gen_highpart (SImode, operands[0]),
+                              gen_highpart (SImode, operands[3]),
+                              operands[1], operands[2]));
+      DONE;
+  }
 )
 
-(define_insn "*umulsidi3adddi_v6"
-  [(set (match_operand:DI 0 "s_register_operand" "=r")
-       (plus:DI
-        (mult:DI
-         (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))
-         (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
-        (match_operand:DI 1 "s_register_operand" "0")))]
-  "TARGET_32BIT && arm_arch6"
-  "umlal%?\\t%Q0, %R0, %3, %2"
+(define_insn "<US>mlal"
+  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
+       (plus:SI
+        (mult:SI
+         (SE:DI (match_operand:SI 4 "s_register_operand" "%r,r"))
+         (SE:DI (match_operand:SI 5 "s_register_operand" "r,r")))
+        (match_operand:SI 1 "s_register_operand" "0,0")))
+   (set (match_operand:SI 2 "s_register_operand" "=r,&r")
+       (plus:SI
+        (truncate:SI
+         (lshiftrt:DI
+          (plus:DI
+           (mult:DI (SE:DI (match_dup 4)) (SE:DI (match_dup 5)))
+           (zero_extend:DI (match_dup 1)))
+          (const_int 32)))
+        (match_operand:SI 3 "s_register_operand" "2,2")))]
+  "TARGET_32BIT"
+  "<US>mlal%?\\t%0, %2, %4, %5"
   [(set_attr "type" "umlal")
-   (set_attr "predicable" "yes")]
+   (set_attr "predicable" "yes")
+   (set_attr "arch" "v6,nov6")]
 )
 
 (define_expand "<US>mulsi3_highpart"
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 
fa6f0c0529d5364b1e1df705cb1029868578e38c..c29897a3b70d342b025c72b8c032bb3bb831040f
 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -796,6 +796,7 @@ (define_code_attr optab [(ltu "ltu") (geu "geu")])
 
 ;; Assembler mnemonics for signedness of widening operations.
 (define_code_attr US [(sign_extend "s") (zero_extend "u")])
+(define_code_attr Us [(sign_extend "") (zero_extend "u")])
 
 ;; Signedness suffix for float->fixed conversions.  Empty for signed
 ;; conversion.

Reply via email to