From 695ae0e560396034bc1fc2e9d9e601ab7b3d901b Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <jozef.l@mittosystems.com>
Date: Wed, 23 Oct 2019 13:19:45 +0100
Subject: [PATCH] MSP430: Use mspabi helper function to perform HImode widening
multiplication
gcc/ChangeLog:
2019-10-23 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* config/msp430/msp430.c (msp430_expand_helper): Support expansion of
calls to __mspabi_mpy* functions.
* config/msp430/msp430.md (mulhisi3): New define_expand.
(umulhisi3): New define_expand.
(*mulhisi3_inline): Use old mulhisi3 define_insn.
(*umulhisi3_inline): Use old umulhisi3 define_insn.
---
gcc/config/msp430/msp430.c | 69 ++++++++++++++++++++++++++++++-------
gcc/config/msp430/msp430.md | 46 +++++++++++++++++++++++--
2 files changed, 101 insertions(+), 14 deletions(-)
@@ -53,6 +53,7 @@
static void msp430_compute_frame_info (void);
+static bool use_32bit_hwmult (void);
@@ -2710,7 +2711,7 @@ void
msp430_expand_helper (rtx *operands, const char *helper_name,
bool const_variants)
{
- rtx c, f;
+ rtx c, fusage, fsym;
char *helper_const = NULL;
int arg1 = 12;
int arg2 = 13;
@@ -2719,8 +2720,14 @@ msp430_expand_helper (rtx *operands, const char *helper_name,
machine_mode arg1mode = GET_MODE (operands[1]);
machine_mode arg2mode = GET_MODE (operands[2]);
int have_430x = msp430x ? 1 : 0;
+ int expand_mpy = strncmp (helper_name, "__mspabi_mpy",
+ sizeof ("__mspabi_mpy") - 1) == 0;
+ /* This function has been used incorrectly if CONST_VARIANTS is TRUE for a
+ hwmpy function. */
+ gcc_assert (!(expand_mpy && const_variants));
- if (CONST_INT_P (operands[2]))
+ /* Emit size-optimal insns for small shifts we can easily do inline. */
+ if (CONST_INT_P (operands[2]) && !expand_mpy)
{
int i;
@@ -2737,6 +2744,10 @@ msp430_expand_helper (rtx *operands, const char *helper_name,
}
}
+ if (arg1mode != VOIDmode && arg2mode != VOIDmode)
+ /* Modes of arguments must be equal if not constants. */
+ gcc_assert (arg1mode == arg2mode);
+
if (arg1mode == VOIDmode)
arg1mode = arg0mode;
if (arg2mode == VOIDmode)
@@ -2749,12 +2760,13 @@ msp430_expand_helper (rtx *operands, const char *helper_name,
}
else if (arg1mode == DImode)
{
- /* Shift value in R8:R11, shift amount in R12. */
arg1 = 8;
arg1sz = 4;
arg2 = 12;
}
+ /* Use the "const_variant" of a shift library function if requested.
+ These are faster, but have larger code size. */
if (const_variants
&& CONST_INT_P (operands[2])
&& INTVAL (operands[2]) >= 1
@@ -2768,25 +2780,58 @@ msp430_expand_helper (rtx *operands, const char *helper_name,
(int) INTVAL (operands[2]));
}
+ /* Setup the arguments to the helper function. */
emit_move_insn (gen_rtx_REG (arg1mode, arg1),
operands[1]);
if (!helper_const)
emit_move_insn (gen_rtx_REG (arg2mode, arg2),
operands[2]);
- c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
- gen_rtx_SYMBOL_REF (VOIDmode, helper_const
- ? helper_const
- : helper_name),
- GEN_INT (0));
+ if (expand_mpy)
+ {
+ if (msp430_use_f5_series_hwmult ())
+ fsym = gen_rtx_SYMBOL_REF (VOIDmode, concat (helper_name,
+ "_f5hw", NULL));
+ else if (use_32bit_hwmult ())
+ {
+ /* When the arguments are 16-bits, the 16-bit hardware multiplier is
+ used. */
+ if (arg1mode == HImode)
+ fsym = gen_rtx_SYMBOL_REF (VOIDmode, concat (helper_name,
+ "_hw", NULL));
+ else
+ fsym = gen_rtx_SYMBOL_REF (VOIDmode, concat (helper_name,
+ "_hw32", NULL));
+ }
+ /* 16-bit hardware multiply. */
+ else if (msp430_has_hwmult ())
+ fsym = gen_rtx_SYMBOL_REF (VOIDmode, concat (helper_name,
+ "_hw", NULL));
+ else
+ fsym = gen_rtx_SYMBOL_REF (VOIDmode, helper_name);
+ }
+ else
+ fsym = gen_rtx_SYMBOL_REF (VOIDmode,
+ helper_const ? helper_const : helper_name);
+
+ c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12), fsym, GEN_INT (0));
+
c = emit_call_insn (c);
RTL_CONST_CALL_P (c) = 1;
- f = 0;
- use_regs (&f, arg1, arg1sz);
+ /* Add register usage information for the arguments to the call. */
+ fusage = NULL;
+ use_regs (&fusage, arg1, arg1sz);
if (!helper_const)
- use_regs (&f, arg2, 1);
- add_function_usage_to (c, f);
+ {
+ /* If we are expanding a shift, we only need to use the low register
+ for the shift amount. */
+ if (!expand_mpy)
+ use_regs (&fusage, arg2, 1);
+ else
+ use_regs (&fusage, arg2, arg1sz);
+ }
+ add_function_usage_to (c, fusage);
emit_move_insn (operands[0],
/* Return value will always start in R12. */
@@ -1638,7 +1638,49 @@
"NOP"
)
-(define_insn "mulhisi3"
+; libgcc helper functions for widening multiplication aren't currently
+; generated by gcc, so we can't catch them later and map them to the mspabi
+; functions.
+; We catch the patterns here and either generate a call to the helper function,
+; or emit the hardware multiply instruction sequence inline.
+;
+; If we don't have hardware multiply support, it will generally be slower and
+; result in larger code to call the mspabi library function to perform the
+; widening multiplication than just leaving GCC to widen the arguments itself.
+;
+; We don't use library functions for SImode->DImode widening since its always
+; larger and slower than letting GCC widen the arguments inline.
+(define_expand "mulhisi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
+ "msp430_has_hwmult ()"
+ {
+ /* Leave the other case for the inline insn. */
+ if (!(optimize > 2 && msp430_has_hwmult ()))
+ {
+ msp430_expand_helper (operands, "__mspabi_mpysl", false);
+ DONE;
+ }
+ }
+)
+
+(define_expand "umulhisi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
+ (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
+ "msp430_has_hwmult ()"
+ {
+ /* Leave the other case for the inline insn. */
+ if (!(optimize > 2 && msp430_has_hwmult ()))
+ {
+ msp430_expand_helper (operands, "__mspabi_mpyul", false);
+ DONE;
+ }
+ }
+)
+
+(define_insn "*mulhisi3_inline"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
(sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
@@ -1651,7 +1693,7 @@
"
)
-(define_insn "umulhisi3"
+(define_insn "*umulhisi3_inline"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%0"))
(zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
--
2.17.1