From 32e68083d2878d03a5cc31700b6d01fb7765d3c3 Mon Sep 17 00:00:00 2001 From: kkojima Date: Tue, 21 Oct 2008 23:40:41 +0000 Subject: [PATCH] PR target/37633 * config/sh/sh.c (sh_hard_regno_mode_ok): New function. * config/sh/sh.h (HARD_REGNO_MODE_OK): Use it. * config/sh/sh-protos.h (sh_hard_regno_mode_ok): Declare. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141282 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 ++++ gcc/config/sh/sh-protos.h | 4 +- gcc/config/sh/sh.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++ gcc/config/sh/sh.h | 48 ++-------------------- 4 files changed, 114 insertions(+), 47 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 08743f849bd..f95f4e4afc9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2008-10-22 Kaz Kojima + + PR target/37633 + * config/sh/sh.c (sh_hard_regno_mode_ok): New function. + * config/sh/sh.h (HARD_REGNO_MODE_OK): Use it. + * config/sh/sh-protos.h (sh_hard_regno_mode_ok): Declare. + 2008-10-22 Jakub Jelinek PR target/37880 diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index a03c624d660..5b971960f2d 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler for Renesas / SuperH SH. Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2003, - 2004, 2005, 2006, 2007 + 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. Contributed by Steve Chamberlain (sac@cygnus.com). Improved by Jim Wilson (wilson@cygnus.com). @@ -174,7 +174,7 @@ extern enum reg_class sh_secondary_reload (bool, rtx, enum reg_class, extern int sh2a_get_function_vector_number (rtx); extern int sh2a_is_function_vector_call (rtx); extern void sh_fix_range (const char *); - +extern bool sh_hard_regno_mode_ok (unsigned int, enum machine_mode); #endif /* ! GCC_SH_PROTOS_H */ #ifdef SYMBIAN diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 7c0bdd4a72f..14892ce310a 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -10193,6 +10193,108 @@ sh_expand_binop_v2sf (enum rtx_code code, rtx op0, rtx op1, rtx op2) emit_insn (gen_binary_sf_op1 (op0, op1, op2, op)); } +/* Return true if hard register REGNO can hold a value of machine-mode MODE. + We can allow any mode in any general register. The special registers + only allow SImode. Don't allow any mode in the PR. + + We cannot hold DCmode values in the XD registers because alter_reg + handles subregs of them incorrectly. We could work around this by + spacing the XD registers like the DR registers, but this would require + additional memory in every compilation to hold larger register vectors. + We could hold SFmode / SCmode values in XD registers, but that + would require a tertiary reload when reloading from / to memory, + and a secondary reload to reload from / to general regs; that + seems to be a loosing proposition. + + We want to allow TImode FP regs so that when V4SFmode is loaded as TImode, + it won't be ferried through GP registers first. */ + +bool +sh_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) +{ + if (SPECIAL_REGISTER_P (regno)) + return mode == SImode; + + if (regno == FPUL_REG) + return (mode == SImode || mode == SFmode); + + if (FP_REGISTER_P (regno) && mode == SFmode) + return true; + + if (mode == V2SFmode) + { + if (((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 2 == 0) + || GENERAL_REGISTER_P (regno))) + return true; + else + return false; + } + + if (mode == V4SFmode) + { + if ((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 4 == 0) + || GENERAL_REGISTER_P (regno)) + return true; + else + return false; + } + + if (mode == V16SFmode) + { + if (TARGET_SHMEDIA) + { + if (FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 16 == 0) + return true; + else + return false; + } + else + return regno == FIRST_XD_REG; + } + + if (FP_REGISTER_P (regno)) + { + if (mode == SFmode + || mode == SImode + || ((TARGET_SH2E || TARGET_SHMEDIA) && mode == SCmode) + || ((((TARGET_SH4 || TARGET_SH2A_DOUBLE) && mode == DFmode) + || mode == DCmode + || (TARGET_SHMEDIA + && (mode == DFmode || mode == DImode + || mode == V2SFmode || mode == TImode))) + && ((regno - FIRST_FP_REG) & 1) == 0) + || ((TARGET_SH4 || TARGET_SHMEDIA) && mode == TImode + && ((regno - FIRST_FP_REG) & 3) == 0)) + return true; + else + return false; + } + + if (XD_REGISTER_P (regno)) + return mode == DFmode; + + if (TARGET_REGISTER_P (regno)) + return (mode == DImode || mode == SImode || mode == PDImode); + + if (regno == PR_REG) + return mode == SImode; + + if (regno == FPSCR_REG) + return mode == PSImode; + + /* FIXME. This works around PR target/37633 for -O0. */ + if (!optimize && TARGET_SHMEDIA32 && GET_MODE_SIZE (mode) > 4) + { + unsigned int n = GET_MODE_SIZE (mode) / 8; + + if (regno >= FIRST_GENERAL_REG + 10 - n + 1 + && regno <= FIRST_GENERAL_REG + 14) + return false; + } + + return true; +} + /* Return the class of registers for which a mode change from FROM to TO is invalid. */ bool diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 8b9ec86ceef..6a4ccb0f0e6 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -1208,52 +1208,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \ ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2)) \ : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) -/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. - We can allow any mode in any general register. The special registers - only allow SImode. Don't allow any mode in the PR. */ - -/* We cannot hold DCmode values in the XD registers because alter_reg - handles subregs of them incorrectly. We could work around this by - spacing the XD registers like the DR registers, but this would require - additional memory in every compilation to hold larger register vectors. - We could hold SFmode / SCmode values in XD registers, but that - would require a tertiary reload when reloading from / to memory, - and a secondary reload to reload from / to general regs; that - seems to be a loosing proposition. */ -/* We want to allow TImode FP regs so that when V4SFmode is loaded as TImode, - it won't be ferried through GP registers first. */ +/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ + #define HARD_REGNO_MODE_OK(REGNO, MODE) \ - (SPECIAL_REGISTER_P (REGNO) ? (MODE) == SImode \ - : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode \ - : FP_REGISTER_P (REGNO) && (MODE) == SFmode \ - ? 1 \ - : (MODE) == V2SFmode \ - ? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \ - || GENERAL_REGISTER_P (REGNO)) \ - : (MODE) == V4SFmode \ - ? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 4 == 0) \ - || GENERAL_REGISTER_P (REGNO)) \ - : (MODE) == V16SFmode \ - ? (TARGET_SHMEDIA \ - ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 16 == 0) \ - : (REGNO) == FIRST_XD_REG) \ - : FP_REGISTER_P (REGNO) \ - ? ((MODE) == SFmode || (MODE) == SImode \ - || ((TARGET_SH2E || TARGET_SHMEDIA) && (MODE) == SCmode) \ - || ((((TARGET_SH4 || TARGET_SH2A_DOUBLE) && (MODE) == DFmode) || (MODE) == DCmode \ - || (TARGET_SHMEDIA && ((MODE) == DFmode || (MODE) == DImode \ - || (MODE) == V2SFmode || (MODE) == TImode))) \ - && (((REGNO) - FIRST_FP_REG) & 1) == 0) \ - || ((TARGET_SH4 || TARGET_SHMEDIA) \ - && (MODE) == TImode \ - && (((REGNO) - FIRST_FP_REG) & 3) == 0)) \ - : XD_REGISTER_P (REGNO) \ - ? (MODE) == DFmode \ - : TARGET_REGISTER_P (REGNO) \ - ? ((MODE) == DImode || (MODE) == SImode || (MODE) == PDImode) \ - : (REGNO) == PR_REG ? (MODE) == SImode \ - : (REGNO) == FPSCR_REG ? (MODE) == PSImode \ - : 1) + sh_hard_regno_mode_ok ((REGNO), (MODE)) /* Value is 1 if it is a good idea to tie two pseudo registers when one has mode MODE1 and one has mode MODE2. -- 2.11.0