Message ID | VI1PR0801MB21272437985FB988897A07CA83B90@VI1PR0801MB2127.eurprd08.prod.outlook.com |
---|---|
State | New |
Headers | show |
Series | [ARM] Cleanup 64-bit multiplies | expand |
ping 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 <wdijkstr@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.
Hi Wilco, On 9/9/19 6:08 PM, Wilco Dijkstra wrote: > ping > > > 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. > Hmm... quite a lot going on this patch. Perhaps breaking it into a series would have been easier. But I think I untangled it all and it looks like a good improvement. Ok. Thanks, Kyrill > Bootstrap OK on armhf, regress passes. > > ChangeLog: > 2019-09-03 Wilco Dijkstra <wdijkstr@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.
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.