aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJozef Lawrynowicz <jozef.l@mittosystems.com>2019-10-30 14:15:02 +0000
committerJozef Lawrynowicz <jozefl@gcc.gnu.org>2019-10-30 14:15:02 +0000
commit499a39af5dd093a676a77e5694e185dea3a96121 (patch)
treead8a0ba08c82876707fd78d2df6c24cbe218d820
parent0149b1b4d7f0d3456e77c036a56c7003ca8a1b64 (diff)
downloadgcc-499a39af5dd093a676a77e5694e185dea3a96121.zip
gcc-499a39af5dd093a676a77e5694e185dea3a96121.tar.gz
gcc-499a39af5dd093a676a77e5694e185dea3a96121.tar.bz2
msp430.c (msp430_expand_helper): Support expansion of calls to __mspabi_mpy* functions.
2019-10-30 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. From-SVN: r277624
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/msp430/msp430.c69
-rw-r--r--gcc/config/msp430/msp430.md46
3 files changed, 110 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7b90915..70412cd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
2019-10-30 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.
+
+2019-10-30 Jozef Lawrynowicz <jozef.l@mittosystems.com>
+
* config/msp430/msp430.c (msp430_check_index_not_high_mem): New.
(msp430_check_plus_not_high_mem): New.
(msp430_op_not_in_high_mem): Use new functions to check if the operand
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index a3d0d9c..c058690 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -53,6 +53,7 @@
static void msp430_compute_frame_info (void);
+static bool use_32bit_hwmult (void);
@@ -2691,7 +2692,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;
@@ -2700,8 +2701,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;
@@ -2718,6 +2725,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)
@@ -2730,12 +2741,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
@@ -2749,25 +2761,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. */
diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md
index ed4c370..c3d8507 100644
--- a/gcc/config/msp430/msp430.md
+++ b/gcc/config/msp430/msp430.md
@@ -1642,7 +1642,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"))))]
@@ -1655,7 +1697,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"))))]