diff options
author | Andrew Stubbs <ams@codesourcery.com> | 2011-08-19 14:56:24 +0000 |
---|---|---|
committer | Andrew Stubbs <ams@gcc.gnu.org> | 2011-08-19 14:56:24 +0000 |
commit | 6a228c2c0e38da47c08d70a90f41301b1278357a (patch) | |
tree | 399ca1eadf9b56228d57ed6b32ae01a3e077b742 /gcc/tree-ssa-math-opts.c | |
parent | 26a855d7e05810f8032ebb8e46a9bf6d18fef50d (diff) | |
download | gcc-6a228c2c0e38da47c08d70a90f41301b1278357a.zip gcc-6a228c2c0e38da47c08d70a90f41301b1278357a.tar.gz gcc-6a228c2c0e38da47c08d70a90f41301b1278357a.tar.bz2 |
tree-ssa-math-opts.c (convert_mult_to_widen): Better handle unsigned inputs of different modes.
2011-08-19 Andrew Stubbs <ams@codesourcery.com>
gcc/
* tree-ssa-math-opts.c (convert_mult_to_widen): Better handle
unsigned inputs of different modes.
(convert_plusminus_to_widen): Likewise.
gcc/testsuite/
* gcc.target/arm/wmul-9.c: New file.
* gcc.target/arm/wmul-bitfield-2.c: New file.
From-SVN: r177908
Diffstat (limited to 'gcc/tree-ssa-math-opts.c')
-rw-r--r-- | gcc/tree-ssa-math-opts.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index bcc02b6..5ba31b5 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -2115,9 +2115,18 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi) { if (op != smul_widen_optab) { - from_mode = GET_MODE_WIDER_MODE (from_mode); - if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode)) - return false; + /* We can use a signed multiply with unsigned types as long as + there is a wider mode to use, or it is the smaller of the two + types that is unsigned. Note that type1 >= type2, always. */ + if ((TYPE_UNSIGNED (type1) + && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode)) + || (TYPE_UNSIGNED (type2) + && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode))) + { + from_mode = GET_MODE_WIDER_MODE (from_mode); + if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode)) + return false; + } op = smul_widen_optab; handler = find_widening_optab_handler_and_mode (op, to_mode, @@ -2284,14 +2293,20 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, /* There's no such thing as a mixed sign madd yet, so use a wider mode. */ if (from_unsigned1 != from_unsigned2) { - enum machine_mode mode = GET_MODE_WIDER_MODE (from_mode); - if (GET_MODE_PRECISION (mode) < GET_MODE_PRECISION (to_mode)) + /* We can use a signed multiply with unsigned types as long as + there is a wider mode to use, or it is the smaller of the two + types that is unsigned. Note that type1 >= type2, always. */ + if ((from_unsigned1 + && TYPE_PRECISION (type1) == GET_MODE_PRECISION (from_mode)) + || (from_unsigned2 + && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode))) { - from_mode = mode; - from_unsigned1 = from_unsigned2 = false; + from_mode = GET_MODE_WIDER_MODE (from_mode); + if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode)) + return false; } - else - return false; + + from_unsigned1 = from_unsigned2 = false; } /* If there was a conversion between the multiply and addition |