From: Michael Meissner Date: Mon, 3 Aug 2015 17:06:24 +0000 (+0000) Subject: vector.md (VEC_L): Add KFmode and TFmode. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c477a66743648570f3a768e49723b5c2f8bc7633;p=gcc.git vector.md (VEC_L): Add KFmode and TFmode. 2015-08-03 Michael Meissner * config/rs6000/vector.md (VEC_L): Add KFmode and TFmode. (VEC_M): Likewise. (VEC_N): Likewise. (mov, VEC_M iterator): Add support for IEEE 128-bit floating point in VSX registers. * config/rs6000/constraints.md (wb constraint): Document unused w constraint. (we constraint): Likewise. (wo constraint): Likewise. (wp constraint): New constraint for IEEE 128-bit floating point in VSX registers. (wq constraint): Likewise. * config/rs6000/predicates.md (easy_fp_constant): Add support for IEEE 128-bit floating point in VSX registers. (easy_scalar_constant): Likewise. * config/rs6000/rs6000.c (rs6000_debug_reg_global): Add new constraints (wp, wq) for IEEE 128-bit floating point in VSX registers. (rs6000_init_hard_regno_mode_ok): Likewise. * config/rs6000/vsx.md (VSX_LE_128): Add support for IEEE 128-bit floating point in VSX registers. (VSX_L): Likewise. (VSX_M): Likewise. (VSX_M2): Likewise. (VSm): Likewise. (VSs): Likewise. (VSr): Likewise. (VSa): Likewise. (VSv): Likewise. (vsx_le_permute_): Add support to properly swap bytes for IEEE 128-bit floating point in VSX registers on little endian. (vsx_le_undo_permute_): Likewise. (vsx_le_perm_load_): Likewise. (vsx_le_perm_store_): Likewise. (splitters for IEEE 128-bit fp moves): Likewise. * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add wp and wq constraints. * config/rs6000/altivec.md (VM): Add support for IEEE 128-bit floating point in VSX registers. (VM2): Likewise. * doc/md.text (Machine Constraints): Document wp and wq constraints on PowerPC. From-SVN: r226520 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9abde9f9124..770848af4fa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,55 @@ +2015-08-03 Michael Meissner + + * config/rs6000/vector.md (VEC_L): Add KFmode and TFmode. + (VEC_M): Likewise. + (VEC_N): Likewise. + (mov, VEC_M iterator): Add support for IEEE 128-bit floating + point in VSX registers. + + * config/rs6000/constraints.md (wb constraint): Document unused + w constraint. + (we constraint): Likewise. + (wo constraint): Likewise. + (wp constraint): New constraint for IEEE 128-bit floating point in + VSX registers. + (wq constraint): Likewise. + + * config/rs6000/predicates.md (easy_fp_constant): Add support for + IEEE 128-bit floating point in VSX registers. + (easy_scalar_constant): Likewise. + + * config/rs6000/rs6000.c (rs6000_debug_reg_global): Add new + constraints (wp, wq) for IEEE 128-bit floating point in VSX + registers. + (rs6000_init_hard_regno_mode_ok): Likewise. + + * config/rs6000/vsx.md (VSX_LE_128): Add support for IEEE 128-bit + floating point in VSX registers. + (VSX_L): Likewise. + (VSX_M): Likewise. + (VSX_M2): Likewise. + (VSm): Likewise. + (VSs): Likewise. + (VSr): Likewise. + (VSa): Likewise. + (VSv): Likewise. + (vsx_le_permute_): Add support to properly swap bytes for + IEEE 128-bit floating point in VSX registers on little endian. + (vsx_le_undo_permute_): Likewise. + (vsx_le_perm_load_): Likewise. + (vsx_le_perm_store_): Likewise. + (splitters for IEEE 128-bit fp moves): Likewise. + + * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add wp and + wq constraints. + + * config/rs6000/altivec.md (VM): Add support for IEEE 128-bit + floating point in VSX registers. + (VM2): Likewise. + + * doc/md.text (Machine Constraints): Document wp and wq + constraints on PowerPC. + 2015-08-03 Jeff Law PR middle-end/66314 diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 5cc0b0359e0..a8ea0fbdfe1 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -167,10 +167,27 @@ (define_mode_iterator V [V4SI V8HI V16QI V4SF]) ;; Vec modes for move/logical/permute ops, include vector types for move not ;; otherwise handled by altivec (v2df, v2di, ti) -(define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI V1TI TI]) +(define_mode_iterator VM [V4SI + V8HI + V16QI + V4SF + V2DF + V2DI + V1TI + TI + (KF "FLOAT128_VECTOR_P (KFmode)") + (TF "FLOAT128_VECTOR_P (TFmode)")]) ;; Like VM, except don't do TImode -(define_mode_iterator VM2 [V4SI V8HI V16QI V4SF V2DF V2DI V1TI]) +(define_mode_iterator VM2 [V4SI + V8HI + V16QI + V4SF + V2DF + V2DI + V1TI + (KF "FLOAT128_VECTOR_P (KFmode)") + (TF "FLOAT128_VECTOR_P (TFmode)")]) (define_mode_attr VI_char [(V2DI "d") (V4SI "w") (V8HI "h") (V16QI "b")]) (define_mode_attr VI_scalar [(V2DI "DI") (V4SI "SI") (V8HI "HI") (V16QI "QI")]) diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md index 893a826dcba..2b8f4bb6066 100644 --- a/gcc/config/rs6000/constraints.md +++ b/gcc/config/rs6000/constraints.md @@ -56,12 +56,16 @@ (define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]" "Any VSX register if the -mvsx option was used or NO_REGS.") +;; wb is not currently used + ;; NOTE: For compatibility, "wc" is reserved to represent individual CR bits. ;; It is currently used for that purpose in LLVM. (define_register_constraint "wd" "rs6000_constraints[RS6000_CONSTRAINT_wd]" "VSX vector register to hold vector double data or NO_REGS.") +;; we is not currently used + (define_register_constraint "wf" "rs6000_constraints[RS6000_CONSTRAINT_wf]" "VSX vector register to hold vector float data or NO_REGS.") @@ -93,6 +97,14 @@ ;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode (define_register_constraint "wn" "NO_REGS" "No register (NO_REGS).") +;; wo is not currently used + +(define_register_constraint "wp" "rs6000_constraints[RS6000_CONSTRAINT_wp]" + "VSX register to use for IEEE 128-bit fp TFmode, or NO_REGS.") + +(define_register_constraint "wq" "rs6000_constraints[RS6000_CONSTRAINT_wq]" + "VSX register to use for IEEE 128-bit fp KFmode, or NO_REGS.") + (define_register_constraint "wr" "rs6000_constraints[RS6000_CONSTRAINT_wr]" "General purpose register if 64-bit instructions are enabled or NO_REGS.") diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 2adeee7be31..5a6bb70c59f 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -460,6 +460,8 @@ switch (mode) { + case KFmode: + case IFmode: case TFmode: case DFmode: case SFmode: @@ -486,6 +488,12 @@ if (TARGET_PAIRED_FLOAT) return false; + /* Because IEEE 128-bit floating point is considered a vector type + in order to pass it in VSX registers, it might use this function + instead of easy_fp_constant. */ + if (FLOAT128_VECTOR_P (mode)) + return easy_fp_constant (op, mode); + if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)) { if (zero_constant (op, mode)) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 78de6452feb..bcd0cd074c1 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -2168,6 +2168,8 @@ rs6000_debug_reg_global (void) "wk reg_class = %s\n" "wl reg_class = %s\n" "wm reg_class = %s\n" + "wp reg_class = %s\n" + "wq reg_class = %s\n" "wr reg_class = %s\n" "ws reg_class = %s\n" "wt reg_class = %s\n" @@ -2191,6 +2193,8 @@ rs6000_debug_reg_global (void) reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wk]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wm]], + reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wp]], + reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wq]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]], @@ -2857,6 +2861,13 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p) if (TARGET_LFIWZX) rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS; /* DImode */ + if (TARGET_FLOAT128) + { + rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS; /* KFmode */ + if (rs6000_ieeequad) + rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS; /* TFmode */ + } + /* Set up the reload helper and direct move functions. */ if (TARGET_VSX || TARGET_ALTIVEC) { diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 1518457ad9f..102bbce1525 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1496,6 +1496,8 @@ enum r6000_reg_class_enum { RS6000_CONSTRAINT_wk, /* FPR/VSX register for DFmode direct moves. */ RS6000_CONSTRAINT_wl, /* FPR register for LFIWAX */ RS6000_CONSTRAINT_wm, /* VSX register for direct move */ + RS6000_CONSTRAINT_wp, /* VSX reg for IEEE 128-bit fp TFmode. */ + RS6000_CONSTRAINT_wq, /* VSX reg for IEEE 128-bit fp KFmode. */ RS6000_CONSTRAINT_wr, /* GPR register if 64-bit */ RS6000_CONSTRAINT_ws, /* VSX register for DF */ RS6000_CONSTRAINT_wt, /* VSX register for TImode */ diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md index 40d596b4381..4a62fbbbdd4 100644 --- a/gcc/config/rs6000/vector.md +++ b/gcc/config/rs6000/vector.md @@ -36,13 +36,14 @@ (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF]) ;; Vector logical modes -(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI]) +(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI KF TF]) -;; Vector modes for moves. Don't do TImode here. -(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI]) +;; Vector modes for moves. Don't do TImode or TFmode here, since their +;; moves are handled elsewhere. +(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI KF]) ;; Vector modes for types that don't need a realignment under VSX -(define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI]) +(define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI KF TF]) ;; Vector comparison modes (define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF]) @@ -95,12 +96,19 @@ { if (can_create_pseudo_p ()) { - if (CONSTANT_P (operands[1]) - && !easy_vector_constant (operands[1], mode)) - operands[1] = force_const_mem (mode, operands[1]); - - else if (!vlogical_operand (operands[0], mode) - && !vlogical_operand (operands[1], mode)) + if (CONSTANT_P (operands[1])) + { + if (FLOAT128_VECTOR_P (mode)) + { + if (!easy_fp_constant (operands[1], mode)) + operands[1] = force_const_mem (mode, operands[1]); + } + else if (!easy_vector_constant (operands[1], mode)) + operands[1] = force_const_mem (mode, operands[1]); + } + + if (!vlogical_operand (operands[0], mode) + && !vlogical_operand (operands[1], mode)) operands[1] = force_reg (mode, operands[1]); } if (!BYTES_BIG_ENDIAN diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index b7459a710a5..7f366b8d69a 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -31,6 +31,11 @@ V1TI (TI "VECTOR_MEM_VSX_P (TImode)")]) +;; Mode iterator to handle swapping words on little endian for the 128-bit +;; types that goes in a single vector register. +(define_mode_iterator VSX_LE_128 [(KF "FLOAT128_VECTOR_P (KFmode)") + (TF "FLOAT128_VECTOR_P (TFmode)")]) + ;; Iterator for the 2 32-bit vector types (define_mode_iterator VSX_W [V4SF V4SI]) @@ -41,11 +46,31 @@ (define_mode_iterator VSX_F [V4SF V2DF]) ;; Iterator for logical types supported by VSX -(define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI]) +;; Note, IFmode won't actually be used since it isn't a VSX type, but it simplifies +;; the code by using 128-bit iterators for floating point. +(define_mode_iterator VSX_L [V16QI + V8HI + V4SI + V2DI + V4SF + V2DF + V1TI + TI + (KF "FLOAT128_VECTOR_P (KFmode)") + (TF "FLOAT128_VECTOR_P (TFmode)") + (IF "FLOAT128_VECTOR_P (IFmode)")]) ;; Iterator for memory move. Handle TImode specially to allow ;; it to use gprs as well as vsx registers. -(define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI]) +(define_mode_iterator VSX_M [V16QI + V8HI + V4SI + V2DI + V4SF + V2DF + V1TI + (KF "FLOAT128_VECTOR_P (KFmode)") + (TF "FLOAT128_VECTOR_P (TFmode)")]) (define_mode_iterator VSX_M2 [V16QI V8HI @@ -54,6 +79,8 @@ V4SF V2DF V1TI + (KF "FLOAT128_VECTOR_P (KFmode)") + (TF "FLOAT128_VECTOR_P (TFmode)") (TI "TARGET_VSX_TIMODE")]) ;; Map into the appropriate load/store name based on the type @@ -64,6 +91,8 @@ (V2DF "vd2") (V2DI "vd2") (DF "d") + (TF "vd2") + (KF "vd2") (V1TI "vd2") (TI "vd2")]) @@ -76,6 +105,8 @@ (V2DI "dp") (DF "dp") (SF "sp") + (TF "dp") + (KF "dp") (V1TI "dp") (TI "dp")]) @@ -89,6 +120,8 @@ (DI "wi") (DF "ws") (SF "ww") + (TF "wp") + (KF "wq") (V1TI "v") (TI "wt")]) @@ -132,7 +165,9 @@ (DF "ws") (SF "ww") (V1TI "wa") - (TI "wt")]) + (TI "wt") + (TF "wp") + (KF "wq")]) ;; Same size integer type for floating point data (define_mode_attr VSi [(V4SF "v4si") @@ -157,7 +192,8 @@ (V2DI "v") (V2DF "v") (V1TI "v") - (DF "s")]) + (DF "s") + (KF "v")]) ;; Appropriate type for add ops (and other simple FP ops) (define_mode_attr VStype_simple [(V2DF "vecdouble") @@ -623,6 +659,105 @@ (const_int 6) (const_int 7)])))] "") +;; Little endian word swapping for 128-bit types that are either scalars or the +;; special V1TI container class, which it is not appropriate to use vec_select +;; for the type. +(define_insn "*vsx_le_permute_" + [(set (match_operand:VSX_LE_128 0 "nonimmediate_operand" "=,,Z") + (rotate:VSX_LE_128 + (match_operand:VSX_LE_128 1 "input_operand" ",Z,") + (const_int 64)))] + "!BYTES_BIG_ENDIAN && TARGET_VSX" + "@ + xxpermdi %x0,%x1,%x1,2 + lxvd2x %x0,%y1 + stxvd2x %x1,%y0" + [(set_attr "length" "4") + (set_attr "type" "vecperm,vecload,vecstore")]) + +(define_insn_and_split "*vsx_le_undo_permute_" + [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=,") + (rotate:VSX_LE_128 + (rotate:VSX_LE_128 + (match_operand:VSX_LE_128 1 "vsx_register_operand" "0,") + (const_int 64)) + (const_int 64)))] + "!BYTES_BIG_ENDIAN && TARGET_VSX" + "@ + # + xxlor %x0,%x1" + "" + [(set (match_dup 0) (match_dup 1))] +{ + if (reload_completed && REGNO (operands[0]) == REGNO (operands[1])) + { + emit_note (NOTE_INSN_DELETED); + DONE; + } +} + [(set_attr "length" "0,4") + (set_attr "type" "vecsimple")]) + +(define_insn_and_split "*vsx_le_perm_load_" + [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=") + (match_operand:VSX_LE_128 1 "memory_operand" "Z"))] + "!BYTES_BIG_ENDIAN && TARGET_VSX" + "#" + "!BYTES_BIG_ENDIAN && TARGET_VSX" + [(set (match_dup 2) + (rotate:VSX_LE_128 (match_dup 1) + (const_int 64))) + (set (match_dup 0) + (rotate:VSX_LE_128 (match_dup 2) + (const_int 64)))] + " +{ + operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0]) + : operands[0]; +} + " + [(set_attr "type" "vecload") + (set_attr "length" "8")]) + +(define_insn "*vsx_le_perm_store_" + [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z") + (match_operand:VSX_LE_128 1 "vsx_register_operand" "+"))] + "!BYTES_BIG_ENDIAN && TARGET_VSX" + "#" + [(set_attr "type" "vecstore") + (set_attr "length" "12")]) + +(define_split + [(set (match_operand:VSX_LE_128 0 "memory_operand" "") + (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed" + [(set (match_dup 2) + (rotate:VSX_LE_128 (match_dup 1) + (const_int 64))) + (set (match_dup 0) + (rotate:VSX_LE_128 (match_dup 2) + (const_int 64)))] +{ + operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0]) + : operands[0]; +}) + +;; The post-reload split requires that we re-permute the source +;; register in case it is still live. +(define_split + [(set (match_operand:VSX_LE_128 0 "memory_operand" "") + (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed" + [(set (match_dup 1) + (rotate:VSX_LE_128 (match_dup 1) + (const_int 64))) + (set (match_dup 0) + (rotate:VSX_LE_128 (match_dup 1) + (const_int 64))) + (set (match_dup 1) + (rotate:VSX_LE_128 (match_dup 1) + (const_int 64)))] + "") (define_insn "*vsx_mov" [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,,,?Z,?,?,wQ,?&r,??Y,??r,??r,,?,*r,v,wZ, v") diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 0ec229ff381..0bffdc63388 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -3087,12 +3087,13 @@ Any VSX register if the -mvsx option was used or NO_REGS. When using any of the register constraints (@code{wa}, @code{wd}, @code{wf}, @code{wg}, @code{wh}, @code{wi}, @code{wj}, @code{wk}, -@code{wl}, @code{wm}, @code{ws}, @code{wt}, @code{wu}, @code{wv}, -@code{ww}, or @code{wy}) that take VSX registers, you must use -@code{%x} in the template so that the correct register is used. -Otherwise the register number output in the assembly file will be -incorrect if an Altivec register is an operand of a VSX instruction -that expects VSX register numbering. +@code{wl}, @code{wm}, @code{wp}, @code{wq}, @code{ws}, @code{wt}, +@code{wu}, @code{wv}, @code{ww}, or @code{wy}) +that take VSX registers, you must use @code{%x} in the template so +that the correct register is used. Otherwise the register number +output in the assembly file will be incorrect if an Altivec register +is an operand of a VSX instruction that expects VSX register +numbering. @smallexample asm ("xvadddp %x0,%x1,%x2" : "=wa" (v1) : "wa" (v2), "wa" (v3)); @@ -3136,6 +3137,12 @@ VSX register if direct move instructions are enabled, or NO_REGS. @item wn No register (NO_REGS). +@item wp +VSX register to use for IEEE 128-bit floating point TFmode, or NO_REGS. + +@item wq +VSX register to use for IEEE 128-bit floating point, or NO_REGS. + @item wr General purpose register if 64-bit instructions are enabled or NO_REGS.