diff options
author | Richard Henderson <rth@redhat.com> | 2005-04-24 00:59:22 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-04-24 00:59:22 -0700 |
commit | 1272914c20c57d7e4498e3a1a36c4784555a39c2 (patch) | |
tree | 6ef27bbdc28738298b27a76311c4ff4faf90efb3 /gcc | |
parent | d076e5d27d8e986eed6e5397e2b8f79a69955728 (diff) | |
download | gcc-1272914c20c57d7e4498e3a1a36c4784555a39c2.zip gcc-1272914c20c57d7e4498e3a1a36c4784555a39c2.tar.gz gcc-1272914c20c57d7e4498e3a1a36c4784555a39c2.tar.bz2 |
re PR target/21101 (ICE: could not find a spill register on MMX intrinsics)
PR target/21101
* config/i386/i386.h (CANNOT_CHANGE_MODE_CLASS): Move guts to ...
* config/i386/i386.c (ix86_cannot_change_mode_class): ... here.
Deny modes smaller than 4 bytes.
* config/i386/i386-protos.h: Update.
From-SVN: r98650
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 35 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr21101.c | 32 |
5 files changed, 84 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d4b9cf7..9f2ee99 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2005-04-24 Richard Henderson <rth@redhat.com> + + PR target/21101 + * config/i386/i386.h (CANNOT_CHANGE_MODE_CLASS): Move guts to ... + * config/i386/i386.c (ix86_cannot_change_mode_class): ... here. + Deny modes smaller than 4 bytes. + * config/i386/i386-protos.h: Update. + 2005-04-24 Ralf Corsepius <ralf.corsepius@rtems.org> * config.gcc (h8300-*-rtems*): Add h8300-*-rtemscoff*. @@ -74,9 +82,9 @@ 2005-04-23 Richard Henderson <rth@redhat.com> - PR rtl-opt/21102 - * simplify-rtx.c (simplify_binary_operation): Fix mode check before - performing some integral scalar simplifications. + PR rtl-opt/21102 + * simplify-rtx.c (simplify_binary_operation): Fix mode check before + performing some integral scalar simplifications. 2005-04-23 Richard Henderson <rth@redhat.com> diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 4834071..d8f15da 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -187,6 +187,8 @@ extern int ix86_register_move_cost (enum machine_mode, enum reg_class, enum reg_class); extern int ix86_secondary_memory_needed (enum reg_class, enum reg_class, enum machine_mode, int); +extern bool ix86_cannot_change_mode_class (enum machine_mode, + enum machine_mode, enum reg_class); extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class); extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int); extern void emit_i387_cw_initialization (rtx, rtx, int); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 5046cf5..110b233 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -15297,6 +15297,41 @@ ix86_secondary_memory_needed (enum reg_class class1, enum reg_class class2, return false; } +/* Return true if the registers in CLASS cannot represent the change from + modes FROM to TO. */ + +bool +ix86_cannot_change_mode_class (enum machine_mode from, enum machine_mode to, + enum reg_class class) +{ + if (from == to) + return false; + + /* x87 registers can't do subreg at all, as all values are reformated + to extended precision. */ + if (MAYBE_FLOAT_CLASS_P (class)) + return true; + + if (MAYBE_SSE_CLASS_P (class) || MAYBE_MMX_CLASS_P (class)) + { + /* Vector registers do not support QI or HImode loads. If we don't + disallow a change to these modes, reload will assume it's ok to + drop the subreg from (subreg:SI (reg:HI 100) 0). This affects + the vec_dupv4hi pattern. */ + if (GET_MODE_SIZE (from) < 4) + return true; + + /* Vector registers do not support subreg with nonzero offsets, which + are otherwise valid for integer registers. Since we can't see + whether we have a nonzero offset from here, prohibit all + nonparadoxical subregs changing size. */ + if (GET_MODE_SIZE (to) < GET_MODE_SIZE (from)) + return true; + } + + return false; +} + /* Return the cost of moving data from a register in class CLASS1 to one in class CLASS2. diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index b58373f..fc0596b 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1338,19 +1338,10 @@ enum reg_class || ((CLASS) == FP_TOP_REG) \ || ((CLASS) == FP_SECOND_REG)) -/* Return a class of registers that cannot change FROM mode to TO mode. - - x87 registers can't do subreg as all values are reformated to extended - precision. XMM registers does not support with nonzero offsets equal - to 4, 8 and 12 otherwise valid for integer registers. Since we can't - determine these, prohibit all nonparadoxical subregs changing size. */ - -#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ - (GET_MODE_SIZE (TO) < GET_MODE_SIZE (FROM) \ - ? reg_classes_intersect_p (FLOAT_SSE_REGS, (CLASS)) \ - || MAYBE_MMX_CLASS_P (CLASS) \ - : GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \ - ? reg_classes_intersect_p (FLOAT_REGS, (CLASS)) : 0) +/* Return a class of registers that cannot change FROM mode to TO mode. */ + +#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \ + ix86_cannot_change_mode_class (FROM, TO, CLASS) /* Stack layout; function entry, exit and calling. */ diff --git a/gcc/testsuite/gcc.target/i386/pr21101.c b/gcc/testsuite/gcc.target/i386/pr21101.c new file mode 100644 index 0000000..104b08c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr21101.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -funroll-loops -march=nocona" } */ + +#include <mmintrin.h> + +int W; +void f() +{ + int j; + int B, C; + unsigned char* S; + __m64 *T = (__m64 *) &W; + + for (j = 0; j < 16; j++, T++) + { + T[0] = T[1] = _mm_set1_pi8(*S); + S += W; + } + + C = 3 * B; + + __m64 E = _mm_set_pi16(3 * B, 3 * B, 3 * B, 5 * B); + __m64 G = _mm_set1_pi16(3 * B); + + for (j = 0; j < 16; j++) + { + __m64 R = _mm_set1_pi16(B + j * C); + R = _m_paddw(R, E); + R = _m_paddw(R, G); + T[0] = _mm_srai_pi16(R, 3); + } +} |