diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-04-22 12:46:07 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-04-22 12:46:07 +0000 |
commit | ac875fa40bf5429aff0612943d8c5705c4e11bb5 (patch) | |
tree | 6254ef8bed13933fcdfb55163f89625f1932c652 /gcc/stor-layout.c | |
parent | 3efb5d22322a504342153f3d64f1a3a209c3fe40 (diff) | |
download | gcc-ac875fa40bf5429aff0612943d8c5705c4e11bb5.tar.gz |
gcc/
* machmode.h (bitwise_mode_for_mode): Declare.
* stor-layout.h (bitwise_type_for_mode): Likewise.
* stor-layout.c (bitwise_mode_for_mode): New function.
(bitwise_type_for_mode): Likewise.
* builtins.c (fold_builtin_memory_op): Use it instead of
int_mode_for_mode and build_nonstandard_integer_type.
gcc/testsuite/
* gcc.dg/memcpy-5.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@209622 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/stor-layout.c')
-rw-r--r-- | gcc/stor-layout.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index e3f8406626b..4f99fa3469a 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -403,6 +403,73 @@ int_mode_for_mode (enum machine_mode mode) return mode; } +/* Find a mode that can be used for efficient bitwise operations on MODE. + Return BLKmode if no such mode exists. */ + +enum machine_mode +bitwise_mode_for_mode (enum machine_mode mode) +{ + /* Quick exit if we already have a suitable mode. */ + unsigned int bitsize = GET_MODE_BITSIZE (mode); + if (SCALAR_INT_MODE_P (mode) && bitsize <= MAX_FIXED_MODE_SIZE) + return mode; + + /* Reuse the sanity checks from int_mode_for_mode. */ + gcc_checking_assert ((int_mode_for_mode (mode), true)); + + /* Try to replace complex modes with complex modes. In general we + expect both components to be processed independently, so we only + care whether there is a register for the inner mode. */ + if (COMPLEX_MODE_P (mode)) + { + enum machine_mode trial = mode; + if (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT) + trial = mode_for_size (bitsize, MODE_COMPLEX_INT, false); + if (trial != BLKmode + && have_regs_of_mode[GET_MODE_INNER (trial)]) + return trial; + } + + /* Try to replace vector modes with vector modes. Also try using vector + modes if an integer mode would be too big. */ + if (VECTOR_MODE_P (mode) || bitsize > MAX_FIXED_MODE_SIZE) + { + enum machine_mode trial = mode; + if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT) + trial = mode_for_size (bitsize, MODE_VECTOR_INT, 0); + if (trial != BLKmode + && have_regs_of_mode[trial] + && targetm.vector_mode_supported_p (trial)) + return trial; + } + + /* Otherwise fall back on integers while honoring MAX_FIXED_MODE_SIZE. */ + return mode_for_size (bitsize, MODE_INT, true); +} + +/* Find a type that can be used for efficient bitwise operations on MODE. + Return null if no such mode exists. */ + +tree +bitwise_type_for_mode (enum machine_mode mode) +{ + mode = bitwise_mode_for_mode (mode); + if (mode == BLKmode) + return NULL_TREE; + + unsigned int inner_size = GET_MODE_UNIT_BITSIZE (mode); + tree inner_type = build_nonstandard_integer_type (inner_size, true); + + if (VECTOR_MODE_P (mode)) + return build_vector_type_for_mode (inner_type, mode); + + if (COMPLEX_MODE_P (mode)) + return build_complex_type (inner_type); + + gcc_checking_assert (GET_MODE_INNER (mode) == VOIDmode); + return inner_type; +} + /* Find a mode that is suitable for representing a vector with NUNITS elements of mode INNERMODE. Returns BLKmode if there is no suitable mode. */ |