From 9c878e1b27d2177f5c47663bbb6a7af518c52164 Mon Sep 17 00:00:00 2001 From: meissner Date: Tue, 23 Jun 2009 20:15:15 +0000 Subject: [PATCH] Step 1 of VSX changes: Powerpc infrstructure changes git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@148869 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 178 ++++++++++++ gcc/config.in | 13 +- gcc/config/rs6000/aix53.h | 10 +- gcc/config/rs6000/aix61.h | 10 +- gcc/config/rs6000/driver-rs6000.c | 149 ++++++++++- gcc/config/rs6000/e500.h | 5 +- gcc/config/rs6000/linux64.h | 2 +- gcc/config/rs6000/linux64.opt | 4 +- gcc/config/rs6000/rs6000-c.c | 4 + gcc/config/rs6000/rs6000-protos.h | 3 +- gcc/config/rs6000/rs6000.c | 550 ++++++++++++++++++++++++++++++++------ gcc/config/rs6000/rs6000.h | 254 ++++++++++++++---- gcc/config/rs6000/rs6000.md | 200 ++++++++++---- gcc/config/rs6000/rs6000.opt | 20 +- gcc/config/rs6000/spe.md | 4 +- gcc/config/rs6000/sync.md | 2 +- gcc/config/rs6000/sysv4.h | 4 +- gcc/config/rs6000/sysv4.opt | 8 +- gcc/config/rs6000/t-rs6000 | 27 ++ gcc/configure | 98 ++++++- gcc/configure.ac | 36 ++- 21 files changed, 1327 insertions(+), 254 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4c20942..ea2ca53 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,181 @@ +2009-06-23 Michael Meissner + Pat Haugen + Revital1 Eres + + * config.in (HAVE_AS_POPCNTD): Add default definition. + (HAVE_AS_LWSYNC): Ditto. + + * configure.ac (gcc_cv_as_powerpc_mfpgpr): Provide real binutils + release number. + (gcc_cv_as_powerpc_cmpb): Ditto. + (gcc_cv_as_powerpc_dfp): Ditto. + (gcc_cv_as_powerpc_vsx): Ditto. + (gcc_cv_as_powerpc_popcntd): Add feature test for assembler + supporting the popcntd/lwsync instructions. + (gcc_cv_as_powerpc_lwsync): Ditto. + * configure: Regenerate. + + * config/rs6000/aix53.h (ASM_CPU_SPEC): Add support for + -mcpu=native and -mcpu=power7. + * config/rs6000/aix61.h (ASM_CPU_SPEC): Ditto. + + * config/rs6000/linux64.opt (-mprofile-kernel): Move switch to be + a variable instead of a mask to reduce the number of mask bits. + * config/rs6000/sysv4.opt (-mbit-align): Ditto. + (-mbit-word): Ditto. + (-mregnames): Ditto. + * config/rs6000/rs6000.opt (-mupdate): Ditto. + (-mfused-madd): Ditto. + + * config/rs6000/rs6000.opt (-mpopcntd): New switch for non-VSX ISA + 2.06 instructions. + (-mvsx): New switch for VSX instructions. + (-misel): Move from a variable to a mask to allow it to be set by + -mcpu=. + + * config/rs6000/rs6000-protos.h (rs6000_hard_regno_nregs): Change + function declaration to an array declaration. + (rs6000_hard_regno_nregs): New external array declaration. + + * config/rs6000/t-rs6000 (MD_INCLUDES): Define, add all of the .md + files included by rs6000.md. + + * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Use + SET_PROFILE_KERNEL macro to reset the -mprofile-kernel switch. + + * config/rs6000/rs6000.c (rs6000_isel): Delete, -misel moved to be + a target mask. + (rs6000_debug_reg): New -mdebug= variables. + (rs6000_debug_addr): Ditto. + (rs6000_debug_cost): Ditto. + (rs6000_pmode): New variable to hold Pmode. + (rs6000_pointer_size): New variable to hold POINTER_SIZE. + (rs6000_class_max_nregs): New array to hold CLASS_MAX_NREGS + calculated at compiler start. + (rs6000_hard_regno_nregs): Change function to an array which holds + HARD_REGNO_NREGS calculated at compiler start. + (rs6000_explicit_options): Delete isel field. + (rs6000_vector_unit): New array to hold which vector unit + supports arithmetic options for a given type. + (rs6000_vector_mem): New array to hold which vector unit supports + memory reference operations for a given type. + (rs6000_vector_align): New array to given the alignment of each + vector type. + (power7_cost): New basic costs for power7. + (SET_PROFILE_KERNEL): New macro for resetting -mprofile-kernel. + (rs6000_hard_regno_nregs_internal): New function, moved from + HARD_REGNO_NREGS, to calculate the number of registers each hard + register takes for each type. + (rs6000_debug_reg_print): New function for -mdebug=reg support. + (rs6000_debug_vector_unit): New array, map rs6000_vector to + string. + (+rs6000_init_hard_regno_mode_ok): New function, move calculation + of HARD_REGNO_NREGS, CLASS_MAX_NREGS, REGNO_REG_CLASS, and vector + unit information here so it is calculated once at compiler startup + time. + (rs6000_override_options): Make -misel a target mask. Add more + power7 target masks. Setup Pmode and POINTER_SIZE. Add initial + VSX support. Add support for -mdebug=reg, -mdebug=addr, and + -mdebug=cost. + (POWERPC_MASKS): Add MASK_POPCNTD, MASK_VSX, and MASK_ISEL. + (rs6000_handle_option): Move -misel from variable to target mask. + (rs6000_builtin_mask_for_load): Add VSX support. + (rs6000_conditional_register_usage): Ditto. + (USE_ALTIVEC_FOR_ARG_P): Ditto. + (function_arg_boundary): Ditto. + (rs6000_expand_builtin): Ditto. + (def_builtin): Make abort message a little friendlier. + (rs6000_emit_int_cmove): Add support for 64-bit isel. + + * config/rs6000/rs6000.h (ASM_CPU_POWER7_SPEC): Depend on the + assembler support the popcntd instruction instead of a vsx + instruction to enable power7 support. + (ASM_CPU_SPEC): Add support for -mcpu=native and -mcpu=power7. + (EXTRA_SPECS): Add ASM_CPU_NATIVE_SPEC to allow passing the right + option to the assembler if -mcpu=native. + (ASM_CPU_NATIVE_SPEC): Ditto. + (TARGET_POPCNTD): If assembler doesn't support popcntd, turn off + ISA 2.06 features. + (TARGET_LWSYNC_INSTRUCTION): Define whether it is safe to issue + the lwsync instruction. + (enum processor_type): Add PROCESSOR_POWER7. + (rs6000_debug_reg): New -mdebug= options. + (rs6000_debug_addr): Ditto. + (rs6000_debug_cost): Ditto. + (rs6000_isel): Delete. + (enum rs6000_vector): New enum to say what vector unit we have. + (VECTOR_UNIT_*): New macros to say which vector unit has + arithmetic operations for a given type. + (VECTOR_MEM_*): New macros to say which vector unit has memory + operations for a given type. + (TARGET_LDBRX): Whether the machine supports the ldbrx + instruction. + (TARGET_ISEL): Delete, -misel moved to be a mask. + (TARGET_ISEL64): New macro for 64-bit isel support. + (UNITS_PER_VSX_WORD): New macro. + (POINTER_SIZE): Move to be an external variable, rather than + calculating whether we are generating 32 ot 64-bit code. + (Pmode): Ditto. + (STACK_BOUNDARY): Add VSX support. + (LOCAL_ALIGNMENT): Ditto. + (SLOW_UNALIGNED_ACCESS): Ditto. + (VSX_REGNO_P): New macro for VSX support. + (VFLOAT_REGNO_P): Ditto. + (VINT_REGNO_P): Ditto. + (VLOGICAL_REGNO_P): Ditto. + (VSX_VECTOR_MODE): Ditto. + (VSX_SCALAR_MODE): Ditto. + (VSX_MODE): Ditto. + (VSX_MOVE_MODE): Ditto. + (VSX_REG_CLASS_P): Ditto. + (HARD_REGNO_NREGS): Instead of calling a function, use an array + lookup. + (UNITS_PER_SIMD_WORD): Add VSX support. + (MODES_TIEABLE_P): Ditto. + (STARTING_FRAME_OFFSET): Ditto. + (STACK_DYNAMIC_OFFSET): Ditto. + (EPILOGUE_USES): Ditto. + (REGNO_REG_CLASS): Move to array lookup. + (CLASS_MAX_NREGS): Ditto. + (rs6000_vector_reg_class): Add declaration. + (ADDITIONAL_REGISTER_NAMES): Add VSX names for the registers that + overlap with the floating point and Altivec registers. + + * config/rs6000/e500.h (CHECK_E500_OPTIONS): Disallow -mvsx. + + * config/rs6000/driver-rs6000.c (asm_names): New static array to + give the appropriate asm switches if -mcpu=native. + (host_detect_local_cpu): Add support for "asm". + (host_detect_local_cpu): Follow GNU code guidelines for name. + + * config/rs6000/sysv4.h (SUBTARGET_OVERRIDE_OPTIONS): Move + -mbit-word to a variable instead of being a target mask. + + * config/rs6000/sync.md (lwsync): If the assembler supports it, + emit the lwsync instruction instead of emitting the instruction as + an integer constant. + + * config/rs6000/spe.md (spe_fixuns_truncdfsi2): Rename from + fixuns_trundfsi2, move expander into rs6000.md. + + * config/rs6000/rs6000.md (cpu): Add power7. + (sel, *ptrsize): New mode attributes for 32/64-bit isel. + (logical predicate patterns): Change the single instruction + primitives that set CR0 to be fast_compare instead of compare. + (norsi*): Ditto. + (popcntwsi2): Add support for ISA 2.06 popcount instructions. + (popcntddi2): Ditto. + (popcount): Ditto. + (floating multiply/add insns): Name the floating point + multiply/add insns. + (isel_signed_): Add support for -misel on 64-bit systems. + (isel_unsigned_): Ditto. + (fixuns_trundfsi2): Move expander here from spe.md. + (smindi3): Define if we have -misel on 64-bit systems. + (smaxdi3): Ditto. + (umindi3): Ditto. + (umaxdi3): Ditto. + 2009-06-23 Anatoly Sokolov * config.gcc (avr-*-rtems*, avr-*-*): Set extra_gcc_objs and diff --git a/gcc/config.in b/gcc/config.in index adccc18..cc0202b 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -351,12 +351,23 @@ #endif -/* Define if your assembler supports popcntb field. */ +/* Define if your assembler supports popcntb instruction. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_POPCNTB #endif +/* Define if your assembler supports popcntd instruction. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_POPCNTD +#endif + +/* Define if your assembler supports lwsync instruction. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_LWSYNC +#endif + + /* Define if your assembler supports .register. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_REGISTER_PSEUDO_OP diff --git a/gcc/config/rs6000/aix53.h b/gcc/config/rs6000/aix53.h index 6172e76..b7b1eec 100644 --- a/gcc/config/rs6000/aix53.h +++ b/gcc/config/rs6000/aix53.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for IBM RS/6000 POWER running AIX V5.3. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by David Edelsohn (edelsohn@gnu.org). @@ -57,20 +57,24 @@ do { \ #undef ASM_SPEC #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)" -/* Common ASM definitions used by ASM_SPEC amongst the various targets - for handling -mcpu=xxx switches. */ +/* Common ASM definitions used by ASM_SPEC amongst the various targets for + handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to + provide the default assembler options if the user uses -mcpu=native, so if + you make changes here, make them there also. */ #undef ASM_CPU_SPEC #define ASM_CPU_SPEC \ "%{!mcpu*: %{!maix64: \ %{mpowerpc64: -mppc64} \ %{maltivec: -m970} \ %{!maltivec: %{!mpower64: %(asm_default)}}}} \ +%{mcpu=native: %(asm_cpu_native)} \ %{mcpu=power3: -m620} \ %{mcpu=power4: -mpwr4} \ %{mcpu=power5: -mpwr5} \ %{mcpu=power5+: -mpwr5x} \ %{mcpu=power6: -mpwr6} \ %{mcpu=power6x: -mpwr6} \ +%{mcpu=power7: -mpwr7} \ %{mcpu=powerpc: -mppc} \ %{mcpu=rs64a: -mppc} \ %{mcpu=603: -m603} \ diff --git a/gcc/config/rs6000/aix61.h b/gcc/config/rs6000/aix61.h index c0899d8..048486b 100644 --- a/gcc/config/rs6000/aix61.h +++ b/gcc/config/rs6000/aix61.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for IBM RS/6000 POWER running AIX V6.1. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by David Edelsohn (edelsohn@gnu.org). @@ -57,20 +57,24 @@ do { \ #undef ASM_SPEC #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)" -/* Common ASM definitions used by ASM_SPEC amongst the various targets - for handling -mcpu=xxx switches. */ +/* Common ASM definitions used by ASM_SPEC amongst the various targets for + handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to + provide the default assembler options if the user uses -mcpu=native, so if + you make changes here, make them there also. */ #undef ASM_CPU_SPEC #define ASM_CPU_SPEC \ "%{!mcpu*: %{!maix64: \ %{mpowerpc64: -mppc64} \ %{maltivec: -m970} \ %{!maltivec: %{!mpower64: %(asm_default)}}}} \ +%{mcpu=native: %(asm_cpu_native)} \ %{mcpu=power3: -m620} \ %{mcpu=power4: -mpwr4} \ %{mcpu=power5: -mpwr5} \ %{mcpu=power5+: -mpwr5x} \ %{mcpu=power6: -mpwr6} \ %{mcpu=power6x: -mpwr6} \ +%{mcpu=power7: -mpwr7} \ %{mcpu=powerpc: -mppc} \ %{mcpu=rs64a: -mppc} \ %{mcpu=603: -m603} \ diff --git a/gcc/config/rs6000/driver-rs6000.c b/gcc/config/rs6000/driver-rs6000.c index 3f5524e..11e76ea 100644 --- a/gcc/config/rs6000/driver-rs6000.c +++ b/gcc/config/rs6000/driver-rs6000.c @@ -1,5 +1,5 @@ /* Subroutines for the gcc driver. - Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -343,47 +343,156 @@ detect_processor_aix (void) #endif /* _AIX */ +/* + * Array to map -mcpu=native names to the switches passed to the assembler. + * This list mirrors the specs in ASM_CPU_SPEC, and any changes made here + * should be made there as well. + */ + +struct asm_name { + const char *cpu; + const char *asm_sw; +}; + +static const struct asm_name asm_names[] = { +#if defined (_AIX) + { "power3", "-m620" }, + { "power4", "-mpwr4" }, + { "power5", "-mpwr5" }, + { "power5+", "-mpwr5x" }, + { "power6", "-mpwr6" }, + { "power6x", "-mpwr6" }, + { "power7", "-mpwr7" }, + { "powerpc", "-mppc" }, + { "rs64a", "-mppc" }, + { "603", "-m603" }, + { "603e", "-m603" }, + { "604", "-m604" }, + { "604e", "-m604" }, + { "620", "-m620" }, + { "630", "-m620" }, + { "970", "-m970" }, + { "G5", "-m970" }, + { NULL, "\ +%{!maix64: \ +%{mpowerpc64: -mppc64} \ +%{maltivec: -m970} \ +%{!maltivec: %{!mpower64: %(asm_default)}}}" }, + +#else + { "common", "-mcom" }, + { "cell", "-mcell" }, + { "power", "-mpwr" }, + { "power2", "-mpwrx" }, + { "power3", "-mppc64" }, + { "power4", "-mpower4" }, + { "power5", "%(asm_cpu_power5)" }, + { "power5+", "%(asm_cpu_power5)" }, + { "power6", "%(asm_cpu_power6) -maltivec" }, + { "power6x", "%(asm_cpu_power6) -maltivec" }, + { "power7", "%(asm_cpu_power7)" }, + { "powerpc", "-mppc" }, + { "rios", "-mpwr" }, + { "rios1", "-mpwr" }, + { "rios2", "-mpwrx" }, + { "rsc", "-mpwr" }, + { "rsc1", "-mpwr" }, + { "rs64a", "-mppc64" }, + { "401", "-mppc" }, + { "403", "-m403" }, + { "405", "-m405" }, + { "405fp", "-m405" }, + { "440", "-m440" }, + { "440fp", "-m440" }, + { "464", "-m440" }, + { "464fp", "-m440" }, + { "505", "-mppc" }, + { "601", "-m601" }, + { "602", "-mppc" }, + { "603", "-mppc" }, + { "603e", "-mppc" }, + { "ec603e", "-mppc" }, + { "604", "-mppc" }, + { "604e", "-mppc" }, + { "620", "-mppc64" }, + { "630", "-mppc64" }, + { "740", "-mppc" }, + { "750", "-mppc" }, + { "G3", "-mppc" }, + { "7400", "-mppc -maltivec" }, + { "7450", "-mppc -maltivec" }, + { "G4", "-mppc -maltivec" }, + { "801", "-mppc" }, + { "821", "-mppc" }, + { "823", "-mppc" }, + { "860", "-mppc" }, + { "970", "-mpower4 -maltivec" }, + { "G5", "-mpower4 -maltivec" }, + { "8540", "-me500" }, + { "8548", "-me500" }, + { "e300c2", "-me300" }, + { "e300c3", "-me300" }, + { "e500mc", "-me500mc" }, + { NULL, "\ +%{mpower: %{!mpower2: -mpwr}} \ +%{mpower2: -mpwrx} \ +%{mpowerpc64*: -mppc64} \ +%{!mpowerpc64*: %{mpowerpc*: -mppc}} \ +%{mno-power: %{!mpowerpc*: -mcom}} \ +%{!mno-power: %{!mpower*: %(asm_default)}}" }, +#endif +}; + /* This will be called by the spec parser in gcc.c when it sees a %:local_cpu_detect(args) construct. Currently it will be called with either "arch" or "tune" as argument depending on if -march=native or -mtune=native is to be substituted. + Additionally it will be called with "asm" to select the appropriate flags + for the assembler. + It returns a string containing new command line parameters to be put at the place of the above two options, depending on what CPU this is executed. ARGC and ARGV are set depending on the actual arguments given in the spec. */ -const char -*host_detect_local_cpu (int argc, const char **argv) +const char * +host_detect_local_cpu (int argc, const char **argv) { const char *cpu = NULL; const char *cache = ""; const char *options = ""; bool arch; + bool assembler; + size_t i; if (argc < 1) return NULL; arch = strcmp (argv[0], "cpu") == 0; - if (!arch && strcmp (argv[0], "tune")) + assembler = (!arch && strcmp (argv[0], "asm") == 0); + if (!arch && !assembler && strcmp (argv[0], "tune")) return NULL; + if (! assembler) + { #if defined (_AIX) - cache = detect_caches_aix (); + cache = detect_caches_aix (); #elif defined (__APPLE__) - cache = detect_caches_darwin (); + cache = detect_caches_darwin (); #elif defined (__FreeBSD__) - cache = detect_caches_freebsd (); - /* FreeBSD PPC does not provide any cache information yet. */ - cache = ""; + cache = detect_caches_freebsd (); + /* FreeBSD PPC does not provide any cache information yet. */ + cache = ""; #elif defined (__linux__) - cache = detect_caches_linux (); - /* PPC Linux does not provide any cache information yet. */ - cache = ""; + cache = detect_caches_linux (); + /* PPC Linux does not provide any cache information yet. */ + cache = ""; #else - cache = ""; + cache = ""; #endif + } #if defined (_AIX) cpu = detect_processor_aix (); @@ -397,6 +506,17 @@ const char cpu = "powerpc"; #endif + if (assembler) + { + for (i = 0; i < sizeof (asm_names) / sizeof (asm_names[0]); i++) + { + if (!asm_names[i].cpu || !strcmp (asm_names[i].cpu, cpu)) + return asm_names[i].asm_sw; + } + + return NULL; + } + return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL); } @@ -404,7 +524,8 @@ const char /* If we aren't compiling with GCC we just provide a minimal default value. */ -const char *host_detect_local_cpu (int argc, const char **argv) +const char * +host_detect_local_cpu (int argc, const char **argv) { const char *cpu; bool arch; diff --git a/gcc/config/rs6000/e500.h b/gcc/config/rs6000/e500.h index 81fb472..05b20ad 100644 --- a/gcc/config/rs6000/e500.h +++ b/gcc/config/rs6000/e500.h @@ -1,5 +1,6 @@ /* Enable E500 support. - Copyright (C) 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 Free Software + Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it @@ -37,6 +38,8 @@ { \ if (TARGET_ALTIVEC) \ error ("AltiVec and E500 instructions cannot coexist"); \ + if (TARGET_VSX) \ + error ("VSX and E500 instructions cannot coexist"); \ if (TARGET_64BIT) \ error ("64-bit E500 not supported"); \ if (TARGET_HARD_FLOAT && TARGET_FPRS) \ diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index c3193dc..94d18ae 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -119,7 +119,7 @@ extern int dot_symbols; error (INVALID_32BIT, "32"); \ if (TARGET_PROFILE_KERNEL) \ { \ - target_flags &= ~MASK_PROFILE_KERNEL; \ + SET_PROFILE_KERNEL (0); \ error (INVALID_32BIT, "profile-kernel"); \ } \ } \ diff --git a/gcc/config/rs6000/linux64.opt b/gcc/config/rs6000/linux64.opt index f408eb8..1eac738 100644 --- a/gcc/config/rs6000/linux64.opt +++ b/gcc/config/rs6000/linux64.opt @@ -1,6 +1,6 @@ ; Options for 64-bit PowerPC Linux. ; -; Copyright (C) 2005, 2007 Free Software Foundation, Inc. +; Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc. ; Contributed by Aldy Hernandez . ; ; This file is part of GCC. @@ -20,5 +20,5 @@ ; . mprofile-kernel -Target Report Mask(PROFILE_KERNEL) +Target Report Var(TARGET_PROFILE_KERNEL) Call mcount for profiling before a function prologue diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index 8a39b9e..d1ab9da 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -284,6 +284,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile) builtin_define ("_ARCH_PWR6X"); if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC) builtin_define ("_ARCH_COM"); + if (TARGET_POPCNTD) + builtin_define ("_ARCH_PWR7"); if (TARGET_ALTIVEC) { builtin_define ("__ALTIVEC__"); @@ -326,6 +328,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile) /* Used by libstdc++. */ if (TARGET_NO_LWSYNC) builtin_define ("__NO_LWSYNC__"); + if (TARGET_VSX) + builtin_define ("__VSX__"); /* May be overridden by target configuration. */ RS6000_CPU_CPP_ENDIAN_BUILTINS(); diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 1b68d44..731349e 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -168,7 +168,6 @@ extern int rs6000_register_move_cost (enum machine_mode, enum reg_class, enum reg_class); extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int); extern bool rs6000_tls_referenced_p (rtx); -extern int rs6000_hard_regno_nregs (int, enum machine_mode); extern void rs6000_conditional_register_usage (void); /* Declare functions in rs6000-c.c */ @@ -187,4 +186,6 @@ const char * rs6000_xcoff_strip_dollar (const char *); void rs6000_final_prescan_insn (rtx, rtx *operand, int num_operands); extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER]; +extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES]; +extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER]; #endif /* rs6000-protos.h */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 9465c9f..0263f91 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -178,9 +178,6 @@ int rs6000_spe; /* Nonzero if we want SPE ABI extensions. */ int rs6000_spe_abi; -/* Nonzero to use isel instructions. */ -int rs6000_isel; - /* Nonzero if floating point operations are done in the GPRs. */ int rs6000_float_gprs = 0; @@ -222,12 +219,33 @@ int dot_symbols; const char *rs6000_debug_name; int rs6000_debug_stack; /* debug stack applications */ int rs6000_debug_arg; /* debug argument handling */ +int rs6000_debug_reg; /* debug register classes */ +int rs6000_debug_addr; /* debug memory addressing */ +int rs6000_debug_cost; /* debug rtx_costs */ + +/* Specify the machine mode that pointers have. After generation of rtl, the + compiler makes no further distinction between pointers and any other objects + of this machine mode. The type is unsigned since not all things that + include rs6000.h also include machmode.h. */ +unsigned rs6000_pmode; + +/* Width in bits of a pointer. */ +unsigned rs6000_pointer_size; + /* Value is TRUE if register/mode pair is acceptable. */ bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER]; -/* Built in types. */ +/* Maximum number of registers needed for a given register class and mode. */ +unsigned char rs6000_class_max_nregs[NUM_MACHINE_MODES][LIM_REG_CLASSES]; + +/* How many registers are needed for a given register and mode. */ +unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER]; +/* Map register number to register class. */ +enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER]; + +/* Built in types. */ tree rs6000_builtin_types[RS6000_BTI_MAX]; tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT]; @@ -265,7 +283,6 @@ static struct { bool altivec_abi; /* True if -mabi=altivec/no-altivec used. */ bool spe; /* True if -mspe= was used. */ bool float_gprs; /* True if -mfloat-gprs= was used. */ - bool isel; /* True if -misel was used. */ bool long_double; /* True if -mlong-double- was used. */ bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */ bool vrsave; /* True if -mvrsave was used. */ @@ -281,6 +298,14 @@ struct builtin_description const char *const name; const enum rs6000_builtins code; }; + +/* Describe the vector unit used for modes. */ +enum rs6000_vector rs6000_vector_unit[NUM_MACHINE_MODES]; +enum rs6000_vector rs6000_vector_mem[NUM_MACHINE_MODES]; +enum reg_class rs6000_vector_reg_class[NUM_MACHINE_MODES]; + +/* Describe the alignment of a vector. */ +int rs6000_vector_align[NUM_MACHINE_MODES]; /* Target cpu costs. */ @@ -744,6 +769,25 @@ struct processor_costs power6_cost = { 16, /* prefetch streams */ }; +/* Instruction costs on POWER7 processors. */ +static const +struct processor_costs power7_cost = { + COSTS_N_INSNS (2), /* mulsi */ + COSTS_N_INSNS (2), /* mulsi_const */ + COSTS_N_INSNS (2), /* mulsi_const9 */ + COSTS_N_INSNS (2), /* muldi */ + COSTS_N_INSNS (18), /* divsi */ + COSTS_N_INSNS (34), /* divdi */ + COSTS_N_INSNS (3), /* fp */ + COSTS_N_INSNS (3), /* dmul */ + COSTS_N_INSNS (13), /* sdiv */ + COSTS_N_INSNS (16), /* ddiv */ + 128, /* cache line size */ + 32, /* l1 cache */ + 256, /* l2 cache */ + 12, /* prefetch streams */ +}; + static bool rs6000_function_ok_for_sibcall (tree, tree); static const char *rs6000_invalid_within_doloop (const_rtx); @@ -1055,6 +1099,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #endif #ifndef TARGET_PROFILE_KERNEL #define TARGET_PROFILE_KERNEL 0 +#define SET_PROFILE_KERNEL(N) +#else +#define SET_PROFILE_KERNEL(N) TARGET_PROFILE_KERNEL = (N) #endif /* The VRSAVE bitmask puts bit %v0 as the most significant bit. */ @@ -1312,6 +1359,46 @@ static const struct attribute_spec rs6000_attribute_table[] = struct gcc_target targetm = TARGET_INITIALIZER; +/* Return number of consecutive hard regs needed starting at reg REGNO + to hold something of mode MODE. + This is ordinarily the length in words of a value of mode MODE + but can be less for certain modes in special long registers. + + For the SPE, GPRs are 64 bits but only 32 bits are visible in + scalar instructions. The upper 32 bits are only available to the + SIMD instructions. + + POWER and PowerPC GPRs hold 32 bits worth; + PowerPC64 GPRs and FPRs point register holds 64 bits worth. */ + +static int +rs6000_hard_regno_nregs_internal (int regno, enum machine_mode mode) +{ + unsigned HOST_WIDE_INT reg_size; + + if (FP_REGNO_P (regno)) + reg_size = UNITS_PER_FP_WORD; + + else if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode)) + reg_size = UNITS_PER_SPE_WORD; + + else if (ALTIVEC_REGNO_P (regno)) + reg_size = UNITS_PER_ALTIVEC_WORD; + + /* The value returned for SCmode in the E500 double case is 2 for + ABI compatibility; storing an SCmode value in a single register + would require function_arg and rs6000_spe_function_arg to handle + SCmode so as to pass the value correctly in a pair of + registers. */ + else if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode + && !DECIMAL_FLOAT_MODE_P (mode)) + reg_size = UNITS_PER_FP_WORD; + + else + reg_size = UNITS_PER_WORD; + + return (GET_MODE_SIZE (mode) + reg_size - 1) / reg_size; +} /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */ @@ -1356,16 +1443,267 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode) return GET_MODE_SIZE (mode) <= UNITS_PER_WORD; } -/* Initialize rs6000_hard_regno_mode_ok_p table. */ +/* Print interesting facts about registers. */ static void -rs6000_init_hard_regno_mode_ok (void) +rs6000_debug_reg_print (int first_regno, int last_regno, const char *reg_name) { int r, m; + for (r = first_regno; r <= last_regno; ++r) + { + const char *comma = ""; + int len; + + if (first_regno == last_regno) + fprintf (stderr, "%s:\t", reg_name); + else + fprintf (stderr, "%s%d:\t", reg_name, r - first_regno); + + len = 8; + for (m = 0; m < NUM_MACHINE_MODES; ++m) + if (rs6000_hard_regno_mode_ok_p[m][r] && rs6000_hard_regno_nregs[m][r]) + { + if (len > 70) + { + fprintf (stderr, ",\n\t"); + len = 8; + comma = ""; + } + + if (rs6000_hard_regno_nregs[m][r] > 1) + len += fprintf (stderr, "%s%s/%d", comma, GET_MODE_NAME (m), + rs6000_hard_regno_nregs[m][r]); + else + len += fprintf (stderr, "%s%s", comma, GET_MODE_NAME (m)); + + comma = ", "; + } + + if (call_used_regs[r]) + { + if (len > 70) + { + fprintf (stderr, ",\n\t"); + len = 8; + comma = ""; + } + + len += fprintf (stderr, "%s%s", comma, "call-used"); + comma = ", "; + } + + if (fixed_regs[r]) + { + if (len > 70) + { + fprintf (stderr, ",\n\t"); + len = 8; + comma = ""; + } + + len += fprintf (stderr, "%s%s", comma, "fixed"); + comma = ", "; + } + + if (len > 70) + { + fprintf (stderr, ",\n\t"); + comma = ""; + } + + fprintf (stderr, "%sregno = %d\n", comma, r); + } +} + +/* Map enum rs6000_vector to string. */ +static const char * +rs6000_debug_vector_unit[] = { + "none", + "altivec", + "vsx", + "paired", + "spe", + "other" +}; + +/* Initialize the various global tables that are based on register size. */ +static void +rs6000_init_hard_regno_mode_ok (void) +{ + int r, m, c; + bool float_p = (TARGET_HARD_FLOAT && TARGET_FPRS); + + /* Precalculate REGNO_REG_CLASS. */ + rs6000_regno_regclass[0] = GENERAL_REGS; + for (r = 1; r < 32; ++r) + rs6000_regno_regclass[r] = BASE_REGS; + + for (r = 32; r < 64; ++r) + rs6000_regno_regclass[r] = FLOAT_REGS; + + for (r = 64; r < FIRST_PSEUDO_REGISTER; ++r) + rs6000_regno_regclass[r] = NO_REGS; + + for (r = FIRST_ALTIVEC_REGNO; r <= LAST_ALTIVEC_REGNO; ++r) + rs6000_regno_regclass[r] = ALTIVEC_REGS; + + rs6000_regno_regclass[CR0_REGNO] = CR0_REGS; + for (r = CR1_REGNO; r <= CR7_REGNO; ++r) + rs6000_regno_regclass[r] = CR_REGS; + + rs6000_regno_regclass[MQ_REGNO] = MQ_REGS; + rs6000_regno_regclass[LR_REGNO] = LINK_REGS; + rs6000_regno_regclass[CTR_REGNO] = CTR_REGS; + rs6000_regno_regclass[XER_REGNO] = XER_REGS; + rs6000_regno_regclass[VRSAVE_REGNO] = VRSAVE_REGS; + rs6000_regno_regclass[VSCR_REGNO] = VRSAVE_REGS; + rs6000_regno_regclass[SPE_ACC_REGNO] = SPE_ACC_REGS; + rs6000_regno_regclass[SPEFSCR_REGNO] = SPEFSCR_REGS; + rs6000_regno_regclass[ARG_POINTER_REGNUM] = BASE_REGS; + rs6000_regno_regclass[FRAME_POINTER_REGNUM] = BASE_REGS; + + /* Precalculate vector information, this must be set up before the + rs6000_hard_regno_nregs_internal below. */ + for (m = 0; m < NUM_MACHINE_MODES; ++m) + { + rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE; + rs6000_vector_reg_class[m] = NO_REGS; + } + + /* V4SF mode, Altivec only. */ + if (float_p && TARGET_ALTIVEC) + { + rs6000_vector_unit[V4SFmode] = VECTOR_ALTIVEC; + rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC; + rs6000_vector_align[V4SFmode] = 128; + } + + /* V16QImode, V8HImode, V4SImode are Altivec only. */ + if (TARGET_ALTIVEC) + { + rs6000_vector_unit[V4SImode] = VECTOR_ALTIVEC; + rs6000_vector_unit[V8HImode] = VECTOR_ALTIVEC; + rs6000_vector_unit[V16QImode] = VECTOR_ALTIVEC; + + rs6000_vector_reg_class[V16QImode] = ALTIVEC_REGS; + rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS; + rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS; + + rs6000_vector_mem[V4SImode] = VECTOR_ALTIVEC; + rs6000_vector_mem[V8HImode] = VECTOR_ALTIVEC; + rs6000_vector_mem[V16QImode] = VECTOR_ALTIVEC; + rs6000_vector_align[V4SImode] = 128; + rs6000_vector_align[V8HImode] = 128; + rs6000_vector_align[V16QImode] = 128; + } + + /* V2DImode, prefer vsx over altivec, since the main use will be for + vectorized floating point conversions. */ + if (TARGET_ALTIVEC) + { + rs6000_vector_mem[V2DImode] = VECTOR_ALTIVEC; + rs6000_vector_unit[V2DImode] = VECTOR_NONE; + rs6000_vector_reg_class[V2DImode] = ALTIVEC_REGS; + rs6000_vector_align[V2DImode] = 128; + } + + /* TODO add SPE and paired floating point vector support. */ + + /* Set the VSX register classes. */ + rs6000_vector_reg_class[V4SFmode] + = (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) + ? ALTIVEC_REGS + : NO_REGS); + + rs6000_vector_reg_class[V2DFmode] = NO_REGS; + + rs6000_vector_reg_class[DFmode] = (!float_p ? NO_REGS : FLOAT_REGS); + + /* Precalculate HARD_REGNO_NREGS. */ + for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r) + for (m = 0; m < NUM_MACHINE_MODES; ++m) + rs6000_hard_regno_nregs[m][r] + = rs6000_hard_regno_nregs_internal (r, (enum machine_mode)m); + + /* Precalculate HARD_REGNO_MODE_OK. */ for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r) for (m = 0; m < NUM_MACHINE_MODES; ++m) - if (rs6000_hard_regno_mode_ok (r, (enum machine_mode) m)) + if (rs6000_hard_regno_mode_ok (r, (enum machine_mode)m)) rs6000_hard_regno_mode_ok_p[m][r] = true; + + /* Precalculate CLASS_MAX_NREGS sizes. */ + for (c = 0; c < LIM_REG_CLASSES; ++c) + { + int reg_size; + + if (c == ALTIVEC_REGS) + reg_size = UNITS_PER_ALTIVEC_WORD; + + else if (c == FLOAT_REGS) + reg_size = UNITS_PER_FP_WORD; + + else + reg_size = UNITS_PER_WORD; + + for (m = 0; m < NUM_MACHINE_MODES; ++m) + rs6000_class_max_nregs[m][c] + = (GET_MODE_SIZE (m) + reg_size - 1) / reg_size; + } + + if (TARGET_E500_DOUBLE) + rs6000_class_max_nregs[DFmode][GENERAL_REGS] = 1; + + if (TARGET_DEBUG_REG) + { + const char *nl = (const char *)0; + + fprintf (stderr, "Register information: (last virtual reg = %d)\n", + LAST_VIRTUAL_REGISTER); + rs6000_debug_reg_print (0, 31, "gr"); + rs6000_debug_reg_print (32, 63, "fp"); + rs6000_debug_reg_print (FIRST_ALTIVEC_REGNO, + LAST_ALTIVEC_REGNO, + "vs"); + rs6000_debug_reg_print (LR_REGNO, LR_REGNO, "lr"); + rs6000_debug_reg_print (CTR_REGNO, CTR_REGNO, "ctr"); + rs6000_debug_reg_print (CR0_REGNO, CR7_REGNO, "cr"); + rs6000_debug_reg_print (MQ_REGNO, MQ_REGNO, "mq"); + rs6000_debug_reg_print (XER_REGNO, XER_REGNO, "xer"); + rs6000_debug_reg_print (VRSAVE_REGNO, VRSAVE_REGNO, "vrsave"); + rs6000_debug_reg_print (VSCR_REGNO, VSCR_REGNO, "vscr"); + rs6000_debug_reg_print (SPE_ACC_REGNO, SPE_ACC_REGNO, "spe_a"); + rs6000_debug_reg_print (SPEFSCR_REGNO, SPEFSCR_REGNO, "spe_f"); + + fprintf (stderr, + "\n" + "V16QI reg_class = %s\n" + "V8HI reg_class = %s\n" + "V4SI reg_class = %s\n" + "V2DI reg_class = %s\n" + "V4SF reg_class = %s\n" + "V2DF reg_class = %s\n" + "DF reg_class = %s\n\n", + reg_class_names[rs6000_vector_reg_class[V16QImode]], + reg_class_names[rs6000_vector_reg_class[V8HImode]], + reg_class_names[rs6000_vector_reg_class[V4SImode]], + reg_class_names[rs6000_vector_reg_class[V2DImode]], + reg_class_names[rs6000_vector_reg_class[V4SFmode]], + reg_class_names[rs6000_vector_reg_class[V2DFmode]], + reg_class_names[rs6000_vector_reg_class[DFmode]]); + + for (m = 0; m < NUM_MACHINE_MODES; ++m) + if (rs6000_vector_unit[m] || rs6000_vector_mem[m]) + { + nl = "\n"; + fprintf (stderr, "Vector mode: %-5s arithmetic: %-8s move: %-8s\n", + GET_MODE_NAME (m), + rs6000_debug_vector_unit[ rs6000_vector_unit[m] ], + rs6000_debug_vector_unit[ rs6000_vector_mem[m] ]); + } + + if (nl) + fputs (nl, stderr); + } } #if TARGET_MACHO @@ -1495,12 +1833,15 @@ rs6000_override_options (const char *default_cpu) {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, - {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN}, + {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN + | MASK_ISEL}, /* 8548 has a dummy entry for now. */ - {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN}, + {"8548", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_STRICT_ALIGN + | MASK_ISEL}, {"e300c2", PROCESSOR_PPCE300C2, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"e300c3", PROCESSOR_PPCE300C3, POWERPC_BASE_MASK}, - {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT}, + {"e500mc", PROCESSOR_PPCE500MC, POWERPC_BASE_MASK | MASK_PPC_GFXOPT + | MASK_ISEL}, {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"970", PROCESSOR_POWER4, POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, @@ -1533,9 +1874,10 @@ rs6000_override_options (const char *default_cpu) POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_MFPGPR}, - {"power7", PROCESSOR_POWER5, + {"power7", PROCESSOR_POWER7, POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF - | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP}, + | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD + | MASK_VSX}, /* Don't add MASK_ISEL by default */ {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK}, {"powerpc64", PROCESSOR_POWERPC64, POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, @@ -1562,9 +1904,22 @@ rs6000_override_options (const char *default_cpu) POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW - | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP) + | MASK_DLMZB | MASK_CMPB | MASK_MFPGPR | MASK_DFP + | MASK_POPCNTD | MASK_VSX | MASK_ISEL) }; + /* Set the pointer size. */ + if (TARGET_POWERPC64) + { + rs6000_pmode = (int)DImode; + rs6000_pointer_size = 64; + } + else + { + rs6000_pmode = (int)SImode; + rs6000_pointer_size = 32; + } + set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT; #ifdef OS_MISSING_POWERPC64 if (OS_MISSING_POWERPC64) @@ -1607,10 +1962,6 @@ rs6000_override_options (const char *default_cpu) } } - if ((TARGET_E500 || rs6000_cpu == PROCESSOR_PPCE500MC) - && !rs6000_explicit_options.isel) - rs6000_isel = 1; - if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3 || rs6000_cpu == PROCESSOR_PPCE500MC) { @@ -1655,15 +2006,55 @@ rs6000_override_options (const char *default_cpu) } } + /* Add some warnings for VSX. Enable -maltivec unless the user explicitly + used -mno-altivec */ + if (TARGET_VSX) + { + const char *msg = NULL; + if (!TARGET_HARD_FLOAT || !TARGET_FPRS + || !TARGET_SINGLE_FLOAT || !TARGET_DOUBLE_FLOAT) + { + if (target_flags_explicit & MASK_VSX) + msg = N_("-mvsx requires hardware floating point"); + else + target_flags &= ~ MASK_VSX; + } + else if (TARGET_PAIRED_FLOAT) + msg = N_("-mvsx and -mpaired are incompatible"); + /* The hardware will allow VSX and little endian, but until we make sure + things like vector select, etc. work don't allow VSX on little endian + systems at this point. */ + else if (!BYTES_BIG_ENDIAN) + msg = N_("-mvsx used with little endian code"); + else if (TARGET_AVOID_XFORM > 0) + msg = N_("-mvsx needs indexed addressing"); + + if (msg) + { + warning (0, msg); + target_flags &= ~ MASK_VSX; + } + else if (TARGET_VSX && !TARGET_ALTIVEC + && (target_flags_explicit & MASK_ALTIVEC) == 0) + target_flags |= MASK_ALTIVEC; + } + /* Set debug flags */ if (rs6000_debug_name) { if (! strcmp (rs6000_debug_name, "all")) - rs6000_debug_stack = rs6000_debug_arg = 1; + rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg + = rs6000_debug_addr = rs6000_debug_cost = 1; else if (! strcmp (rs6000_debug_name, "stack")) rs6000_debug_stack = 1; else if (! strcmp (rs6000_debug_name, "arg")) rs6000_debug_arg = 1; + else if (! strcmp (rs6000_debug_name, "reg")) + rs6000_debug_reg = 1; + else if (! strcmp (rs6000_debug_name, "addr")) + rs6000_debug_addr = 1; + else if (! strcmp (rs6000_debug_name, "cost")) + rs6000_debug_cost = 1; else error ("unknown -mdebug-%s switch", rs6000_debug_name); } @@ -1690,7 +2081,7 @@ rs6000_override_options (const char *default_cpu) #endif /* Enable Altivec ABI for AIX -maltivec. */ - if (TARGET_XCOFF && TARGET_ALTIVEC) + if (TARGET_XCOFF && (TARGET_ALTIVEC || TARGET_VSX)) rs6000_altivec_abi = 1; /* The AltiVec ABI is the default for PowerPC-64 GNU/Linux. For @@ -1699,7 +2090,7 @@ rs6000_override_options (const char *default_cpu) if (TARGET_ELF) { if (!rs6000_explicit_options.altivec_abi - && (TARGET_64BIT || TARGET_ALTIVEC)) + && (TARGET_64BIT || TARGET_ALTIVEC || TARGET_VSX)) rs6000_altivec_abi = 1; /* Enable VRSAVE for AltiVec ABI, unless explicitly overridden. */ @@ -1754,8 +2145,8 @@ rs6000_override_options (const char *default_cpu) rs6000_spe = 0; if (!rs6000_explicit_options.float_gprs) rs6000_float_gprs = 0; - if (!rs6000_explicit_options.isel) - rs6000_isel = 0; + if (!(target_flags_explicit & MASK_ISEL)) + target_flags &= ~MASK_ISEL; } /* Detect invalid option combinations with E500. */ @@ -1763,13 +2154,15 @@ rs6000_override_options (const char *default_cpu) rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4 && rs6000_cpu != PROCESSOR_POWER5 - && rs6000_cpu != PROCESSOR_POWER6 + && rs6000_cpu != PROCESSOR_POWER6 + && rs6000_cpu != PROCESSOR_POWER7 && rs6000_cpu != PROCESSOR_CELL); rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4 || rs6000_cpu == PROCESSOR_POWER5); rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4 - || rs6000_cpu == PROCESSOR_POWER5 - || rs6000_cpu == PROCESSOR_POWER6); + || rs6000_cpu == PROCESSOR_POWER5 + || rs6000_cpu == PROCESSOR_POWER6 + || rs6000_cpu == PROCESSOR_POWER7); rs6000_sched_restricted_insns_priority = (rs6000_sched_groups ? 1 : 0); @@ -1966,6 +2359,10 @@ rs6000_override_options (const char *default_cpu) rs6000_cost = &power6_cost; break; + case PROCESSOR_POWER7: + rs6000_cost = &power7_cost; + break; + default: gcc_unreachable (); } @@ -2016,7 +2413,7 @@ rs6000_override_options (const char *default_cpu) static tree rs6000_builtin_mask_for_load (void) { - if (TARGET_ALTIVEC) + if (TARGET_ALTIVEC || TARGET_VSX) return altivec_builtin_mask_for_load; else return 0; @@ -2246,6 +2643,7 @@ static bool rs6000_handle_option (size_t code, const char *arg, int value) { enum fpu_type_t fpu_type = FPU_NONE; + int isel; switch (code) { @@ -2353,14 +2751,14 @@ rs6000_handle_option (size_t code, const char *arg, int value) rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE)); break; - case OPT_misel: - rs6000_explicit_options.isel = true; - rs6000_isel = value; - break; - case OPT_misel_: - rs6000_explicit_options.isel = true; - rs6000_parse_yes_no_option ("isel", arg, &(rs6000_isel)); + target_flags_explicit |= MASK_ISEL; + isel = 0; + rs6000_parse_yes_no_option ("isel", arg, &isel); + if (isel) + target_flags |= MASK_ISEL; + else + target_flags &= ~MASK_ISEL; break; case OPT_mspe: @@ -4584,43 +4982,6 @@ rs6000_offsettable_memref_p (rtx op) return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1); } -/* Return number of consecutive hard regs needed starting at reg REGNO - to hold something of mode MODE. - This is ordinarily the length in words of a value of mode MODE - but can be less for certain modes in special long registers. - - For the SPE, GPRs are 64 bits but only 32 bits are visible in - scalar instructions. The upper 32 bits are only available to the - SIMD instructions. - - POWER and PowerPC GPRs hold 32 bits worth; - PowerPC64 GPRs and FPRs point register holds 64 bits worth. */ - -int -rs6000_hard_regno_nregs (int regno, enum machine_mode mode) -{ - if (FP_REGNO_P (regno)) - return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD; - - if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode)) - return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD; - - if (ALTIVEC_REGNO_P (regno)) - return - (GET_MODE_SIZE (mode) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD; - - /* The value returned for SCmode in the E500 double case is 2 for - ABI compatibility; storing an SCmode value in a single register - would require function_arg and rs6000_spe_function_arg to handle - SCmode so as to pass the value correctly in a pair of - registers. */ - if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode - && !DECIMAL_FLOAT_MODE_P (mode)) - return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD; - - return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; -} - /* Change register usage conditional on target flags. */ void rs6000_conditional_register_usage (void) @@ -4685,14 +5046,14 @@ rs6000_conditional_register_usage (void) = call_really_used_regs[14] = 1; } - if (!TARGET_ALTIVEC) + if (!TARGET_ALTIVEC && !TARGET_VSX) { for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i) fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1; call_really_used_regs[VRSAVE_REGNO] = 1; } - if (TARGET_ALTIVEC) + if (TARGET_ALTIVEC || TARGET_VSX) global_regs[VSCR_REGNO] = 1; if (TARGET_ALTIVEC_ABI) @@ -5310,10 +5671,10 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) && TARGET_HARD_FLOAT && TARGET_FPRS) /* Nonzero if we can use an AltiVec register to pass this arg. */ -#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \ - (ALTIVEC_VECTOR_MODE (MODE) \ - && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \ - && TARGET_ALTIVEC_ABI \ +#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE,NAMED) \ + ((ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)) \ + && (CUM)->vregno <= ALTIVEC_ARG_MAX_REG \ + && TARGET_ALTIVEC_ABI \ && (NAMED)) /* Return a nonzero value to say to return the function value in @@ -5554,7 +5915,7 @@ function_arg_boundary (enum machine_mode mode, tree type) && int_size_in_bytes (type) >= 8 && int_size_in_bytes (type) < 16)) return 64; - else if (ALTIVEC_VECTOR_MODE (mode) + else if ((ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode)) || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) >= 16)) return 128; @@ -5700,6 +6061,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, if (TARGET_ALTIVEC_ABI && (ALTIVEC_VECTOR_MODE (mode) + || VSX_VECTOR_MODE (mode) || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) == 16))) { @@ -6294,6 +6656,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, return gen_rtx_REG (mode, cum->vregno); else if (TARGET_ALTIVEC_ABI && (ALTIVEC_VECTOR_MODE (mode) + || VSX_VECTOR_MODE (mode) || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) == 16))) { @@ -7192,7 +7555,8 @@ def_builtin (int mask, const char *name, tree type, int code) if ((mask & target_flags) || TARGET_PAIRED_FLOAT) { if (rs6000_builtin_decls[code]) - abort (); + fatal_error ("internal error: builtin function to %s already processed.", + name); rs6000_builtin_decls[code] = add_builtin_function (name, type, code, BUILT_IN_MD, @@ -9342,7 +9706,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return ret; } - gcc_assert (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT); + gcc_assert (TARGET_ALTIVEC || TARGET_VSX || TARGET_SPE || TARGET_PAIRED_FLOAT); /* Handle simple unary operations. */ d = (struct builtin_description *) bdesc_1arg; @@ -13770,9 +14134,9 @@ static int rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) { rtx condition_rtx, cr; + enum machine_mode mode = GET_MODE (XEXP (op, 0)); - /* All isel implementations thus far are 32-bits. */ - if (GET_MODE (XEXP (op, 0)) != SImode) + if (mode != SImode && (!TARGET_POWERPC64 || mode != DImode)) return 0; /* We still have to do the compare, because isel doesn't do a @@ -13781,12 +14145,24 @@ rs6000_emit_int_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond) condition_rtx = rs6000_generate_compare (op, SImode); cr = XEXP (condition_rtx, 0); - if (GET_MODE (cr) == CCmode) - emit_insn (gen_isel_signed (dest, condition_rtx, - true_cond, false_cond, cr)); + if (mode == SImode) + { + if (GET_MODE (cr) == CCmode) + emit_insn (gen_isel_signed_si (dest, condition_rtx, + true_cond, false_cond, cr)); + else + emit_insn (gen_isel_unsigned_si (dest, condition_rtx, + true_cond, false_cond, cr)); + } else - emit_insn (gen_isel_unsigned (dest, condition_rtx, - true_cond, false_cond, cr)); + { + if (GET_MODE (cr) == CCmode) + emit_insn (gen_isel_signed_di (dest, condition_rtx, + true_cond, false_cond, cr)); + else + emit_insn (gen_isel_unsigned_di (dest, condition_rtx, + true_cond, false_cond, cr)); + } return 1; } diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index c500600..f4a5401 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -77,14 +77,16 @@ #define ASM_CPU_POWER6_SPEC "-mpower4 -maltivec" #endif -#ifdef HAVE_AS_VSX +#ifdef HAVE_AS_POPCNTD #define ASM_CPU_POWER7_SPEC "-mpower7" #else #define ASM_CPU_POWER7_SPEC "-mpower4 -maltivec" #endif -/* Common ASM definitions used by ASM_SPEC among the various targets - for handling -mcpu=xxx switches. */ +/* Common ASM definitions used by ASM_SPEC among the various targets for + handling -mcpu=xxx switches. There is a parallel list in driver-rs6000.c to + provide the default assembler options if the user uses -mcpu=native, so if + you make changes here, make them also there. */ #define ASM_CPU_SPEC \ "%{!mcpu*: \ %{mpower: %{!mpower2: -mpwr}} \ @@ -93,6 +95,7 @@ %{!mpowerpc64*: %{mpowerpc*: -mppc}} \ %{mno-power: %{!mpowerpc*: -mcom}} \ %{!mno-power: %{!mpower*: %(asm_default)}}} \ +%{mcpu=native: %(asm_cpu_native)} \ %{mcpu=common: -mcom} \ %{mcpu=cell: -mcell} \ %{mcpu=power: -mpwr} \ @@ -168,6 +171,7 @@ #define EXTRA_SPECS \ { "cpp_default", CPP_DEFAULT_SPEC }, \ { "asm_cpu", ASM_CPU_SPEC }, \ + { "asm_cpu_native", ASM_CPU_NATIVE_SPEC }, \ { "asm_default", ASM_DEFAULT_SPEC }, \ { "cc1_cpu", CC1_CPU_SPEC }, \ { "asm_cpu_power5", ASM_CPU_POWER5_SPEC }, \ @@ -184,6 +188,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define EXTRA_SPEC_FUNCTIONS \ { "local_cpu_detect", host_detect_local_cpu }, #define HAVE_LOCAL_CPU_DETECT +#define ASM_CPU_NATIVE_SPEC "%:local_cpu_detect(asm)" + +#else +#define ASM_CPU_NATIVE_SPEC "%(asm_default)" #endif #ifndef CC1_CPU_SPEC @@ -245,6 +253,22 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define TARGET_DFP 0 #endif +/* Define TARGET_POPCNTD if the target assembler does not support the + popcount word and double word instructions. */ + +#ifndef HAVE_AS_POPCNTD +#undef TARGET_POPCNTD +#define TARGET_POPCNTD 0 +#endif + +/* Define TARGET_LWSYNC_INSTRUCTION if the assembler knows about lwsync. If + not, generate the lwsync code as an integer constant. */ +#ifdef HAVE_AS_LWSYNC +#define TARGET_LWSYNC_INSTRUCTION 1 +#else +#define TARGET_LWSYNC_INSTRUCTION 0 +#endif + /* Define TARGET_TLS_MARKERS if the target assembler does not support arg markers for __tls_get_addr calls. */ #ifndef HAVE_AS_TLS_MARKERS @@ -309,6 +333,7 @@ enum processor_type PROCESSOR_POWER4, PROCESSOR_POWER5, PROCESSOR_POWER6, + PROCESSOR_POWER7, PROCESSOR_CELL }; @@ -392,9 +417,15 @@ extern struct rs6000_cpu_select rs6000_select[]; extern const char *rs6000_debug_name; /* Name for -mdebug-xxxx option */ extern int rs6000_debug_stack; /* debug stack applications */ extern int rs6000_debug_arg; /* debug argument handling */ +extern int rs6000_debug_reg; /* debug register handling */ +extern int rs6000_debug_addr; /* debug memory addressing */ +extern int rs6000_debug_cost; /* debug rtx_costs */ #define TARGET_DEBUG_STACK rs6000_debug_stack #define TARGET_DEBUG_ARG rs6000_debug_arg +#define TARGET_DEBUG_REG rs6000_debug_reg +#define TARGET_DEBUG_ADDR rs6000_debug_addr +#define TARGET_DEBUG_COST rs6000_debug_cost extern const char *rs6000_traceback_name; /* Type of traceback table. */ @@ -405,13 +436,65 @@ extern int rs6000_ieeequad; extern int rs6000_altivec_abi; extern int rs6000_spe_abi; extern int rs6000_spe; -extern int rs6000_isel; extern int rs6000_float_gprs; extern int rs6000_alignment_flags; extern const char *rs6000_sched_insert_nops_str; extern enum rs6000_nop_insertion rs6000_sched_insert_nops; extern int rs6000_xilinx_fpu; +/* Describe which vector unit to use for a given machine mode. */ +enum rs6000_vector { + VECTOR_NONE, /* Type is not a vector or not supported */ + VECTOR_ALTIVEC, /* Use altivec for vector processing */ + VECTOR_VSX, /* Use VSX for vector processing */ + VECTOR_PAIRED, /* Use paired floating point for vectors */ + VECTOR_SPE, /* Use SPE for vector processing */ + VECTOR_OTHER /* Some other vector unit */ +}; + +extern enum rs6000_vector rs6000_vector_unit[]; + +#define VECTOR_UNIT_NONE_P(MODE) \ + (rs6000_vector_unit[(MODE)] == VECTOR_NONE) + +#define VECTOR_UNIT_VSX_P(MODE) \ + (rs6000_vector_unit[(MODE)] == VECTOR_VSX) + +#define VECTOR_UNIT_ALTIVEC_P(MODE) \ + (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC) + +#define VECTOR_UNIT_ALTIVEC_OR_VSX_P(MODE) \ + (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC \ + || rs6000_vector_unit[(MODE)] == VECTOR_VSX) + +/* Describe whether to use VSX loads or Altivec loads. For now, just use the + same unit as the vector unit we are using, but we may want to migrate to + using VSX style loads even for types handled by altivec. */ +extern enum rs6000_vector rs6000_vector_mem[]; + +#define VECTOR_MEM_NONE_P(MODE) \ + (rs6000_vector_mem[(MODE)] == VECTOR_NONE) + +#define VECTOR_MEM_VSX_P(MODE) \ + (rs6000_vector_mem[(MODE)] == VECTOR_VSX) + +#define VECTOR_MEM_ALTIVEC_P(MODE) \ + (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC) + +#define VECTOR_MEM_ALTIVEC_OR_VSX_P(MODE) \ + (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC \ + || rs6000_vector_mem[(MODE)] == VECTOR_VSX) + +/* Return the alignment of a given vector type, which is set based on the + vector unit use. VSX for instance can load 32 or 64 bit aligned words + without problems, while Altivec requires 128-bit aligned vectors. */ +extern int rs6000_vector_align[]; + +#define VECTOR_ALIGN(MODE) \ + ((rs6000_vector_align[(MODE)] != 0) \ + ? rs6000_vector_align[(MODE)] \ + : (int)GET_MODE_BITSIZE ((MODE))) + /* Alignment options for fields in structures for sub-targets following AIX-like ABI. ALIGN_POWER word-aligns FP doubles (default AIX ABI). @@ -432,11 +515,12 @@ extern int rs6000_xilinx_fpu; #define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128) #define TARGET_IEEEQUAD rs6000_ieeequad #define TARGET_ALTIVEC_ABI rs6000_altivec_abi +#define TARGET_LDBRX (TARGET_POPCNTD || rs6000_cpu == PROCESSOR_CELL) #define TARGET_SPE_ABI 0 #define TARGET_SPE 0 #define TARGET_E500 0 -#define TARGET_ISEL rs6000_isel +#define TARGET_ISEL64 (TARGET_ISEL && TARGET_POWERPC64) #define TARGET_FPRS 1 #define TARGET_E500_SINGLE 0 #define TARGET_E500_DOUBLE 0 @@ -534,6 +618,7 @@ extern int rs6000_xilinx_fpu; #endif #define UNITS_PER_FP_WORD 8 #define UNITS_PER_ALTIVEC_WORD 16 +#define UNITS_PER_VSX_WORD 16 #define UNITS_PER_SPE_WORD 8 #define UNITS_PER_PAIRED_WORD 8 @@ -598,14 +683,16 @@ extern int rs6000_xilinx_fpu; /* Width in bits of a pointer. See also the macro `Pmode' defined below. */ -#define POINTER_SIZE (TARGET_32BIT ? 32 : 64) +extern unsigned rs6000_pointer_size; +#define POINTER_SIZE rs6000_pointer_size /* Allocation boundary (in *bits*) for storing arguments in argument list. */ #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64) /* Boundary (in *bits*) on which stack pointer should be aligned. */ -#define STACK_BOUNDARY \ - ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI) ? 64 : 128) +#define STACK_BOUNDARY \ + ((TARGET_32BIT && !TARGET_ALTIVEC && !TARGET_ALTIVEC_ABI && !TARGET_VSX) \ + ? 64 : 128) /* Allocation boundary (in *bits*) for the code of a function. */ #define FUNCTION_BOUNDARY 32 @@ -617,10 +704,11 @@ extern int rs6000_xilinx_fpu; local store. TYPE is the data type, and ALIGN is the alignment that the object would ordinarily have. */ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \ - ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \ + (((TARGET_ALTIVEC || TARGET_VSX) \ + && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \ (TARGET_E500_DOUBLE \ - && TYPE_MODE (TYPE) == DFmode) ? 64 : \ - ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \ + && TYPE_MODE (TYPE) == DFmode) ? 64 : \ + ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \ && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \ && TREE_CODE (TYPE) == VECTOR_TYPE \ && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN) @@ -678,15 +766,17 @@ extern int rs6000_xilinx_fpu; /* Define this macro to be the value 1 if unaligned accesses have a cost many times greater than aligned accesses, for example if they are emulated in a trap handler. */ -/* Altivec vector memory instructions simply ignore the low bits; SPE - vector memory instructions trap on unaligned accesses. */ +/* Altivec vector memory instructions simply ignore the low bits; SPE vector + memory instructions trap on unaligned accesses; VSX memory instructions are + aligned to 4 or 8 bytes. */ #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) \ (STRICT_ALIGNMENT \ || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \ || (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode \ || (MODE) == DImode) \ && (ALIGN) < 32) \ - || (VECTOR_MODE_P ((MODE)) && (ALIGN) < GET_MODE_BITSIZE ((MODE)))) + || (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE)))) + /* Standard register usage. */ @@ -913,16 +1003,49 @@ extern int rs6000_xilinx_fpu; /* True if register is an AltiVec register. */ #define ALTIVEC_REGNO_P(N) ((N) >= FIRST_ALTIVEC_REGNO && (N) <= LAST_ALTIVEC_REGNO) +/* True if register is a VSX register. */ +#define VSX_REGNO_P(N) (FP_REGNO_P (N) || ALTIVEC_REGNO_P (N)) + +/* Alternate name for any vector register supporting floating point, no matter + which instruction set(s) are available. */ +#define VFLOAT_REGNO_P(N) \ + (ALTIVEC_REGNO_P (N) || (TARGET_VSX && FP_REGNO_P (N))) + +/* Alternate name for any vector register supporting integer, no matter which + instruction set(s) are available. */ +#define VINT_REGNO_P(N) ALTIVEC_REGNO_P (N) + +/* Alternate name for any vector register supporting logical operations, no + matter which instruction set(s) are available. */ +#define VLOGICAL_REGNO_P(N) VFLOAT_REGNO_P (N) + /* Return number of consecutive hard regs needed starting at reg REGNO to hold something of mode MODE. */ -#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs ((REGNO), (MODE)) +#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs[(MODE)][(REGNO)] #define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \ ((TARGET_32BIT && TARGET_POWERPC64 \ && (GET_MODE_SIZE (MODE) > 4) \ && INT_REGNO_P (REGNO)) ? 1 : 0) +#define VSX_VECTOR_MODE(MODE) \ + ((MODE) == V4SFmode \ + || (MODE) == V2DFmode) \ + +#define VSX_SCALAR_MODE(MODE) \ + ((MODE) == DFmode) + +#define VSX_MODE(MODE) \ + (VSX_VECTOR_MODE (MODE) \ + || VSX_SCALAR_MODE (MODE)) + +#define VSX_MOVE_MODE(MODE) \ + (VSX_VECTOR_MODE (MODE) \ + || VSX_SCALAR_MODE (MODE) \ + || ALTIVEC_VECTOR_MODE (MODE) \ + || (MODE) == TImode) + #define ALTIVEC_VECTOR_MODE(MODE) \ ((MODE) == V16QImode \ || (MODE) == V8HImode \ @@ -938,10 +1061,12 @@ extern int rs6000_xilinx_fpu; #define PAIRED_VECTOR_MODE(MODE) \ ((MODE) == V2SFmode) -#define UNITS_PER_SIMD_WORD(MODE) \ - (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \ - : (TARGET_SPE ? UNITS_PER_SPE_WORD : (TARGET_PAIRED_FLOAT ? \ - UNITS_PER_PAIRED_WORD : UNITS_PER_WORD))) +#define UNITS_PER_SIMD_WORD(MODE) \ + (TARGET_VSX ? UNITS_PER_VSX_WORD \ + : (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \ + : (TARGET_SPE ? UNITS_PER_SPE_WORD \ + : (TARGET_PAIRED_FLOAT ? UNITS_PER_PAIRED_WORD \ + : UNITS_PER_WORD)))) /* Value is TRUE if hard register REGNO can hold a value of machine-mode MODE. */ @@ -969,6 +1094,10 @@ extern int rs6000_xilinx_fpu; ? ALTIVEC_VECTOR_MODE (MODE2) \ : ALTIVEC_VECTOR_MODE (MODE2) \ ? ALTIVEC_VECTOR_MODE (MODE1) \ + : VSX_VECTOR_MODE (MODE1) \ + ? VSX_VECTOR_MODE (MODE2) \ + : VSX_VECTOR_MODE (MODE2) \ + ? VSX_VECTOR_MODE (MODE1) \ : 1) /* Post-reload, we can't use any new AltiVec registers, as we already @@ -1054,9 +1183,10 @@ extern int rs6000_xilinx_fpu; For any two classes, it is very desirable that there be another class that represents their union. */ -/* The RS/6000 has three types of registers, fixed-point, floating-point, - and condition registers, plus three special registers, MQ, CTR, and the - link register. AltiVec adds a vector register class. +/* The RS/6000 has three types of registers, fixed-point, floating-point, and + condition registers, plus three special registers, MQ, CTR, and the link + register. AltiVec adds a vector register class. VSX registers overlap the + FPR registers and the Altivec registers. However, r0 is special in that it cannot be used as a base register. So make a class for registers valid as base registers. @@ -1169,29 +1299,28 @@ enum reg_class reg number REGNO. This could be a conditional expression or could index an array. */ -#define REGNO_REG_CLASS(REGNO) \ - ((REGNO) == 0 ? GENERAL_REGS \ - : (REGNO) < 32 ? BASE_REGS \ - : FP_REGNO_P (REGNO) ? FLOAT_REGS \ - : ALTIVEC_REGNO_P (REGNO) ? ALTIVEC_REGS \ - : (REGNO) == CR0_REGNO ? CR0_REGS \ - : CR_REGNO_P (REGNO) ? CR_REGS \ - : (REGNO) == MQ_REGNO ? MQ_REGS \ - : (REGNO) == LR_REGNO ? LINK_REGS \ - : (REGNO) == CTR_REGNO ? CTR_REGS \ - : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS \ - : (REGNO) == XER_REGNO ? XER_REGS \ - : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS \ - : (REGNO) == VSCR_REGNO ? VRSAVE_REGS \ - : (REGNO) == SPE_ACC_REGNO ? SPE_ACC_REGS \ - : (REGNO) == SPEFSCR_REGNO ? SPEFSCR_REGS \ - : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS \ - : NO_REGS) +extern enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER]; + +#if ENABLE_CHECKING +#define REGNO_REG_CLASS(REGNO) \ + (gcc_assert (IN_RANGE ((REGNO), 0, FIRST_PSEUDO_REGISTER-1)), \ + rs6000_regno_regclass[(REGNO)]) + +#else +#define REGNO_REG_CLASS(REGNO) rs6000_regno_regclass[(REGNO)] +#endif + +/* VSX register classes. */ +extern enum reg_class rs6000_vector_reg_class[]; /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS GENERAL_REGS #define BASE_REG_CLASS BASE_REGS +/* Return whether a given register class can hold VSX objects. */ +#define VSX_REG_CLASS_P(CLASS) \ + ((CLASS) == VSX_REGS || (CLASS) == FLOAT_REGS || (CLASS) == ALTIVEC_REGS) + /* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines @@ -1255,15 +1384,10 @@ enum reg_class /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. - On RS/6000, this is the size of MODE in words, - except in the FP regs, where a single reg is enough for two words. */ -#define CLASS_MAX_NREGS(CLASS, MODE) \ - (((CLASS) == FLOAT_REGS) \ - ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \ - : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS \ - && (MODE) == DFmode) \ - ? 1 \ - : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + On RS/6000, this is the size of MODE in words, except in the FP regs, where + a single reg is enough for two words, unless we have VSX, where the FP + registers can hold 128 bits. */ +#define CLASS_MAX_NREGS(CLASS, MODE) rs6000_class_max_nregs[(MODE)][(CLASS)] /* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */ @@ -1341,8 +1465,8 @@ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */ #define STARTING_FRAME_OFFSET \ (FRAME_GROWS_DOWNWARD \ ? 0 \ - : (RS6000_ALIGN (crtl->outgoing_args_size, \ - TARGET_ALTIVEC ? 16 : 8) \ + : (RS6000_ALIGN (crtl->outgoing_args_size, \ + (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8) \ + RS6000_SAVE_AREA)) /* Offset from the stack pointer register to an item dynamically @@ -1352,8 +1476,8 @@ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */ length of the outgoing arguments. The default is correct for most machines. See `function.c' for details. */ #define STACK_DYNAMIC_OFFSET(FUNDECL) \ - (RS6000_ALIGN (crtl->outgoing_args_size, \ - TARGET_ALTIVEC ? 16 : 8) \ + (RS6000_ALIGN (crtl->outgoing_args_size, \ + (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8) \ + (STACK_POINTER_OFFSET)) /* If we generate an insn to push BYTES bytes, @@ -1603,7 +1727,7 @@ typedef struct rs6000_args #define EPILOGUE_USES(REGNO) \ ((reload_completed && (REGNO) == LR_REGNO) \ || (TARGET_ALTIVEC && (REGNO) == VRSAVE_REGNO) \ - || (crtl->calls_eh_return \ + || (crtl->calls_eh_return \ && TARGET_AIX \ && (REGNO) == 2)) @@ -1892,7 +2016,8 @@ do { \ /* Specify the machine mode that pointers have. After generation of rtl, the compiler makes no further distinction between pointers and any other objects of this machine mode. */ -#define Pmode (TARGET_32BIT ? SImode : DImode) +extern unsigned rs6000_pmode; +#define Pmode ((enum machine_mode)rs6000_pmode) /* Supply definition of STACK_SIZE_MODE for allocate_dynamic_stack_space. */ #define STACK_SIZE_MODE (TARGET_32BIT ? SImode : DImode) @@ -2233,7 +2358,24 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ /* no additional names for: mq, lr, ctr, ap */ \ {"cr0", 68}, {"cr1", 69}, {"cr2", 70}, {"cr3", 71}, \ {"cr4", 72}, {"cr5", 73}, {"cr6", 74}, {"cr7", 75}, \ - {"cc", 68}, {"sp", 1}, {"toc", 2} } + {"cc", 68}, {"sp", 1}, {"toc", 2}, \ + /* VSX registers overlaid on top of FR, Altivec registers */ \ + {"vs0", 32}, {"vs1", 33}, {"vs2", 34}, {"vs3", 35}, \ + {"vs4", 36}, {"vs5", 37}, {"vs6", 38}, {"vs7", 39}, \ + {"vs8", 40}, {"vs9", 41}, {"vs10", 42}, {"vs11", 43}, \ + {"vs12", 44}, {"vs13", 45}, {"vs14", 46}, {"vs15", 47}, \ + {"vs16", 48}, {"vs17", 49}, {"vs18", 50}, {"vs19", 51}, \ + {"vs20", 52}, {"vs21", 53}, {"vs22", 54}, {"vs23", 55}, \ + {"vs24", 56}, {"vs25", 57}, {"vs26", 58}, {"vs27", 59}, \ + {"vs28", 60}, {"vs29", 61}, {"vs30", 62}, {"vs31", 63}, \ + {"vs32", 77}, {"vs33", 78}, {"vs34", 79}, {"vs35", 80}, \ + {"vs36", 81}, {"vs37", 82}, {"vs38", 83}, {"vs39", 84}, \ + {"vs40", 85}, {"vs41", 86}, {"vs42", 87}, {"vs43", 88}, \ + {"vs44", 89}, {"vs45", 90}, {"vs46", 91}, {"vs47", 92}, \ + {"vs48", 93}, {"vs49", 94}, {"vs50", 95}, {"vs51", 96}, \ + {"vs52", 97}, {"vs53", 98}, {"vs54", 99}, {"vs55", 100}, \ + {"vs56", 101},{"vs57", 102},{"vs58", 103},{"vs59", 104}, \ + {"vs60", 105},{"vs61", 106},{"vs62", 107},{"vs63", 108} } /* Text to write out after a CALL that may be replaced by glue code by the loader. This depends on the AIX version. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index cc6478e..9a4079c 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -138,7 +138,7 @@ ;; Processor type -- this attribute must exactly match the processor_type ;; enumeration in rs6000.h. -(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,cell" +(define_attr "cpu" "rios1,rios2,rs64a,mpccore,ppc403,ppc405,ppc440,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppce300c2,ppce300c3,ppce500mc,power4,power5,power6,power7,cell" (const (symbol_ref "rs6000_cpu_attr"))) @@ -218,6 +218,19 @@ ; DImode bits (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")]) +;; ISEL/ISEL64 target selection +(define_mode_attr sel [(SI "") (DI "64")]) + +;; Suffix for reload patterns +(define_mode_attr ptrsize [(SI "32bit") + (DI "64bit")]) + +(define_mode_attr tptrsize [(SI "TARGET_32BIT") + (DI "TARGET_64BIT")]) + +(define_mode_attr mptrsize [(SI "si") + (DI "di")]) + ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. @@ -520,7 +533,7 @@ "@ {andil.|andi.} %2,%1,0xff #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -546,7 +559,7 @@ "@ {andil.|andi.} %0,%1,0xff #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -687,7 +700,7 @@ "@ {andil.|andi.} %2,%1,0xff #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -713,7 +726,7 @@ "@ {andil.|andi.} %0,%1,0xff #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -856,7 +869,7 @@ "@ {andil.|andi.} %2,%1,0xffff #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -882,7 +895,7 @@ "@ {andil.|andi.} %0,%1,0xffff #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -1670,7 +1683,7 @@ "@ nor. %2,%1,%1 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -1696,7 +1709,7 @@ "@ nor. %0,%1,%1 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -2221,10 +2234,22 @@ "TARGET_POPCNTB" "popcntb %0,%1") +(define_insn "popcntwsi2" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (popcount:SI (match_operand:SI 1 "gpc_reg_operand" "r")))] + "TARGET_POPCNTD" + "popcntw %0,%1") + +(define_insn "popcntddi2" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (popcount:DI (match_operand:DI 1 "gpc_reg_operand" "r")))] + "TARGET_POPCNTD && TARGET_POWERPC64" + "popcntd %0,%1") + (define_expand "popcount2" [(set (match_operand:GPR 0 "gpc_reg_operand" "") (popcount:GPR (match_operand:GPR 1 "gpc_reg_operand" "")))] - "TARGET_POPCNTB" + "TARGET_POPCNTB || TARGET_POPCNTD" { rs6000_emit_popcount (operands[0], operands[1]); DONE; @@ -2852,7 +2877,7 @@ {rlinm|rlwinm} %0,%1,0,%m2,%M2 {andil.|andi.} %0,%1,%b2 {andiu.|andis.} %0,%1,%u2" - [(set_attr "type" "*,*,compare,compare")]) + [(set_attr "type" "*,*,fast_compare,fast_compare")]) (define_insn "andsi3_nomc" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") @@ -2895,7 +2920,8 @@ # # #" - [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare") + [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\ + compare,compare,compare,compare") (set_attr "length" "4,4,4,4,8,8,8,8")]) (define_insn "*andsi3_internal3_mc" @@ -2915,7 +2941,8 @@ # # #" - [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare") + [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\ + compare,compare,compare") (set_attr "length" "8,4,4,4,8,8,8,8")]) (define_split @@ -2974,7 +3001,8 @@ # # #" - [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare") + [(set_attr "type" "fast_compare,fast_compare,fast_compare,delayed_compare,\ + compare,compare,compare,compare") (set_attr "length" "4,4,4,4,8,8,8,8")]) (define_insn "*andsi3_internal5_mc" @@ -2996,7 +3024,8 @@ # # #" - [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare") + [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\ + compare,compare,compare") (set_attr "length" "8,4,4,4,8,8,8,8")]) (define_split @@ -3127,7 +3156,7 @@ "@ %q4. %3,%1,%2 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -3156,7 +3185,7 @@ "@ %q4. %0,%1,%2 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -3281,7 +3310,7 @@ "@ %q4. %3,%1,%2 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -3310,7 +3339,7 @@ "@ %q4. %0,%1,%2 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -5303,7 +5332,7 @@ "fres %0,%1" [(set_attr "type" "fp")]) -(define_insn "" +(define_insn "*fmaddsf4_powerpc" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5314,7 +5343,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) -(define_insn "" +(define_insn "*fmaddsf4_power" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5323,7 +5352,7 @@ "{fma|fmadd} %0,%1,%2,%3" [(set_attr "type" "dmul")]) -(define_insn "" +(define_insn "*fmsubsf4_powerpc" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5334,7 +5363,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) -(define_insn "" +(define_insn "*fmsubsf4_power" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5343,7 +5372,7 @@ "{fms|fmsub} %0,%1,%2,%3" [(set_attr "type" "dmul")]) -(define_insn "" +(define_insn "*fnmaddsf4_powerpc_1" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5354,7 +5383,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) -(define_insn "" +(define_insn "*fnmaddsf4_powerpc_2" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")) (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5365,7 +5394,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) -(define_insn "" +(define_insn "*fnmaddsf4_power_1" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5374,7 +5403,7 @@ "{fnma|fnmadd} %0,%1,%2,%3" [(set_attr "type" "dmul")]) -(define_insn "" +(define_insn "*fnmaddsf4_power_2" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")) (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5384,7 +5413,7 @@ "{fnma|fnmadd} %0,%1,%2,%3" [(set_attr "type" "dmul")]) -(define_insn "" +(define_insn "*fnmsubsf4_powerpc_1" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5395,7 +5424,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) -(define_insn "" +(define_insn "*fnmsubsf4_powerpc_2" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f") (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") @@ -5406,7 +5435,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) -(define_insn "" +(define_insn "*fnmsubsf4_power_1" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) @@ -5415,7 +5444,7 @@ "{fnms|fnmsub} %0,%1,%2,%3" [(set_attr "type" "dmul")]) -(define_insn "" +(define_insn "*fnmsubsf4_power_2" [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f") (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") @@ -5542,12 +5571,12 @@ DONE; }") -(define_expand "movsicc" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (if_then_else:SI (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "gpc_reg_operand" "") - (match_operand:SI 3 "gpc_reg_operand" "")))] - "TARGET_ISEL" +(define_expand "movcc" + [(set (match_operand:GPR 0 "gpc_reg_operand" "") + (if_then_else:GPR (match_operand 1 "comparison_operator" "") + (match_operand:GPR 2 "gpc_reg_operand" "") + (match_operand:GPR 3 "gpc_reg_operand" "")))] + "TARGET_ISEL" " { if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) @@ -5564,28 +5593,28 @@ ;; leave out the mode in operand 4 and use one pattern, but reload can ;; change the mode underneath our feet and then gets confused trying ;; to reload the value. -(define_insn "isel_signed" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (if_then_else:SI +(define_insn "isel_signed_" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (if_then_else:GPR (match_operator 1 "comparison_operator" [(match_operand:CC 4 "cc_reg_operand" "y") (const_int 0)]) - (match_operand:SI 2 "gpc_reg_operand" "b") - (match_operand:SI 3 "gpc_reg_operand" "b")))] - "TARGET_ISEL" + (match_operand:GPR 2 "gpc_reg_operand" "b") + (match_operand:GPR 3 "gpc_reg_operand" "b")))] + "TARGET_ISEL" "* { return output_isel (operands); }" [(set_attr "length" "4")]) -(define_insn "isel_unsigned" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (if_then_else:SI +(define_insn "isel_unsigned_" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (if_then_else:GPR (match_operator 1 "comparison_operator" [(match_operand:CCUNS 4 "cc_reg_operand" "y") (const_int 0)]) - (match_operand:SI 2 "gpc_reg_operand" "b") - (match_operand:SI 3 "gpc_reg_operand" "b")))] - "TARGET_ISEL" + (match_operand:GPR 2 "gpc_reg_operand" "b") + (match_operand:GPR 3 "gpc_reg_operand" "b")))] + "TARGET_ISEL" "* { return output_isel (operands); }" [(set_attr "length" "4")]) @@ -5898,6 +5927,12 @@ "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT" "") +(define_expand "fixuns_truncdfsi2" + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))] + "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE" + "") + ; For each of these conversions, there is a define_expand, a define_insn ; with a '#' template, and a define_split (with C code). The idea is ; to allow constant folding with the template of the define_insn, @@ -7609,7 +7644,7 @@ andi. %0,%1,%b2 andis. %0,%1,%u2 #" - [(set_attr "type" "*,*,*,compare,compare,*") + [(set_attr "type" "*,*,*,fast_compare,fast_compare,*") (set_attr "length" "4,4,4,4,4,8")]) (define_insn "anddi3_nomc" @@ -7667,7 +7702,9 @@ # # #" - [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare") + [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\ + fast_compare,compare,compare,compare,compare,compare,\ + compare,compare") (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")]) (define_split @@ -7718,7 +7755,9 @@ # # #" - [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare") + [(set_attr "type" "fast_compare,compare,delayed_compare,fast_compare,\ + fast_compare,compare,compare,compare,compare,compare,\ + compare,compare") (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")]) (define_split @@ -7858,7 +7897,7 @@ "@ %q4. %3,%1,%2 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -7887,7 +7926,7 @@ "@ %q4. %0,%1,%2 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -7958,7 +7997,7 @@ "@ %q4. %3,%2,%1 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -7987,7 +8026,7 @@ "@ %q4. %0,%2,%1 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -8024,7 +8063,7 @@ "@ %q4. %3,%1,%2 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -8053,7 +8092,7 @@ "@ %q4. %0,%1,%2 #" - [(set_attr "type" "compare") + [(set_attr "type" "fast_compare,compare") (set_attr "length" "4,8")]) (define_split @@ -8070,6 +8109,51 @@ (compare:CC (match_dup 0) (const_int 0)))] "") + +(define_expand "smindi3" + [(match_operand:DI 0 "gpc_reg_operand" "") + (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "gpc_reg_operand" "")] + "TARGET_ISEL64" + " +{ + rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); + DONE; +}") + +(define_expand "smaxdi3" + [(match_operand:DI 0 "gpc_reg_operand" "") + (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "gpc_reg_operand" "")] + "TARGET_ISEL64" + " +{ + rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); + DONE; +}") + +(define_expand "umindi3" + [(match_operand:DI 0 "gpc_reg_operand" "") + (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "gpc_reg_operand" "")] + "TARGET_ISEL64" + " +{ + rs6000_emit_minmax (operands[0], UMIN, operands[1], operands[2]); + DONE; +}") + +(define_expand "umaxdi3" + [(match_operand:DI 0 "gpc_reg_operand" "") + (match_operand:DI 1 "gpc_reg_operand" "") + (match_operand:DI 2 "gpc_reg_operand" "")] + "TARGET_ISEL64" + " +{ + rs6000_emit_minmax (operands[0], UMAX, operands[1], operands[2]); + DONE; +}") + ;; Now define ways of moving data around. diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index 45e1c8f..00bd1b0 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -111,24 +111,24 @@ mhard-float Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT) Use hardware floating point -mno-update -Target Report RejectNegative Mask(NO_UPDATE) -Do not generate load/store with update instructions +mpopcntd +Target Report Mask(POPCNTD) +Use PowerPC V2.06 popcntd instruction + +mvsx +Target Report Mask(VSX) +Use vector/scalar (VSX) instructions mupdate -Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE) +Target Report Var(TARGET_UPDATE) Init(1) Generate load/store with update instructions mavoid-indexed-addresses Target Report Var(TARGET_AVOID_XFORM) Init(-1) Avoid generation of indexed load/store instructions when possible -mno-fused-madd -Target Report RejectNegative Mask(NO_FUSED_MADD) -Do not generate fused multiply/add instructions - mfused-madd -Target Report RejectNegative InverseMask(NO_FUSED_MADD, FUSED_MADD) +Target Report Var(TARGET_FUSED_MADD) Init(1) Generate fused multiply/add instructions mtls-markers @@ -198,7 +198,7 @@ Target RejectNegative Joined -mvrsave=yes/no Deprecated option. Use -mvrsave/-mno-vrsave instead misel -Target +Target Report Mask(ISEL) Generate isel instructions misel= diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md index 5368bac..917f817 100644 --- a/gcc/config/rs6000/spe.md +++ b/gcc/config/rs6000/spe.md @@ -1,5 +1,5 @@ ;; e500 SPE description -;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 +;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 ;; Free Software Foundation, Inc. ;; Contributed by Aldy Hernandez (aldy@quesejoda.com) @@ -99,7 +99,7 @@ ;; Floating point conversion instructions. -(define_insn "fixuns_truncdfsi2" +(define_insn "spe_fixuns_truncdfsi2" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "r")))] "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE" diff --git a/gcc/config/rs6000/sync.md b/gcc/config/rs6000/sync.md index 9d1ef9b..f6cc91d 100644 --- a/gcc/config/rs6000/sync.md +++ b/gcc/config/rs6000/sync.md @@ -616,7 +616,7 @@ if (TARGET_NO_LWSYNC) return "sync"; else - return ".long 0x7c2004ac"; + return (TARGET_LWSYNC_INSTRUCTION) ? "lwsync" : ".long 0x7c2004ac"; } [(set_attr "type" "sync")]) diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 611c0d2..4d28e37 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -125,9 +125,9 @@ do { \ else if (!strcmp (rs6000_abi_name, "i960-old")) \ { \ rs6000_current_abi = ABI_V4; \ - target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI \ - | MASK_NO_BITFIELD_WORD); \ + target_flags |= (MASK_LITTLE_ENDIAN | MASK_EABI); \ target_flags &= ~MASK_STRICT_ALIGN; \ + TARGET_NO_BITFIELD_WORD = 1; \ } \ else \ { \ diff --git a/gcc/config/rs6000/sysv4.opt b/gcc/config/rs6000/sysv4.opt index 1ead31d..428417e 100644 --- a/gcc/config/rs6000/sysv4.opt +++ b/gcc/config/rs6000/sysv4.opt @@ -1,6 +1,6 @@ ; SYSV4 options for PPC port. ; -; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc. +; Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc. ; Contributed by Aldy Hernandez . ; ; This file is part of GCC. @@ -32,7 +32,7 @@ Target RejectNegative Joined Specify bit size of immediate TLS offsets mbit-align -Target Report Mask(NO_BITFIELD_TYPE) +Target Report Var(TARGET_NO_BITFIELD_TYPE) Align to the base type of the bit-field mstrict-align @@ -87,11 +87,11 @@ Target Report Mask(EABI) Use EABI mbit-word -Target Report Mask(NO_BITFIELD_WORD) +Target Report Var(TARGET_NO_BITFIELD_WORD) Allow bit-fields to cross word boundaries mregnames -Target Mask(REGNAMES) +Target Var(TARGET_REGNAMES) Use alternate register names ;; This option does nothing and only exists because the compiler diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000 index 1a838c5..695f579 100644 --- a/gcc/config/rs6000/t-rs6000 +++ b/gcc/config/rs6000/t-rs6000 @@ -36,3 +36,30 @@ rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c \ # The rs6000 backend doesn't cause warnings in these files. insn-conditions.o-warn = + +MD_INCLUDES = $(srcdir)/config/rs6000/rios1.md \ + $(srcdir)/config/rs6000/rios2.md \ + $(srcdir)/config/rs6000/rs64.md \ + $(srcdir)/config/rs6000/mpc.md \ + $(srcdir)/config/rs6000/40x.md \ + $(srcdir)/config/rs6000/440.md \ + $(srcdir)/config/rs6000/603.md \ + $(srcdir)/config/rs6000/6xx.md \ + $(srcdir)/config/rs6000/7xx.md \ + $(srcdir)/config/rs6000/7450.md \ + $(srcdir)/config/rs6000/8540.md \ + $(srcdir)/config/rs6000/e300c2c3.md \ + $(srcdir)/config/rs6000/e500mc.md \ + $(srcdir)/config/rs6000/power4.md \ + $(srcdir)/config/rs6000/power5.md \ + $(srcdir)/config/rs6000/power6.md \ + $(srcdir)/config/rs6000/cell.md \ + $(srcdir)/config/rs6000/xfpu.md \ + $(srcdir)/config/rs6000/predicates.md \ + $(srcdir)/config/rs6000/constraints.md \ + $(srcdir)/config/rs6000/darwin.md \ + $(srcdir)/config/rs6000/sync.md \ + $(srcdir)/config/rs6000/altivec.md \ + $(srcdir)/config/rs6000/spe.md \ + $(srcdir)/config/rs6000/dfp.md \ + $(srcdir)/config/rs6000/paired.md diff --git a/gcc/configure b/gcc/configure index 8713f15..8fc162d 100755 --- a/gcc/configure +++ b/gcc/configure @@ -23234,7 +23234,7 @@ if test "${gcc_cv_as_powerpc_mfpgpr+set}" = set; then else gcc_cv_as_powerpc_mfpgpr=no if test $in_tree_gas = yes; then - if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` + if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` then gcc_cv_as_powerpc_mfpgpr=yes fi elif test x$gcc_cv_as != x; then @@ -23330,7 +23330,7 @@ if test "${gcc_cv_as_powerpc_cmpb+set}" = set; then else gcc_cv_as_powerpc_cmpb=no if test $in_tree_gas = yes; then - if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` + if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` then gcc_cv_as_powerpc_cmpb=yes fi elif test x$gcc_cv_as != x; then @@ -23376,7 +23376,7 @@ if test "${gcc_cv_as_powerpc_dfp+set}" = set; then else gcc_cv_as_powerpc_dfp=no if test $in_tree_gas = yes; then - if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` + if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` then gcc_cv_as_powerpc_dfp=yes fi elif test x$gcc_cv_as != x; then @@ -23422,7 +23422,7 @@ if test "${gcc_cv_as_powerpc_vsx+set}" = set; then else gcc_cv_as_powerpc_vsx=no if test $in_tree_gas = yes; then - if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` + if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` then gcc_cv_as_powerpc_vsx=yes fi elif test x$gcc_cv_as != x; then @@ -23452,6 +23452,96 @@ _ACEOF fi + case $target in + *-*-aix*) conftest_s=' .machine "pwr7" + .csect .text[PR] + popcntd 3,3';; + *) conftest_s=' .machine power7 + .text + popcntd 3,3';; + esac + + echo "$as_me:$LINENO: checking assembler for popcntd support" >&5 +echo $ECHO_N "checking assembler for popcntd support... $ECHO_C" >&6 +if test "${gcc_cv_as_powerpc_popcntd+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + gcc_cv_as_powerpc_popcntd=no + if test $in_tree_gas = yes; then + if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` + then gcc_cv_as_powerpc_popcntd=yes +fi + elif test x$gcc_cv_as != x; then + echo "$conftest_s" > conftest.s + if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } + then + gcc_cv_as_powerpc_popcntd=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntd" >&5 +echo "${ECHO_T}$gcc_cv_as_powerpc_popcntd" >&6 +if test $gcc_cv_as_powerpc_popcntd = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_AS_POPCNTD 1 +_ACEOF + +fi + + case $target in + *-*-aix*) conftest_s=' .csect .text[PR] + lwsync';; + *) conftest_s=' .text + lwsync';; + esac + + echo "$as_me:$LINENO: checking assembler for lwsync support" >&5 +echo $ECHO_N "checking assembler for lwsync support... $ECHO_C" >&6 +if test "${gcc_cv_as_powerpc_lwsync+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + gcc_cv_as_powerpc_lwsync=no + if test $in_tree_gas = yes; then + if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` + then gcc_cv_as_powerpc_lwsync=yes +fi + elif test x$gcc_cv_as != x; then + echo "$conftest_s" > conftest.s + if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } + then + gcc_cv_as_powerpc_lwsync=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_lwsync" >&5 +echo "${ECHO_T}$gcc_cv_as_powerpc_lwsync" >&6 +if test $gcc_cv_as_powerpc_lwsync = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_AS_LWSYNC 1 +_ACEOF + +fi + echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5 echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6 if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then diff --git a/gcc/configure.ac b/gcc/configure.ac index f637a11..341571c 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -3125,7 +3125,7 @@ foo: nop esac gcc_GAS_CHECK_FEATURE([move fp gpr support], - gcc_cv_as_powerpc_mfpgpr, [9,99,0],, + gcc_cv_as_powerpc_mfpgpr, [2,19,2],, [$conftest_s],, [AC_DEFINE(HAVE_AS_MFPGPR, 1, [Define if your assembler supports mffgpr and mftgpr.])]) @@ -3159,7 +3159,7 @@ LCF0: esac gcc_GAS_CHECK_FEATURE([compare bytes support], - gcc_cv_as_powerpc_cmpb, [9,99,0], -a32, + gcc_cv_as_powerpc_cmpb, [2,19,2], -a32, [$conftest_s],, [AC_DEFINE(HAVE_AS_CMPB, 1, [Define if your assembler supports cmpb.])]) @@ -3174,7 +3174,7 @@ LCF0: esac gcc_GAS_CHECK_FEATURE([decimal float support], - gcc_cv_as_powerpc_dfp, [9,99,0], -a32, + gcc_cv_as_powerpc_dfp, [2,19,2], -a32, [$conftest_s],, [AC_DEFINE(HAVE_AS_DFP, 1, [Define if your assembler supports DFP instructions.])]) @@ -3189,11 +3189,39 @@ LCF0: esac gcc_GAS_CHECK_FEATURE([vector-scalar support], - gcc_cv_as_powerpc_vsx, [9,99,0], -a32, + gcc_cv_as_powerpc_vsx, [2,19,2], -a32, [$conftest_s],, [AC_DEFINE(HAVE_AS_VSX, 1, [Define if your assembler supports VSX instructions.])]) + case $target in + *-*-aix*) conftest_s=' .machine "pwr7" + .csect .text[[PR]] + popcntd 3,3';; + *) conftest_s=' .machine power7 + .text + popcntd 3,3';; + esac + + gcc_GAS_CHECK_FEATURE([popcntd support], + gcc_cv_as_powerpc_popcntd, [2,19,2], -a32, + [$conftest_s],, + [AC_DEFINE(HAVE_AS_POPCNTD, 1, + [Define if your assembler supports POPCNTD instructions.])]) + + case $target in + *-*-aix*) conftest_s=' .csect .text[[PR]] + lwsync';; + *) conftest_s=' .text + lwsync';; + esac + + gcc_GAS_CHECK_FEATURE([lwsync support], + gcc_cv_as_powerpc_lwsync, [2,19,2], -a32, + [$conftest_s],, + [AC_DEFINE(HAVE_AS_LWSYNC, 1, + [Define if your assembler supports LWSYNC instructions.])]) + gcc_GAS_CHECK_FEATURE([.gnu_attribute support], gcc_cv_as_powerpc_gnu_attribute, [2,18,0],, [.gnu_attribute 4,1],, -- 2.7.4