From 1272914c20c57d7e4498e3a1a36c4784555a39c2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 24 Apr 2005 00:59:22 -0700 Subject: [PATCH] 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 --- gcc/ChangeLog | 14 ++++++++++--- gcc/config/i386/i386-protos.h | 2 ++ gcc/config/i386/i386.c | 35 +++++++++++++++++++++++++++++++++ gcc/config/i386/i386.h | 17 ++++------------ gcc/testsuite/gcc.target/i386/pr21101.c | 32 ++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr21101.c 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 + + 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 * config.gcc (h8300-*-rtems*): Add h8300-*-rtemscoff*. @@ -74,9 +82,9 @@ 2005-04-23 Richard Henderson - 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 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 + +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); + } +} -- 2.7.4