These patches are primarily infrastructure patches patches, that adds the switches the following patches will use. I also added the new constraints and predicates that will be used by future patches.
At this point of development, I have multiple switches for different sub-features. I could reduce the number of documented switches down to just one or two, like we did in the power7 time frame if desired. 2013-05-17 Michael Meissner <meiss...@linux.vnet.ibm.com> Pat Haugen <pthau...@us.ibm.com> Peter Bergner <berg...@vnet.ibm.com> * doc/invoke.texi (Option Summary): Add power8 options. (RS/6000 and PowerPC Options): Likewise. * doc/md.texi (PowerPC and IBM RS6000 constraints): Update to use constraints.md instead of rs6000.h. Reorder w* constraints. Add wm, wn, wr documentation. * gcc/config/rs6000/constraints.md (wm): New constraint for VSX registers if direct move instructions are enabled. (wn): New constraint for no registers. (wq): New constraint for quad word even GPR registers. (wr): New constraint if 64-bit instructions are enabled. (wv): New constraint if power8 vector instructions are enabled. (wQ): New constraint for quad word memory locations. * gcc/config/rs6000/predicates.md (const_0_to_15_operand): New constraint for 0..15 for crypto instructions. (gpc_reg_operand): If VSX allow registers in VSX registers as well as GPR and floating point registers. (int_reg_operand): New predicate to match only GPR registers. (base_reg_operand): New predicate to match base registers. (quad_int_reg_operand): New predicate to match even GPR registers for quad memory operations. (vsx_reg_or_cint_operand): New predicate to allow vector logical operations in both GPR and VSX registers. (quad_memory_operand): New predicate for quad memory operations. (reg_or_indexed_operand): New predicate for direct move support. * gcc/config/rs6000/rs6000-cpus.def (ISA_2_5_MASKS_EMBEDDED): Inherit from ISA_2_4_MASKS, not ISA_2_2_MASKS. (ISA_2_7_MASKS_SERVER): New mask for ISA 2.07 (i.e. power8). (POWERPC_MASKS): Add power8 options. (power8 cpu): Use ISA_2_7_MASKS_SERVER instead of specifying the various options. * gcc/config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Define _ARCH_PWR8 and __POWER8_VECTOR__ for power8. * gcc/config/rs6000/rs6000.opt (-mvsx-timode): Add documentation. (-mpower8-fusion): New power8 options. (-mpower8-fusion-sign): Likewise. (-mpower8-vector): Likewise. (-mcrypto): Likewise. (-mdirect-move): Likewise. (-mquad-memory): Likewise. * gcc/config/rs6000/rs6000.c (power8_cost): Initial definition for power8. (rs6000_hard_regno_mode_ok): Make PTImode only match even GPR registers. (rs6000_debug_reg_print): Print the base register class if -mdebug=reg. (rs6000_debug_vector_unit): Add p8_vector. (rs6000_debug_reg_global): If -mdebug=reg, print power8 constraint definitions. Also print fusion state. (rs6000_init_hard_regno_mode_ok): Set up power8 constraints. (rs6000_builtin_mask_calculate): Add power8 builtin support. (rs6000_option_override_internal): Add support for power8. (rs6000_common_init_builtins): Add debugging for skipped builtins if -mdebug=builtin. (rs6000_adjust_cost): Add power8 support. (rs6000_issue_rate): Likewise. (insn_must_be_first_in_group): Likewise. (insn_must_be_last_in_group): Likewise. (force_new_group): Likewise. (rs6000_register_move_cost): Likewise. (rs6000_opt_masks): Likewise. * config/rs6000/rs6000.h (ASM_CPU_POWER8_SPEC): If we don't have a power8 capable assembler, default to power7 options. (TARGET_DIRECT_MOVE): Likewise. (TARGET_CRYPTO): Likewise. (TARGET_P8_VECTOR): Likewise. (VECTOR_UNIT_P8_VECTOR_P): Define power8 vector support. (VECTOR_UNIT_VSX_OR_P8_VECTOR_P): Likewise. (VECTOR_MEM_P8_VECTOR_P): Likewise. (VECTOR_MEM_VSX_OR_P8_VECTOR_P): Likewise. (VECTOR_MEM_ALTIVEC_OR_VSX_P): Likewise. (TARGET_XSCVDPSPN): Likewise. (TARGET_XSCVSPDPN): Likewsie. (TARGET_SYNC_HI_QI): Likewise. (TARGET_SYNC_TI): Likewise. (MASK_CRYPTO): Likewise. (MASK_DIRECT_MOVE): Likewise. (MASK_P8_FUSION): Likewise. (MASK_P8_VECTOR): Likewise. (REG_ALLOC_ORDER): Move fr13 to be lower in priority so that the TFmode temporary used by some of the direct move instructions to get two FP temporary registers does not force creation of a stack frame. (VLOGICAL_REGNO_P): Allow vector logical operations in GPRs. (MODES_TIEABLE_P): Move the VSX tests above the Altivec tests so that any VSX registers are tieable, even if they are also an Altivec vector mode. (r6000_reg_class_enum): Add wm, wq, wr, wv constraints. (RS6000_BTM_P8_VECTOR): Power8 builtin support. (RS6000_BTM_CRYPTO): Likewise. (RS6000_BTM_COMMON): Likewise. * config/rs6000/rs6000.md (cpu attribute): Add power8. * config/rs6000/rs6000-opts.h (PROCESSOR_POWER8): Likewise. (enum rs6000_vector): Add power8 vector support. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460, USA email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 199037) +++ gcc/doc/invoke.texi (working copy) @@ -860,7 +860,10 @@ See RS/6000 and PowerPC Options. -mno-recip-precision @gol -mveclibabi=@var{type} -mfriz -mno-friz @gol -mpointers-to-nested-functions -mno-pointers-to-nested-functions @gol --msave-toc-indirect -mno-save-toc-indirect} +-msave-toc-indirect -mno-save-toc-indirect @gol +-mpower8-fusion -mno-mpower8-fusion -mpower8-vector -mno-power8-vector @gol +-mcrypto -mno-crypto -mdirect-move -mno-direct-move @gol +-mquad-memory -mno-quad-memory} @emph{RX Options} @gccoptlist{-m64bit-doubles -m32bit-doubles -fpu -nofpu@gol @@ -17341,7 +17344,8 @@ following options: @gccoptlist{-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple @gol -mpopcntb -mpopcntd -mpowerpc64 @gol -mpowerpc-gpopt -mpowerpc-gfxopt -msingle-float -mdouble-float @gol --msimple-fpu -mstring -mmulhw -mdlmzb -mmfpgpr -mvsx} +-msimple-fpu -mstring -mmulhw -mdlmzb -mmfpgpr -mvsx @gol +-mcrypto -mdirect-move -mpower8-fusion -mpower8-vector -mquad-memory} The particular options set for any particular CPU varies between compiler versions, depending on what setting seems to produce optimal @@ -17459,6 +17463,47 @@ Generate code that uses (does not use) v instructions, and also enable the use of built-in functions that allow more direct access to the VSX instruction set. +@item -mcrypto +@itemx -mno-crypto +@opindex mcrypto +@opindex mno-crypto +Enable the use (disable) of the built-in functions that allow direct +access to the cryptographic instructions that were added in version +2.07 of the PowerPC ISA. + +@item -mdirect-move +@itemx -mno-direct-move +@opindex mdirect-move +@opindex mno-direct-move +Generate code that uses (does not use) the instructions to move data +between the general purpose registers and the vector/scalar (VSX) +registers that were added in version 2.07 of the PowerPC ISA. + +@item -mpower8-fusion +@itemx -mno-power8-fusion +@opindex mpower8-fusion +@opindex mno-power8-fusion +Generate code that keeps (does not keeps) some integer operations +adjacent so that the instructions can be fused together on power8 and +later processors. + +@item -mpower8-vector +@itemx -mno-power8-vector +@opindex mpower8-vector +@opindex mno-power8-vector +Generate code that uses (does not use) the vector and scalar +instructions that were added in version 2.07 of the PowerPC ISA. Also +enable the use of built-in functions that allow more direct access to +the vector instructions. + +@item -mquad-memory +@itemx -mno-quad-memory +@opindex mquad-memory +@opindex mno-quad-memory +Generate code that uses (does not use) the quad word memory +instructions. The @option{-mquad-memory} option requires use of +64-bit mode. + @item -mfloat-gprs=@var{yes/single/double/no} @itemx -mfloat-gprs @opindex mfloat-gprs Index: gcc/doc/md.texi =================================================================== --- gcc/doc/md.texi (revision 199037) +++ gcc/doc/md.texi (working copy) @@ -2055,7 +2055,7 @@ Any constant whose absolute value is no @end table -@item PowerPC and IBM RS6000---@file{config/rs6000/rs6000.h} +@item PowerPC and IBM RS6000---@file{config/rs6000/constraints.md} @table @code @item b Address base register @@ -2069,6 +2069,9 @@ Floating point register (containing 32-b @item v Altivec vector register +@item wa +Any VSX register + @item wd VSX vector register to hold vector double data @@ -2081,6 +2084,18 @@ If @option{-mmfpgpr} was used, a floatin @item wl If the LFIWAX instruction is enabled, a floating point register +@item wm +If direct moves are enabled, a VSX register. + +@item wn +No register. + +@item wq +Even general purpose register to use with load/store quad instructions + +@item wr +General purpose register if 64-bit mode is used + @item ws VSX vector register to hold scalar float data @@ -2093,8 +2108,9 @@ If the STFIWX instruction is enabled, a @item wz If the LFIWZX instruction is enabled, a floating point register -@item wa -Any VSX register +@item wQ +A memory address that will work with the @code{lq} and @code{stq} +instructions. @item h @samp{MQ}, @samp{CTR}, or @samp{LINK} register Index: gcc/ChangeLog.ibm =================================================================== --- gcc/ChangeLog.ibm (revision 199038) +++ gcc/ChangeLog.ibm (working copy) @@ -1,5 +1,108 @@ 2013-05-17 Michael Meissner <meiss...@linux.vnet.ibm.com> + * doc/invoke.texi (Option Summary): Add power8 options. + (RS/6000 and PowerPC Options): Likewise. + + * doc/md.texi (PowerPC and IBM RS6000 constraints): Update to use + constraints.md instead of rs6000.h. Reorder w* constraints. Add + wm, wn, wr documentation. + + * gcc/config/rs6000/constraints.md (wm): New constraint for VSX + registers if direct move instructions are enabled. + (wn): New constraint for no registers. + (wq): New constraint for quad word even GPR registers. + (wr): New constraint if 64-bit instructions are enabled. + (wv): New constraint if power8 vector instructions are enabled. + (wQ): New constraint for quad word memory locations. + + * gcc/config/rs6000/predicates.md (const_0_to_15_operand): New + constraint for 0..15 for crypto instructions. + (gpc_reg_operand): If VSX allow registers in VSX registers as well + as GPR and floating point registers. + (int_reg_operand): New predicate to match only GPR registers. + (base_reg_operand): New predicate to match base registers. + (quad_int_reg_operand): New predicate to match even GPR registers + for quad memory operations. + (vsx_reg_or_cint_operand): New predicate to allow vector logical + operations in both GPR and VSX registers. + (quad_memory_operand): New predicate for quad memory operations. + (reg_or_indexed_operand): New predicate for direct move support. + + * gcc/config/rs6000/rs6000-cpus.def (ISA_2_5_MASKS_EMBEDDED): + Inherit from ISA_2_4_MASKS, not ISA_2_2_MASKS. + (ISA_2_7_MASKS_SERVER): New mask for ISA 2.07 (i.e. power8). + (POWERPC_MASKS): Add power8 options. + (power8 cpu): Use ISA_2_7_MASKS_SERVER instead of specifying the + various options. + + * gcc/config/rs6000/rs6000-c.c (rs6000_target_modify_macros): + Define _ARCH_PWR8 and __POWER8_VECTOR__ for power8. + + * gcc/config/rs6000/rs6000.opt (-mvsx-timode): Add documentation. + (-mpower8-fusion): New power8 options. + (-mpower8-fusion-sign): Likewise. + (-mpower8-vector): Likewise. + (-mcrypto): Likewise. + (-mdirect-move): Likewise. + (-mquad-memory): Likewise. + + * gcc/config/rs6000/rs6000.c (power8_cost): Initial definition for + power8. + (rs6000_hard_regno_mode_ok): Make PTImode only match even GPR + registers. + (rs6000_debug_reg_print): Print the base register class if + -mdebug=reg. + (rs6000_debug_vector_unit): Add p8_vector. + (rs6000_debug_reg_global): If -mdebug=reg, print power8 constraint + definitions. Also print fusion state. + (rs6000_init_hard_regno_mode_ok): Set up power8 constraints. + (rs6000_builtin_mask_calculate): Add power8 builtin support. + (rs6000_option_override_internal): Add support for power8. + (rs6000_common_init_builtins): Add debugging for skipped builtins + if -mdebug=builtin. + (rs6000_adjust_cost): Add power8 support. + (rs6000_issue_rate): Likewise. + (insn_must_be_first_in_group): Likewise. + (insn_must_be_last_in_group): Likewise. + (force_new_group): Likewise. + (rs6000_register_move_cost): Likewise. + (rs6000_opt_masks): Likewise. + + * config/rs6000/rs6000.h (ASM_CPU_POWER8_SPEC): If we don't have a + power8 capable assembler, default to power7 options. + (TARGET_DIRECT_MOVE): Likewise. + (TARGET_CRYPTO): Likewise. + (TARGET_P8_VECTOR): Likewise. + (VECTOR_UNIT_P8_VECTOR_P): Define power8 vector support. + (VECTOR_UNIT_VSX_OR_P8_VECTOR_P): Likewise. + (VECTOR_MEM_P8_VECTOR_P): Likewise. + (VECTOR_MEM_VSX_OR_P8_VECTOR_P): Likewise. + (VECTOR_MEM_ALTIVEC_OR_VSX_P): Likewise. + (TARGET_XSCVDPSPN): Likewise. + (TARGET_XSCVSPDPN): Likewsie. + (TARGET_SYNC_HI_QI): Likewise. + (TARGET_SYNC_TI): Likewise. + (MASK_CRYPTO): Likewise. + (MASK_DIRECT_MOVE): Likewise. + (MASK_P8_FUSION): Likewise. + (MASK_P8_VECTOR): Likewise. + (REG_ALLOC_ORDER): Move fr13 to be lower in priority so that the + TFmode temporary used by some of the direct move instructions to + get two FP temporary registers does not force creation of a stack + frame. + (VLOGICAL_REGNO_P): Allow vector logical operations in GPRs. + (MODES_TIEABLE_P): Move the VSX tests above the Altivec tests so + that any VSX registers are tieable, even if they are also an + Altivec vector mode. + (r6000_reg_class_enum): Add wm, wq, wr, wv constraints. + (RS6000_BTM_P8_VECTOR): Power8 builtin support. + (RS6000_BTM_CRYPTO): Likewise. + (RS6000_BTM_COMMON): Likewise. + + * config/rs6000/rs6000.md (cpu attribute): Add power8. + * config/rs6000/rs6000-opts.h (PROCESSOR_POWER8): Likewise. + (enum rs6000_vector): Add power8 vector support. + Clone branch from subversion id 199028. * REVISION: New file to track subversion id. Index: gcc/config/rs6000/constraints.md =================================================================== --- gcc/config/rs6000/constraints.md (revision 199037) +++ gcc/config/rs6000/constraints.md (working copy) @@ -79,12 +79,35 @@ (define_register_constraint "wg" "rs6000 (define_register_constraint "wl" "rs6000_constraints[RS6000_CONSTRAINT_wl]" "Floating point register if the LFIWAX instruction is enabled or NO_REGS.") +(define_register_constraint "wm" "rs6000_constraints[RS6000_CONSTRAINT_wm]" + "VSX register if direct move instructions are enabled, or NO_REGS.") + +(define_constraint "wq" + "Even general purpose register to use with load/store quad instructions." + (match_operand 0 "quad_int_reg_operand")) + +(define_register_constraint "wr" "rs6000_constraints[RS6000_CONSTRAINT_wr]" + "General purpose register if 64-bit instructions are enabled or NO_REGS.") + +(define_register_constraint "wv" "rs6000_constraints[RS6000_CONSTRAINT_wv]" + "Altivec register if -mpower8-vector is used or NO_REGS.") + (define_register_constraint "wx" "rs6000_constraints[RS6000_CONSTRAINT_wx]" "Floating point register if the STFIWX instruction is enabled or NO_REGS.") (define_register_constraint "wz" "rs6000_constraints[RS6000_CONSTRAINT_wz]" "Floating point register if the LFIWZX instruction is enabled or NO_REGS.") +;; NO_REGs register constraint, used to merge mov{sd,sf}, since movsd can use +;; direct move directly, and movsf can't to move between the register sets. +;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode +(define_register_constraint "wn" "NO_REGS") + +;; Lq/stq validates the address for load/store quad +(define_memory_constraint "wQ" + "Memory operand suitable for the load/store quad instructions" + (match_operand 0 "quad_memory_operand")) + ;; Altivec style load/store that ignores the bottom bits of the address (define_memory_constraint "wZ" "Indexed or indirect memory operand, ignoring the bottom 4 bits" Index: gcc/config/rs6000/predicates.md =================================================================== --- gcc/config/rs6000/predicates.md (revision 199037) +++ gcc/config/rs6000/predicates.md (working copy) @@ -166,6 +166,11 @@ (define_predicate "const_2_to_3_operand" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 2, 3)"))) +;; Match op = 0..15 +(define_predicate "const_0_to_15_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 15)"))) + ;; Return 1 if op is a register that is not special. (define_predicate "gpc_reg_operand" (match_operand 0 "register_operand") @@ -182,9 +187,68 @@ (define_predicate "gpc_reg_operand" if (REGNO (op) >= ARG_POINTER_REGNUM && !CA_REGNO_P (REGNO (op))) return 1; + if (TARGET_VSX && VSX_REGNO_P (REGNO (op))) + return 1; + return INT_REGNO_P (REGNO (op)) || FP_REGNO_P (REGNO (op)); }) +;; Return 1 if op is a general purpose register. Unlike gpc_reg_operand, don't +;; allow floating point or vector registers. +(define_predicate "int_reg_operand" + (match_operand 0 "register_operand") +{ + if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode)) + return 0; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (!REG_P (op)) + return 0; + + if (REGNO (op) >= ARG_POINTER_REGNUM && !CA_REGNO_P (REGNO (op))) + return 1; + + return INT_REGNO_P (REGNO (op)); +}) + +;; Like int_reg_operand, but only return true for base registers +(define_predicate "base_reg_operand" + (match_operand 0 "int_reg_operand") +{ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (!REG_P (op)) + return 0; + + return (REGNO (op) != FIRST_GPR_REGNO); +}) + +;; Return 1 if op is a general purpose register that is an even register +;; which suitable for a load/store quad operation +(define_predicate "quad_int_reg_operand" + (match_operand 0 "register_operand") +{ + HOST_WIDE_INT r; + + if (!TARGET_QUAD_MEMORY) + return 0; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (!REG_P (op)) + return 0; + + r = REGNO (op); + if (r >= FIRST_PSEUDO_REGISTER) + return 1; + + return (INT_REGNO_P (r) && ((r & 1) == 0)); +}) + ;; Return 1 if op is a register that is a condition register field. (define_predicate "cc_reg_operand" (match_operand 0 "register_operand") @@ -302,6 +366,11 @@ (define_predicate "reg_or_logical_cint_o & (~ (unsigned HOST_WIDE_INT) 0xffffffff)) == 0)") (match_operand 0 "gpc_reg_operand"))) +;; Like reg_or_logical_cint_operand, but allow vsx registers +(define_predicate "vsx_reg_or_cint_operand" + (ior (match_operand 0 "vsx_register_operand") + (match_operand 0 "reg_or_logical_cint_operand"))) + ;; Return 1 if operand is a CONST_DOUBLE that can be set in a register ;; with no more than one instruction per word. (define_predicate "easy_fp_constant" @@ -507,6 +576,54 @@ (define_predicate "offsettable_mem_opera (and (match_operand 0 "memory_operand") (match_test "offsettable_nonstrict_memref_p (op)"))) +;; Return 1 if the operand is suitable for load/store quad memory. +(define_predicate "quad_memory_operand" + (match_code "mem") +{ + rtx addr, op0, op1; + int ret; + + if (!TARGET_QUAD_MEMORY) + ret = 0; + + else if (!memory_operand (op, mode)) + ret = 0; + + else if (GET_MODE_SIZE (GET_MODE (op)) != 16) + ret = 0; + + else if (MEM_ALIGN (op) < 128) + ret = 0; + + else + { + addr = XEXP (op, 0); + if (int_reg_operand (addr, Pmode)) + ret = 1; + + else if (GET_CODE (addr) != PLUS) + ret = 0; + + else + { + op0 = XEXP (addr, 0); + op1 = XEXP (addr, 1); + ret = (int_reg_operand (op0, Pmode) + && GET_CODE (op1) == CONST_INT + && IN_RANGE (INTVAL (op1), -32768, 32767) + && (INTVAL (op1) & 15) == 0); + } + } + + if (TARGET_DEBUG_ADDR) + { + fprintf (stderr, "\nquad_memory_operand, ret = %s\n", ret ? "true" : "false"); + debug_rtx (op); + } + + return ret; +}) + ;; Return 1 if the operand is an indexed or indirect memory operand. (define_predicate "indexed_or_indirect_operand" (match_code "mem") @@ -521,6 +638,19 @@ (define_predicate "indexed_or_indirect_o return indexed_or_indirect_address (op, mode); }) +;; Like indexed_or_indirect_operand, but also allow a GPR register if direct +;; moves are supported. +(define_predicate "reg_or_indexed_operand" + (match_code "mem,reg") +{ + if (MEM_P (op)) + return indexed_or_indirect_operand (op, mode); + else if (TARGET_DIRECT_MOVE) + return register_operand (op, mode); + return + 0; +}) + ;; Return 1 if the operand is an indexed or indirect memory operand with an ;; AND -16 in it, used to recognize when we need to switch to Altivec loads ;; to realign loops instead of VSX (altivec silently ignores the bottom bits, Index: gcc/config/rs6000/rs6000-cpus.def =================================================================== --- gcc/config/rs6000/rs6000-cpus.def (revision 199037) +++ gcc/config/rs6000/rs6000-cpus.def (working copy) @@ -28,7 +28,7 @@ ALTIVEC, since in general it isn't a win on power6. In ISA 2.04, fsel, fre, fsqrt, etc. were no longer documented as optional. Group masks by server and embedded. */ -#define ISA_2_5_MASKS_EMBEDDED (ISA_2_2_MASKS \ +#define ISA_2_5_MASKS_EMBEDDED (ISA_2_4_MASKS \ | OPTION_MASK_CMPB \ | OPTION_MASK_RECIP_PRECISION \ | OPTION_MASK_PPC_GFXOPT \ @@ -45,6 +45,14 @@ | OPTION_MASK_VSX \ | OPTION_MASK_VSX_TIMODE) +/* For now, don't provide an embedded version of ISA 2.07. */ +#define ISA_2_7_MASKS_SERVER (ISA_2_6_MASKS_SERVER \ + | OPTION_MASK_P8_FUSION \ + | OPTION_MASK_P8_VECTOR \ + | OPTION_MASK_CRYPTO \ + | OPTION_MASK_DIRECT_MOVE \ + | OPTION_MASK_QUAD_MEMORY) + #define POWERPC_7400_MASK (OPTION_MASK_PPC_GFXOPT | OPTION_MASK_ALTIVEC) /* Deal with ports that do not have -mstrict-align. */ @@ -61,7 +69,9 @@ /* Mask of all options to set the default isa flags based on -mcpu=<xxx>. */ #define POWERPC_MASKS (OPTION_MASK_ALTIVEC \ | OPTION_MASK_CMPB \ + | OPTION_MASK_CRYPTO \ | OPTION_MASK_DFP \ + | OPTION_MASK_DIRECT_MOVE \ | OPTION_MASK_DLMZB \ | OPTION_MASK_FPRND \ | OPTION_MASK_ISEL \ @@ -69,11 +79,14 @@ | OPTION_MASK_MFPGPR \ | OPTION_MASK_MULHW \ | OPTION_MASK_NO_UPDATE \ + | OPTION_MASK_P8_FUSION \ + | OPTION_MASK_P8_VECTOR \ | OPTION_MASK_POPCNTB \ | OPTION_MASK_POPCNTD \ | OPTION_MASK_POWERPC64 \ | OPTION_MASK_PPC_GFXOPT \ | OPTION_MASK_PPC_GPOPT \ + | OPTION_MASK_QUAD_MEMORY \ | OPTION_MASK_RECIP_PRECISION \ | OPTION_MASK_SOFT_FLOAT \ | OPTION_MASK_STRICT_ALIGN_OPTIONAL \ @@ -168,10 +181,7 @@ RS6000_CPU ("power7", PROCESSOR_POWER7, POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD | MASK_VSX | MASK_RECIP_PRECISION | MASK_VSX_TIMODE) -RS6000_CPU ("power8", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */ - POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF - | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD - | MASK_VSX | MASK_RECIP_PRECISION | MASK_VSX_TIMODE) +RS6000_CPU ("power8", PROCESSOR_POWER7, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER) RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0) RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64) RS6000_CPU ("rs64", PROCESSOR_RS64A, MASK_PPC_GFXOPT | MASK_POWERPC64) Index: gcc/config/rs6000/rs6000-c.c =================================================================== --- gcc/config/rs6000/rs6000-c.c (revision 199037) +++ gcc/config/rs6000/rs6000-c.c (working copy) @@ -315,6 +315,8 @@ rs6000_target_modify_macros (bool define rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR6X"); if ((flags & OPTION_MASK_POPCNTD) != 0) rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR7"); + if ((flags & OPTION_MASK_DIRECT_MOVE) != 0) + rs6000_define_or_undefine_macro (define_p, "_ARCH_PWR8"); if ((flags & OPTION_MASK_SOFT_FLOAT) != 0) rs6000_define_or_undefine_macro (define_p, "_SOFT_FLOAT"); if ((flags & OPTION_MASK_RECIP_PRECISION) != 0) @@ -331,6 +333,8 @@ rs6000_target_modify_macros (bool define } if ((flags & OPTION_MASK_VSX) != 0) rs6000_define_or_undefine_macro (define_p, "__VSX__"); + if ((flags & OPTION_MASK_P8_VECTOR) != 0) + rs6000_define_or_undefine_macro (define_p, "__POWER8_VECTOR__"); /* options from the builtin masks. */ if ((bu_mask & RS6000_BTM_SPE) != 0) Index: gcc/config/rs6000/rs6000.opt =================================================================== --- gcc/config/rs6000/rs6000.opt (revision 199037) +++ gcc/config/rs6000/rs6000.opt (working copy) @@ -517,4 +517,28 @@ Control whether we save the TOC in the p mvsx-timode Target Undocumented Mask(VSX_TIMODE) Var(rs6000_isa_flags) -; Allow/disallow TImode in VSX registers +Allow 128-bit integers in VSX registers + +mpower8-fusion +Target Report Mask(P8_FUSION) Var(rs6000_isa_flags) +Fuse certain integer operations together for better performance on power8 + +mpower8-fusion-sign +Target Undocumented Mask(P8_FUSION_SIGN) Var(rs6000_isa_flags) +Allow sign extension in fusion operations + +mpower8-vector +Target Report Mask(P8_VECTOR) Var(rs6000_isa_flags) +Use/do not use vector and scalar instructions added in ISA 2.07. + +mcrypto +Target Report Mask(CRYPTO) Var(rs6000_isa_flags) +Use ISA 2.07 crypto instructions + +mdirect-move +Target Report Mask(DIRECT_MOVE) Var(rs6000_isa_flags) +Use ISA 2.07 direct move between GPR & VSX register instructions + +mquad-memory +Target Report Mask(QUAD_MEMORY) Var(rs6000_isa_flags) +Generate the quad word memory instructions (lq/stq/lqarx/stqcx). Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 199037) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -831,6 +831,25 @@ struct processor_costs power7_cost = { 12, /* prefetch streams */ }; +/* Instruction costs on POWER8 processors. */ +static const +struct processor_costs power8_cost = { + COSTS_N_INSNS (3), /* mulsi */ + COSTS_N_INSNS (3), /* mulsi_const */ + COSTS_N_INSNS (3), /* mulsi_const9 */ + COSTS_N_INSNS (3), /* muldi */ + COSTS_N_INSNS (19), /* divsi */ + COSTS_N_INSNS (35), /* divdi */ + COSTS_N_INSNS (3), /* fp */ + COSTS_N_INSNS (3), /* dmul */ + COSTS_N_INSNS (14), /* sdiv */ + COSTS_N_INSNS (17), /* ddiv */ + 128, /* cache line size */ + 32, /* l1 cache */ + 256, /* l2 cache */ + 12, /* prefetch streams */ +}; + /* Instruction costs on POWER A2 processors. */ static const struct processor_costs ppca2_cost = { @@ -1547,6 +1566,15 @@ rs6000_hard_regno_mode_ok (int regno, en { int last_regno = regno + rs6000_hard_regno_nregs[mode][regno] - 1; + /* PTImode can only go in GPRs. Quad word memory operations require even/odd + register combinations, and use PTImode where we need to deal with quad + word memory operations. Don't allow quad words in the argument or frame + pointer registers, just registers 0..31. */ + if (mode == PTImode) + return (IN_RANGE (regno, FIRST_GPR_REGNO, LAST_GPR_REGNO) + && IN_RANGE (last_regno, FIRST_GPR_REGNO, LAST_GPR_REGNO) + && ((regno & 1) == 0)); + /* VSX registers that overlap the FPR registers are larger than for non-VSX implementations. Don't allow an item to be split between a FP register and an Altivec register. */ @@ -1678,6 +1706,16 @@ rs6000_debug_reg_print (int first_regno, comma = ""; } + len += fprintf (stderr, "%sreg-class = %s", comma, + reg_class_names[(int)rs6000_regno_regclass[r]]); + comma = ", "; + + if (len > 70) + { + fprintf (stderr, ",\n\t"); + comma = ""; + } + fprintf (stderr, "%sregno = %d\n", comma, r); } } @@ -1710,6 +1748,7 @@ rs6000_debug_reg_global (void) "none", "altivec", "vsx", + "p8_vector", "paired", "spe", "other" @@ -1802,8 +1841,11 @@ rs6000_debug_reg_global (void) "wf reg_class = %s\n" "wg reg_class = %s\n" "wl reg_class = %s\n" + "wm reg_class = %s\n" + "wr reg_class = %s\n" "ws reg_class = %s\n" "wt reg_class = %s\n" + "wv reg_class = %s\n" "wx reg_class = %s\n" "wz reg_class = %s\n" "\n", @@ -1815,8 +1857,11 @@ rs6000_debug_reg_global (void) reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wf]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wg]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]], + reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wm]], + reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]], + reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wv]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wz]]); @@ -2050,6 +2095,10 @@ rs6000_debug_reg_global (void) if (targetm.lra_p ()) fprintf (stderr, DEBUG_FMT_S, "lra", "true"); + if (TARGET_P8_FUSION) + fprintf (stderr, DEBUG_FMT_S, "p8 fusion", + (TARGET_P8_FUSION_SIGN) ? "zero+sign" : "zero"); + fprintf (stderr, DEBUG_FMT_S, "plt-format", TARGET_SECURE_PLT ? "secure" : "bss"); fprintf (stderr, DEBUG_FMT_S, "struct-return", @@ -2240,6 +2289,15 @@ rs6000_init_hard_regno_mode_ok (bool glo if (TARGET_LFIWAX) rs6000_constraints[RS6000_CONSTRAINT_wl] = FLOAT_REGS; + if (TARGET_DIRECT_MOVE) + rs6000_constraints[RS6000_CONSTRAINT_wm] = VSX_REGS; + + if (TARGET_POWERPC64) + rs6000_constraints[RS6000_CONSTRAINT_wr] = GENERAL_REGS; + + if (TARGET_P8_VECTOR) + rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS; + if (TARGET_STFIWX) rs6000_constraints[RS6000_CONSTRAINT_wx] = FLOAT_REGS; @@ -2520,16 +2578,18 @@ darwin_rs6000_override_options (void) HOST_WIDE_INT rs6000_builtin_mask_calculate (void) { - return (((TARGET_ALTIVEC) ? RS6000_BTM_ALTIVEC : 0) - | ((TARGET_VSX) ? RS6000_BTM_VSX : 0) - | ((TARGET_SPE) ? RS6000_BTM_SPE : 0) - | ((TARGET_PAIRED_FLOAT) ? RS6000_BTM_PAIRED : 0) - | ((TARGET_FRE) ? RS6000_BTM_FRE : 0) - | ((TARGET_FRES) ? RS6000_BTM_FRES : 0) - | ((TARGET_FRSQRTE) ? RS6000_BTM_FRSQRTE : 0) - | ((TARGET_FRSQRTES) ? RS6000_BTM_FRSQRTES : 0) - | ((TARGET_POPCNTD) ? RS6000_BTM_POPCNTD : 0) - | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL : 0)); + return (((TARGET_ALTIVEC) ? RS6000_BTM_ALTIVEC : 0) + | ((TARGET_VSX) ? RS6000_BTM_VSX : 0) + | ((TARGET_SPE) ? RS6000_BTM_SPE : 0) + | ((TARGET_PAIRED_FLOAT) ? RS6000_BTM_PAIRED : 0) + | ((TARGET_FRE) ? RS6000_BTM_FRE : 0) + | ((TARGET_FRES) ? RS6000_BTM_FRES : 0) + | ((TARGET_FRSQRTE) ? RS6000_BTM_FRSQRTE : 0) + | ((TARGET_FRSQRTES) ? RS6000_BTM_FRSQRTES : 0) + | ((TARGET_POPCNTD) ? RS6000_BTM_POPCNTD : 0) + | ((rs6000_cpu == PROCESSOR_CELL) ? RS6000_BTM_CELL : 0) + | ((TARGET_P8_VECTOR) ? RS6000_BTM_P8_VECTOR : 0) + | ((TARGET_CRYPTO) ? RS6000_BTM_CRYPTO : 0)); } /* Override command line options. Mostly we process the processor type and @@ -2803,7 +2863,9 @@ rs6000_option_override_internal (bool gl /* For the newer switches (vsx, dfp, etc.) set some of the older options, unless the user explicitly used the -mno-<option> to disable the code. */ - if (TARGET_VSX) + if (TARGET_P8_VECTOR || TARGET_DIRECT_MOVE || TARGET_CRYPTO) + rs6000_isa_flags |= (ISA_2_7_MASKS_SERVER & ~rs6000_isa_flags_explicit); + else if (TARGET_VSX) rs6000_isa_flags |= (ISA_2_6_MASKS_SERVER & ~rs6000_isa_flags_explicit); else if (TARGET_POPCNTD) rs6000_isa_flags |= (ISA_2_6_MASKS_EMBEDDED & ~rs6000_isa_flags_explicit); @@ -2818,6 +2880,34 @@ rs6000_option_override_internal (bool gl else if (TARGET_ALTIVEC) rs6000_isa_flags |= (OPTION_MASK_PPC_GFXOPT & ~rs6000_isa_flags_explicit); + if (TARGET_CRYPTO && !TARGET_ALTIVEC) + { + if (rs6000_isa_flags_explicit & OPTION_MASK_CRYPTO) + error ("-mcrypto requires -maltivec"); + rs6000_isa_flags &= ~OPTION_MASK_CRYPTO; + } + + if (TARGET_DIRECT_MOVE && !TARGET_VSX) + { + if (rs6000_isa_flags_explicit & OPTION_MASK_DIRECT_MOVE) + error ("-mdirect-move requires -mvsx"); + rs6000_isa_flags &= ~OPTION_MASK_DIRECT_MOVE; + } + + if (TARGET_P8_VECTOR && !TARGET_ALTIVEC) + { + if (rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR) + error ("-mpower8-vector requires -maltivec"); + rs6000_isa_flags &= ~OPTION_MASK_P8_VECTOR; + } + + if (TARGET_P8_VECTOR && !TARGET_VSX) + { + if (rs6000_isa_flags_explicit & OPTION_MASK_P8_VECTOR) + error ("-mpower8-vector requires -mvsx"); + rs6000_isa_flags &= ~OPTION_MASK_P8_VECTOR; + } + if (TARGET_VSX_TIMODE && !TARGET_VSX) { if (rs6000_isa_flags_explicit & OPTION_MASK_VSX_TIMODE) @@ -3019,16 +3109,19 @@ rs6000_option_override_internal (bool gl && rs6000_cpu != PROCESSOR_POWER5 && rs6000_cpu != PROCESSOR_POWER6 && rs6000_cpu != PROCESSOR_POWER7 + && rs6000_cpu != PROCESSOR_POWER8 && rs6000_cpu != PROCESSOR_PPCA2 && rs6000_cpu != PROCESSOR_CELL && rs6000_cpu != PROCESSOR_PPC476); rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4 || rs6000_cpu == PROCESSOR_POWER5 - || rs6000_cpu == PROCESSOR_POWER7); + || rs6000_cpu == PROCESSOR_POWER7 + || rs6000_cpu == PROCESSOR_POWER8); rs6000_align_branch_targets = (rs6000_cpu == PROCESSOR_POWER4 || rs6000_cpu == PROCESSOR_POWER5 || rs6000_cpu == PROCESSOR_POWER6 || rs6000_cpu == PROCESSOR_POWER7 + || rs6000_cpu == PROCESSOR_POWER8 || rs6000_cpu == PROCESSOR_PPCE500MC || rs6000_cpu == PROCESSOR_PPCE500MC64 || rs6000_cpu == PROCESSOR_PPCE5500 @@ -3272,6 +3365,10 @@ rs6000_option_override_internal (bool gl rs6000_cost = &power7_cost; break; + case PROCESSOR_POWER8: + rs6000_cost = &power8_cost; + break; + case PROCESSOR_PPCA2: rs6000_cost = &ppca2_cost; break; @@ -3444,7 +3541,8 @@ rs6000_loop_align (rtx label) && (rs6000_cpu == PROCESSOR_POWER4 || rs6000_cpu == PROCESSOR_POWER5 || rs6000_cpu == PROCESSOR_POWER6 - || rs6000_cpu == PROCESSOR_POWER7)) + || rs6000_cpu == PROCESSOR_POWER7 + || rs6000_cpu == PROCESSOR_POWER8)) return 5; else return align_loops_log; @@ -12891,8 +12989,23 @@ rs6000_common_init_builtins (void) else { enum insn_code icode = d->icode; - if (d->name == 0 || icode == CODE_FOR_nothing) - continue; + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, bdesc_3arg[%ld] no name\n", + (long unsigned)i); + + continue; + } + + if (icode == CODE_FOR_nothing) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip ternary %s (no code)\n", + d->name); + + continue; + } type = builtin_function_type (insn_data[icode].operand[0].mode, insn_data[icode].operand[1].mode, @@ -12931,8 +13044,23 @@ rs6000_common_init_builtins (void) else { enum insn_code icode = d->icode; - if (d->name == 0 || icode == CODE_FOR_nothing) - continue; + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, bdesc_2arg[%ld] no name\n", + (long unsigned)i); + + continue; + } + + if (icode == CODE_FOR_nothing) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip binary %s (no code)\n", + d->name); + + continue; + } mode0 = insn_data[icode].operand[0].mode; mode1 = insn_data[icode].operand[1].mode; @@ -12993,8 +13121,23 @@ rs6000_common_init_builtins (void) else { enum insn_code icode = d->icode; - if (d->name == 0 || icode == CODE_FOR_nothing) - continue; + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, bdesc_1arg[%ld] no name\n", + (long unsigned)i); + + continue; + } + + if (icode == CODE_FOR_nothing) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "rs6000_builtin, skip unary %s (no code)\n", + d->name); + + continue; + } mode0 = insn_data[icode].operand[0].mode; mode1 = insn_data[icode].operand[1].mode; @@ -22951,6 +23094,7 @@ rs6000_adjust_cost (rtx insn, rtx link, || rs6000_cpu_attr == CPU_POWER4 || rs6000_cpu_attr == CPU_POWER5 || rs6000_cpu_attr == CPU_POWER7 + || rs6000_cpu_attr == CPU_POWER8 || rs6000_cpu_attr == CPU_CELL) && recog_memoized (dep_insn) && (INSN_CODE (dep_insn) >= 0)) @@ -23537,6 +23681,8 @@ rs6000_issue_rate (void) case CPU_POWER6: case CPU_POWER7: return 5; + case CPU_POWER8: + return 7; default: return 1; } @@ -24130,6 +24276,7 @@ insn_must_be_first_in_group (rtx insn) } break; case PROCESSOR_POWER7: + case PROCESSOR_POWER8: /* FIXME */ type = get_attr_type (insn); switch (type) @@ -24226,6 +24373,7 @@ insn_must_be_last_in_group (rtx insn) } break; case PROCESSOR_POWER7: + case PROCESSOR_POWER8: /* FIXME */ type = get_attr_type (insn); switch (type) @@ -24332,7 +24480,8 @@ force_new_group (int sched_verbose, FILE can_issue_more--; /* Power6 and Power7 have special group ending nop. */ - if (rs6000_cpu_attr == CPU_POWER6 || rs6000_cpu_attr == CPU_POWER7) + if (rs6000_cpu_attr == CPU_POWER6 || rs6000_cpu_attr == CPU_POWER7 + || rs6000_cpu_attr == CPU_POWER8) { nop = gen_group_ending_nop (); emit_insn_before (nop, next_insn); @@ -26513,7 +26662,8 @@ rs6000_register_move_cost (enum machine_ /* For those processors that have slow LR/CTR moves, make them more expensive than memory in order to bias spills to memory .*/ else if ((rs6000_cpu == PROCESSOR_POWER6 - || rs6000_cpu == PROCESSOR_POWER7) + || rs6000_cpu == PROCESSOR_POWER7 + || rs6000_cpu == PROCESSOR_POWER8) && reg_classes_intersect_p (rclass, LINK_OR_CTR_REGS)) ret = 6 * hard_regno_nregs[0][mode]; @@ -27742,6 +27892,8 @@ static struct rs6000_opt_mask const rs60 { { "altivec", OPTION_MASK_ALTIVEC, false, true }, { "cmpb", OPTION_MASK_CMPB, false, true }, + { "crypto", OPTION_MASK_CRYPTO, false, true }, + { "direct-move", OPTION_MASK_DIRECT_MOVE, false, true }, { "dlmzb", OPTION_MASK_DLMZB, false, true }, { "fprnd", OPTION_MASK_FPRND, false, true }, { "hard-dfp", OPTION_MASK_DFP, false, true }, @@ -27750,13 +27902,17 @@ static struct rs6000_opt_mask const rs60 { "mfpgpr", OPTION_MASK_MFPGPR, false, true }, { "mulhw", OPTION_MASK_MULHW, false, true }, { "multiple", OPTION_MASK_MULTIPLE, false, true }, - { "update", OPTION_MASK_NO_UPDATE, true , true }, { "popcntb", OPTION_MASK_POPCNTB, false, true }, { "popcntd", OPTION_MASK_POPCNTD, false, true }, + { "power8-fusion", OPTION_MASK_P8_FUSION, false, true }, + { "power8-fusion-sign", OPTION_MASK_P8_FUSION_SIGN, false, true }, + { "power8-vector", OPTION_MASK_P8_VECTOR, false, true }, { "powerpc-gfxopt", OPTION_MASK_PPC_GFXOPT, false, true }, { "powerpc-gpopt", OPTION_MASK_PPC_GPOPT, false, true }, + { "quad-memory", OPTION_MASK_QUAD_MEMORY, false, true }, { "recip-precision", OPTION_MASK_RECIP_PRECISION, false, true }, { "string", OPTION_MASK_STRING, false, true }, + { "update", OPTION_MASK_NO_UPDATE, true , true }, { "vsx", OPTION_MASK_VSX, false, true }, { "vsx-timode", OPTION_MASK_VSX_TIMODE, false, true }, #ifdef OPTION_MASK_64BIT @@ -27798,6 +27954,8 @@ static struct rs6000_opt_mask const rs60 { "frsqrtes", RS6000_BTM_FRSQRTES, false, false }, { "popcntd", RS6000_BTM_POPCNTD, false, false }, { "cell", RS6000_BTM_CELL, false, false }, + { "power8-vector", RS6000_BTM_P8_VECTOR, false, false }, + { "crypto", RS6000_BTM_CRYPTO, false, false }, }; /* Option variables that we want to support inside attribute((target)) and Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 199037) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -92,7 +92,7 @@ #ifdef HAVE_AS_POWER8 #define ASM_CPU_POWER8_SPEC "-mpower8" #else -#define ASM_CPU_POWER8_SPEC "-mpower4 -maltivec" +#define ASM_CPU_POWER8_SPEC ASM_CPU_POWER7_SPEC #endif #ifdef HAVE_AS_DCI @@ -164,6 +164,7 @@ %{mcpu=e6500: -me6500} \ %{maltivec: -maltivec} \ %{mvsx: -mvsx %{!maltivec: -maltivec} %{!mcpu*: %(asm_cpu_power7)}} \ +%{mpower8-vector|mcrypto|mdirect-move: %{!mcpu*: %(asm_cpu_power8)}} \ -many" #define CPP_DEFAULT_SPEC "" @@ -277,6 +278,19 @@ extern const char *host_detect_local_cpu #define TARGET_POPCNTD 0 #endif +/* Define the ISA 2.07 flags as 0 if the target assembler does not support the + waitasecond instruction. Allow -mpower8-fusion, since it does not add new + instructions. */ + +#ifndef HAVE_AS_POWER8 +#undef TARGET_DIRECT_MOVE +#undef TARGET_CRYPTO +#undef TARGET_P8_VECTOR +#define TARGET_DIRECT_MOVE 0 +#define TARGET_CRYPTO 0 +#define TARGET_P8_VECTOR 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 @@ -386,6 +400,7 @@ extern const char *host_detect_local_cpu #define TARGET_DEBUG_TARGET (rs6000_debug & MASK_DEBUG_TARGET) #define TARGET_DEBUG_BUILTIN (rs6000_debug & MASK_DEBUG_BUILTIN) +/* Describe the vector unit used for arithmetic operations. */ extern enum rs6000_vector rs6000_vector_unit[]; #define VECTOR_UNIT_NONE_P(MODE) \ @@ -394,12 +409,25 @@ extern enum rs6000_vector rs6000_vector_ #define VECTOR_UNIT_VSX_P(MODE) \ (rs6000_vector_unit[(MODE)] == VECTOR_VSX) +#define VECTOR_UNIT_P8_VECTOR_P(MODE) \ + (rs6000_vector_unit[(MODE)] == VECTOR_P8_VECTOR) + #define VECTOR_UNIT_ALTIVEC_P(MODE) \ (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC) +#define VECTOR_UNIT_VSX_OR_P8_VECTOR_P(MODE) \ + (IN_RANGE ((int)rs6000_vector_unit[(MODE)], \ + (int)VECTOR_VSX, \ + (int)VECTOR_P8_VECTOR)) + +/* VECTOR_UNIT_ALTIVEC_OR_VSX_P is used in places where we are using either + altivec (VMX) or VSX vector instructions. P8 vector support is upwards + compatible, so allow it as well, rather than changing all of the uses of the + macro. */ #define VECTOR_UNIT_ALTIVEC_OR_VSX_P(MODE) \ - (rs6000_vector_unit[(MODE)] == VECTOR_ALTIVEC \ - || rs6000_vector_unit[(MODE)] == VECTOR_VSX) + (IN_RANGE ((int)rs6000_vector_unit[(MODE)], \ + (int)VECTOR_ALTIVEC, \ + (int)VECTOR_P8_VECTOR)) /* 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 @@ -412,12 +440,21 @@ extern enum rs6000_vector rs6000_vector_ #define VECTOR_MEM_VSX_P(MODE) \ (rs6000_vector_mem[(MODE)] == VECTOR_VSX) +#define VECTOR_MEM_P8_VECTOR_P(MODE) \ + (rs6000_vector_mem[(MODE)] == VECTOR_VSX) + #define VECTOR_MEM_ALTIVEC_P(MODE) \ (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC) +#define VECTOR_MEM_VSX_OR_P8_VECTOR_P(MODE) \ + (IN_RANGE ((int)rs6000_vector_mem[(MODE)], \ + (int)VECTOR_VSX, \ + (int)VECTOR_P8_VECTOR)) + #define VECTOR_MEM_ALTIVEC_OR_VSX_P(MODE) \ - (rs6000_vector_mem[(MODE)] == VECTOR_ALTIVEC \ - || rs6000_vector_mem[(MODE)] == VECTOR_VSX) + (IN_RANGE ((int)rs6000_vector_mem[(MODE)], \ + (int)VECTOR_ALTIVEC, \ + (int)VECTOR_P8_VECTOR)) /* 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 @@ -479,6 +516,15 @@ extern int rs6000_vector_align[]; #define TARGET_FCTIDUZ TARGET_POPCNTD #define TARGET_FCTIWUZ TARGET_POPCNTD +#define TARGET_XSCVDPSPN (TARGET_DIRECT_MOVE || TARGET_P8_VECTOR) +#define TARGET_XSCVSPDPN (TARGET_DIRECT_MOVE || TARGET_P8_VECTOR) + +/* Byte/char syncs were added as phased in for ISA 2.06B, but are not present + in power7, so conditionalize them on p8 features. TImode syncs need quad + memory support. */ +#define TARGET_SYNC_HI_QI (TARGET_QUAD_MEMORY || TARGET_DIRECT_MOVE) +#define TARGET_SYNC_TI TARGET_QUAD_MEMORY + /* Power7 has both 32-bit load and store integer for the FPRs, so we don't need to allocate the SDmode stack slot to get the value into the proper location in the register. */ @@ -489,10 +535,13 @@ extern int rs6000_vector_align[]; OPTION_MASK_<xxx> back into MASK_<xxx>. */ #define MASK_ALTIVEC OPTION_MASK_ALTIVEC #define MASK_CMPB OPTION_MASK_CMPB +#define MASK_CRYPTO OPTION_MASK_CRYPTO #define MASK_DFP OPTION_MASK_DFP +#define MASK_DIRECT_MOVE OPTION_MASK_DIRECT_MOVE #define MASK_DLMZB OPTION_MASK_DLMZB #define MASK_EABI OPTION_MASK_EABI #define MASK_FPRND OPTION_MASK_FPRND +#define MASK_P8_FUSION OPTION_MASK_P8_FUSION #define MASK_HARD_FLOAT OPTION_MASK_HARD_FLOAT #define MASK_ISEL OPTION_MASK_ISEL #define MASK_MFCRF OPTION_MASK_MFCRF @@ -500,6 +549,7 @@ extern int rs6000_vector_align[]; #define MASK_MULHW OPTION_MASK_MULHW #define MASK_MULTIPLE OPTION_MASK_MULTIPLE #define MASK_NO_UPDATE OPTION_MASK_NO_UPDATE +#define MASK_P8_VECTOR OPTION_MASK_P8_VECTOR #define MASK_POPCNTB OPTION_MASK_POPCNTB #define MASK_POPCNTD OPTION_MASK_POPCNTD #define MASK_PPC_GFXOPT OPTION_MASK_PPC_GFXOPT @@ -1002,7 +1052,9 @@ extern unsigned rs6000_pointer_size; #define REG_ALLOC_ORDER \ {32, \ - 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \ + /* move fr13 (ie 45) later, so if we need TFmode, it does */ \ + /* not use fr14 which is a saved register. */ \ + 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 45, \ 33, \ 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \ 50, 49, 48, 47, 46, \ @@ -1062,8 +1114,14 @@ extern unsigned rs6000_pointer_size; #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) + matter which instruction set(s) are available. Under VSX, we allow GPRs as + well as vector registers on 64-bit systems. We don't allow 32-bit systems, + due to the number of registers involved, and the number of instructions to + load/store the values.. */ +#define VLOGICAL_REGNO_P(N) \ + (ALTIVEC_REGNO_P (N) \ + || (TARGET_VSX && FP_REGNO_P (N)) \ + || (TARGET_VSX && TARGET_POWERPC64 && INT_REGNO_P (N))) /* Return number of consecutive hard regs needed starting at reg REGNO to hold something of mode MODE. */ @@ -1124,7 +1182,7 @@ extern unsigned rs6000_pointer_size; when one has mode MODE1 and one has mode MODE2. If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, for any hard reg, then this must be 0 for correct output. */ -#define MODES_TIEABLE_P(MODE1, MODE2) \ +#define MODES_TIEABLE_P(MODE1, MODE2) \ (SCALAR_FLOAT_MODE_P (MODE1) \ ? SCALAR_FLOAT_MODE_P (MODE2) \ : SCALAR_FLOAT_MODE_P (MODE2) \ @@ -1137,14 +1195,14 @@ extern unsigned rs6000_pointer_size; ? SPE_VECTOR_MODE (MODE2) \ : SPE_VECTOR_MODE (MODE2) \ ? SPE_VECTOR_MODE (MODE1) \ - : ALTIVEC_VECTOR_MODE (MODE1) \ - ? ALTIVEC_VECTOR_MODE (MODE2) \ - : ALTIVEC_VECTOR_MODE (MODE2) \ - ? ALTIVEC_VECTOR_MODE (MODE1) \ : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1) \ ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2) \ : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2) \ ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE1) \ + : ALTIVEC_VECTOR_MODE (MODE1) \ + ? ALTIVEC_VECTOR_MODE (MODE2) \ + : ALTIVEC_VECTOR_MODE (MODE2) \ + ? ALTIVEC_VECTOR_MODE (MODE1) \ : 1) /* Post-reload, we can't use any new AltiVec registers, as we already @@ -1337,8 +1395,11 @@ enum r6000_reg_class_enum { RS6000_CONSTRAINT_wg, /* FPR register for -mmfpgpr */ RS6000_CONSTRAINT_wf, /* VSX register for V4SF */ RS6000_CONSTRAINT_wl, /* FPR register for LFIWAX */ + RS6000_CONSTRAINT_wm, /* VSX register for direct move */ + RS6000_CONSTRAINT_wr, /* GPR register if 64-bit */ RS6000_CONSTRAINT_ws, /* VSX register for DF */ RS6000_CONSTRAINT_wt, /* VSX register for TImode */ + RS6000_CONSTRAINT_wv, /* Altivec register for power8 vector */ RS6000_CONSTRAINT_wx, /* FPR register for STFIWX */ RS6000_CONSTRAINT_wz, /* FPR register for LFIWZX */ RS6000_CONSTRAINT_MAX @@ -2365,6 +2426,8 @@ extern int frame_pointer_needed; #define RS6000_BTM_ALWAYS 0 /* Always enabled. */ #define RS6000_BTM_ALTIVEC MASK_ALTIVEC /* VMX/altivec vectors. */ #define RS6000_BTM_VSX MASK_VSX /* VSX (vector/scalar). */ +#define RS6000_BTM_P8_VECTOR MASK_P8_VECTOR /* ISA 2.07 vector. */ +#define RS6000_BTM_CRYPTO MASK_CRYPTO /* crypto funcs. */ #define RS6000_BTM_SPE MASK_STRING /* E500 */ #define RS6000_BTM_PAIRED MASK_MULHW /* 750CL paired insns. */ #define RS6000_BTM_FRE MASK_POPCNTB /* FRE instruction. */ @@ -2376,6 +2439,8 @@ extern int frame_pointer_needed; #define RS6000_BTM_COMMON (RS6000_BTM_ALTIVEC \ | RS6000_BTM_VSX \ + | RS6000_BTM_P8_VECTOR \ + | RS6000_BTM_CRYPTO \ | RS6000_BTM_FRE \ | RS6000_BTM_FRES \ | RS6000_BTM_FRSQRTE \ Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 199037) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -168,7 +168,7 @@ (define_attr "length" "" ;; Processor type -- this attribute must exactly match the processor_type ;; enumeration in rs6000.h. -(define_attr "cpu" "rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,power4,power5,power6,power7,cell,ppca2,titan" +(define_attr "cpu" "rs64a,mpccore,ppc403,ppc405,ppc440,ppc476,ppc601,ppc603,ppc604,ppc604e,ppc620,ppc630,ppc750,ppc7400,ppc7450,ppc8540,ppc8548,ppce300c2,ppce300c3,ppce500mc,ppce500mc64,ppce5500,ppce6500,power4,power5,power6,power7,cell,ppca2,titan,power8" (const (symbol_ref "rs6000_cpu_attr"))) Index: gcc/config/rs6000/rs6000-opts.h =================================================================== --- gcc/config/rs6000/rs6000-opts.h (revision 199037) +++ gcc/config/rs6000/rs6000-opts.h (working copy) @@ -59,7 +59,8 @@ enum processor_type PROCESSOR_POWER7, PROCESSOR_CELL, PROCESSOR_PPCA2, - PROCESSOR_TITAN + PROCESSOR_TITAN, + PROCESSOR_POWER8 }; /* FP processor type. */ @@ -131,11 +132,14 @@ enum rs6000_cmodel { CMODEL_LARGE }; -/* Describe which vector unit to use for a given machine mode. */ +/* Describe which vector unit to use for a given machine mode. The + VECTOR_MEM_* and VECTOR_UNIT_* macros assume that Altivec, VSX, and + P8_VECTOR are contiguous. */ 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_P8_VECTOR, /* Use ISA 2.07 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 */