From c75d6010b052d367dbd4b53c7615e09cf4f1bf5a Mon Sep 17 00:00:00 2001 From: "James A. Morrison" Date: Tue, 9 Nov 2004 17:06:03 +0000 Subject: [PATCH] re PR target/18230 (SPARC VIS instructions are not generated by GCC) PR target/18230 * doc/md.texi (SPARC constraints): Document 'Y' constraint. * config/sparc/sparc-modes.def: Add vector modes of 4 and 8 bytes. * config/sparc/sparc.c (sparc_vector_mode_supported_p): New function. (TARGET_VECTOR_MODE_SUPPORTED_P): Set to sparc_vector_mode_supported_p. (fp_zero_operand): Accept MODE_VECTOR_INT modes. (input_operand): Accept CONST_VECTOR with MODE_VECTOR_INT modes. (sparc_cannot_force_const_mem): Return false for CONST_VECTOR. (sparc_init_modes): Set sparc_mode_class to SF_MODE or DF_MODE for MODE_VECTOR_INT modes. (sparc_extra_constraint_check): Add new constraint 'Y'. * config/sparc/sparc.h: Define UNITS_PER_SIMD_WORD to 8 for TARGET_VIS. * config/sparc/sparc.md (V32): New mode macro for 32-bit modes. (V64): New mode macro for 64-bit modes. (movsf): Use V32 for mode instead of SF. (movsf_insn_vis): Use V32 for mode instead of SF. Add 'Y' constraint alongside 'G' constraint. (movdf): Use V64 for mode instead of DF. (movdf_insn_v9only_vis, modf_insn_sp64_vis): Use V64 for mode instead of DF. Add 'Y' constraint alongside 'G' constraint. (multi-isn and misaligned mems DFmode splitters): Use V64 for mode instead of DF. Co-Authored-By: Eric Botcazou From-SVN: r90348 --- gcc/ChangeLog | 26 ++++ gcc/config/sparc/sparc-modes.def | 6 +- gcc/config/sparc/sparc.c | 33 ++++- gcc/config/sparc/sparc.h | 6 +- gcc/config/sparc/sparc.md | 221 ++++++++++++++++++------------- gcc/doc/md.texi | 5 +- 6 files changed, 202 insertions(+), 95 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1816d81f1cb..5ce802b6d14 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2004-11-09 James A. Morrison + Eric Botcazou + + PR target/18230 + * doc/md.texi (SPARC constraints): Document 'Y' constraint. + * config/sparc/sparc-modes.def: Add vector modes of 4 and 8 bytes. + * config/sparc/sparc.c (sparc_vector_mode_supported_p): New function. + (TARGET_VECTOR_MODE_SUPPORTED_P): Set to sparc_vector_mode_supported_p. + (fp_zero_operand): Accept MODE_VECTOR_INT modes. + (input_operand): Accept CONST_VECTOR with MODE_VECTOR_INT modes. + (sparc_cannot_force_const_mem): Return false for CONST_VECTOR. + (sparc_init_modes): Set sparc_mode_class to SF_MODE or DF_MODE for + MODE_VECTOR_INT modes. + (sparc_extra_constraint_check): Add new constraint 'Y'. + * config/sparc/sparc.h: Define UNITS_PER_SIMD_WORD to 8 for TARGET_VIS. + * config/sparc/sparc.md (V32): New mode macro for 32-bit modes. + (V64): New mode macro for 64-bit modes. + (movsf): Use V32 for mode instead of SF. + (movsf_insn_vis): Use V32 for mode instead of SF. Add 'Y' constraint + alongside 'G' constraint. + (movdf): Use V64 for mode instead of DF. + (movdf_insn_v9only_vis, modf_insn_sp64_vis): Use V64 for mode instead + of DF. Add 'Y' constraint alongside 'G' constraint. + (multi-isn and misaligned mems DFmode splitters): Use V64 for mode + instead of DF. + 2004-11-09 Ulrich Weigand * config/s390/s390.c (s390_select_ccmode): Return CCAPmode for diff --git a/gcc/config/sparc/sparc-modes.def b/gcc/config/sparc/sparc-modes.def index ea2a99d5ae1..bf85aed5bec 100644 --- a/gcc/config/sparc/sparc-modes.def +++ b/gcc/config/sparc/sparc-modes.def @@ -1,5 +1,5 @@ /* Definitions of target machine for GCC, for Sun SPARC. - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com). 64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans, at Cygnus Support. @@ -42,3 +42,7 @@ CC_MODE (CC_NOOV); CC_MODE (CCX_NOOV); CC_MODE (CCFP); CC_MODE (CCFPE); + +/* Vector modes. */ +VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */ +VECTOR_MODES (INT, 4); /* V4QI V2HI */ diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 5c5b3267b4e..0f3488492ed 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -348,6 +348,7 @@ static rtx sparc_struct_value_rtx (tree, int); static bool sparc_return_in_memory (tree, tree); static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *); static tree sparc_gimplify_va_arg (tree, tree, tree *, tree *); +static bool sparc_vector_mode_supported_p (enum machine_mode); static bool sparc_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, tree, bool); #ifdef SUBTARGET_ATTRIBUTE_TABLE @@ -466,6 +467,9 @@ enum processor_type sparc_cpu; #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR sparc_gimplify_va_arg +#undef TARGET_VECTOR_MODE_SUPPORTED_P +#define TARGET_VECTOR_MODE_SUPPORTED_P sparc_vector_mode_supported_p + #ifdef SUBTARGET_INSERT_ATTRIBUTES #undef TARGET_INSERT_ATTRIBUTES #define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES @@ -769,7 +773,8 @@ const1_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) int fp_zero_operand (rtx op, enum machine_mode mode) { - if (GET_MODE_CLASS (GET_MODE (op)) != MODE_FLOAT) + enum mode_class mclass = GET_MODE_CLASS (GET_MODE (op)); + if (mclass != MODE_FLOAT && mclass != MODE_VECTOR_INT) return 0; return op == CONST0_RTX (mode); } @@ -1498,6 +1503,8 @@ clobbered_register (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) int input_operand (rtx op, enum machine_mode mode) { + enum mode_class mclass; + /* If both modes are non-void they must be the same. */ if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -1538,8 +1545,9 @@ input_operand (rtx op, enum machine_mode mode) if (register_operand (op, mode)) return 1; - if (GET_MODE_CLASS (mode) == MODE_FLOAT - && GET_CODE (op) == CONST_DOUBLE) + mclass = GET_MODE_CLASS (mode); + if ((mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE) + || (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR)) return 1; /* If this is a SUBREG, look inside so that we handle @@ -3293,6 +3301,7 @@ sparc_cannot_force_const_mem (rtx x) { case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: /* Accept all non-symbolic constants. */ return false; @@ -4181,6 +4190,12 @@ sparc_init_modes (void) else sparc_mode_class[i] = 0; break; + case MODE_VECTOR_INT: + if (GET_MODE_SIZE (i) <= 4) + sparc_mode_class[i] = 1 << (int)SF_MODE; + else if (GET_MODE_SIZE (i) == 8) + sparc_mode_class[i] = 1 << (int)DF_MODE; + break; case MODE_FLOAT: case MODE_COMPLEX_FLOAT: if (GET_MODE_SIZE (i) <= 4) @@ -6263,6 +6278,15 @@ sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) return build_va_arg_indirect_ref (addr); } +/* Implement the TARGET_VECTOR_MODE_SUPPORTED_P target hook. + Specify whether the vector mode is supported by the hardware. */ + +static bool +sparc_vector_mode_supported_p (enum machine_mode mode) +{ + return TARGET_VIS && VECTOR_MODE_P (mode) ? true : false; +} + /* Return the string to output an unconditional branch to LABEL, which is the operand number of the label. @@ -8445,6 +8469,9 @@ sparc_extra_constraint_check (rtx op, int c, int strict) case 'T': break; + case 'Y': + return fp_zero_operand (op, GET_MODE (op)); + default: return 0; } diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index d1b93ec1ab7..37f1905bb58 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -769,6 +769,8 @@ extern struct sparc_cpu_select sparc_select[]; #define MIN_UNITS_PER_WORD 4 #endif +#define UNITS_PER_SIMD_WORD (TARGET_VIS ? 8 : 0) + /* Now define the sizes of the C data types. */ #define SHORT_TYPE_SIZE 16 @@ -2042,7 +2044,9 @@ do { \ integer register, needed for ldd/std instructions. 'W' handles the memory operand when moving operands in/out - of 'e' constraint floating point registers. */ + of 'e' constraint floating point registers. + + 'Y' handles the zero vector constant. */ #ifndef REG_OK_STRICT diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 1000fbb3063..0118a3c3037 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -2207,6 +2207,10 @@ [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore") (set_attr "fptype" "*,*,*,*,*,double,*,*")]) +;; We don't define V1SI because SI should work just fine. +(define_mode_macro V64 [DF V4HI V8QI V2SI]) +(define_mode_macro V32 [SF V2HI V4QI]) + (define_insn "*movdi_insn_sp64_vis" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W,b") (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e,J"))] @@ -2627,12 +2631,12 @@ [(set_attr "type" "fpmove,*,*,*,*,load,fpload,fpstore,store")]) (define_insn "*movsf_insn_vis" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m") - (match_operand:SF 1 "input_operand" "f,G,G,Q,*rR,S,m,m,f,*rG"))] + [(set (match_operand:V32 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m") + (match_operand:V32 1 "input_operand" "f,GY,GY,Q,*rR,S,m,m,f,*rGY"))] "(TARGET_FPU && TARGET_VIS) - && (register_operand (operands[0], SFmode) - || register_operand (operands[1], SFmode) - || fp_zero_operand (operands[1], SFmode))" + && (register_operand (operands[0], mode) + || register_operand (operands[1], mode) + || fp_zero_operand (operands[1], mode))" { if (GET_CODE (operands[1]) == CONST_DOUBLE && (which_alternative == 3 @@ -2718,6 +2722,8 @@ } [(set_attr "type" "*,*,*,*,load,store")]) +;; The following 3 patterns build SFmode constants in integer registers. + (define_insn "*movsf_lo_sum" [(set (match_operand:SF 0 "register_operand" "=r") (lo_sum:SF (match_operand:SF 1 "register_operand" "r") @@ -2756,27 +2762,29 @@ [(set (match_dup 0) (high:SF (match_dup 1))) (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))]) -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" +;; Yes, you guessed it right, the former movsf expander. +(define_expand "mov" + [(set (match_operand:V32 0 "general_operand" "") + (match_operand:V32 1 "general_operand" ""))] + "mode == SFmode || TARGET_VIS" { - /* Force SFmode constants into memory. */ - if (GET_CODE (operands[0]) == REG - && CONSTANT_P (operands[1])) + /* Force constants into memory. */ + if (GET_CODE (operands[0]) == REG && CONSTANT_P (operands[1])) { /* emit_group_store will send such bogosity to us when it is not storing directly into memory. So fix this up to avoid crashes in output_constant_pool. */ if (operands [1] == const0_rtx) - operands[1] = CONST0_RTX (SFmode); + operands[1] = CONST0_RTX (mode); - if (TARGET_VIS && fp_zero_operand (operands[1], SFmode)) + if ((TARGET_VIS || REGNO (operands[0]) < 32) + && fp_zero_operand (operands[1], mode)) goto movsf_is_ok; /* We are able to build any SF constant in integer registers with at most 2 instructions. */ - if (REGNO (operands[0]) < 32) + if (REGNO (operands[0]) < 32 + && mode == SFmode) goto movsf_is_ok; operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]), @@ -2786,14 +2794,14 @@ /* Handle sets of MEM first. */ if (GET_CODE (operands[0]) == MEM) { - if (register_operand (operands[1], SFmode) - || fp_zero_operand (operands[1], SFmode)) + if (register_operand (operands[1], mode) + || fp_zero_operand (operands[1], mode)) goto movsf_is_ok; if (! reload_in_progress) { operands[0] = validize_mem (operands[0]); - operands[1] = force_reg (SFmode, operands[1]); + operands[1] = force_reg (mode, operands[1]); } } @@ -2802,12 +2810,12 @@ { if (CONSTANT_P (operands[1]) && pic_address_needs_scratch (operands[1])) - operands[1] = legitimize_pic_address (operands[1], SFmode, 0); + operands[1] = legitimize_pic_address (operands[1], mode, 0); - if (symbolic_operand (operands[1], SFmode)) + if (symbolic_operand (operands[1], mode)) { operands[1] = legitimize_pic_address (operands[1], - SFmode, + mode, (reload_in_progress ? operands[0] : NULL_RTX)); @@ -2818,27 +2826,28 @@ ; }) -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" +;; Yes, you again guessed it right, the former movdf expander. +(define_expand "mov" + [(set (match_operand:V64 0 "general_operand" "") + (match_operand:V64 1 "general_operand" ""))] + "mode == DFmode || TARGET_VIS" { - /* Force DFmode constants into memory. */ - if (GET_CODE (operands[0]) == REG - && CONSTANT_P (operands[1])) + /* Force constants into memory. */ + if (GET_CODE (operands[0]) == REG && CONSTANT_P (operands[1])) { /* emit_group_store will send such bogosity to us when it is not storing directly into memory. So fix this up to avoid crashes in output_constant_pool. */ if (operands [1] == const0_rtx) - operands[1] = CONST0_RTX (DFmode); + operands[1] = CONST0_RTX (mode); if ((TARGET_VIS || REGNO (operands[0]) < 32) - && fp_zero_operand (operands[1], DFmode)) + && fp_zero_operand (operands[1], mode)) goto movdf_is_ok; /* We are able to build any DF constant in integer registers. */ if (REGNO (operands[0]) < 32 + && mode == DFmode && (reload_completed || reload_in_progress)) goto movdf_is_ok; @@ -2849,14 +2858,14 @@ /* Handle MEM cases first. */ if (GET_CODE (operands[0]) == MEM) { - if (register_operand (operands[1], DFmode) - || fp_zero_operand (operands[1], DFmode)) + if (register_operand (operands[1], mode) + || fp_zero_operand (operands[1], mode)) goto movdf_is_ok; if (! reload_in_progress) { operands[0] = validize_mem (operands[0]); - operands[1] = force_reg (DFmode, operands[1]); + operands[1] = force_reg (mode, operands[1]); } } @@ -2865,12 +2874,12 @@ { if (CONSTANT_P (operands[1]) && pic_address_needs_scratch (operands[1])) - operands[1] = legitimize_pic_address (operands[1], DFmode, 0); + operands[1] = legitimize_pic_address (operands[1], mode, 0); - if (symbolic_operand (operands[1], DFmode)) + if (symbolic_operand (operands[1], mode)) { operands[1] = legitimize_pic_address (operands[1], - DFmode, + mode, (reload_in_progress ? operands[0] : NULL_RTX)); @@ -2969,14 +2978,14 @@ ;; We have available v9 double floats but not 64-bit ;; integer registers but we have VIS. (define_insn "*movdf_insn_v9only_vis" - [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o") - (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGf"))] + [(set (match_operand:V64 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o") + (match_operand:V64 1 "input_operand" "GY,e,W#F,GY,e,T,U,o#F,*roGYF,*rGYf"))] "TARGET_FPU && TARGET_VIS && ! TARGET_ARCH64 - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode) - || fp_zero_operand (operands[1], DFmode))" + && (register_operand (operands[0], mode) + || register_operand (operands[1], mode) + || fp_zero_operand (operands[1], mode))" "@ fzero\t%0 fmovd\t%1, %0 @@ -3018,14 +3027,14 @@ ;; We have available both v9 double floats and 64-bit ;; integer registers. And we have VIS. (define_insn "*movdf_insn_sp64_vis" - [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,W,*r,*r,m,*r") - (match_operand:DF 1 "input_operand" "G,e,W#F,e,*rG,m,*rG,F"))] + [(set (match_operand:V64 0 "nonimmediate_operand" "=e,e,e,W,*r,*r,m,*r") + (match_operand:V64 1 "input_operand" "GY,e,W#F,e,*rGY,m,*rGY,F"))] "TARGET_FPU && TARGET_VIS && TARGET_ARCH64 - && (register_operand (operands[0], DFmode) - || register_operand (operands[1], DFmode) - || fp_zero_operand (operands[1], DFmode))" + && (register_operand (operands[0], mode) + || register_operand (operands[1], mode) + || fp_zero_operand (operands[1], mode))" "@ fzero\t%0 fmovd\t%1, %0 @@ -3053,6 +3062,7 @@ stx\t%r1, %0" [(set_attr "type" "*,load,store")]) +;; This pattern build DFmode constants in integer registers. (define_split [(set (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "const_double_operand" ""))] @@ -3112,8 +3122,8 @@ ;; careful when V9 but not ARCH64 because the integer ;; register DFmode cases must be handled. (define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" ""))] + [(set (match_operand:V64 0 "register_operand" "") + (match_operand:V64 1 "register_operand" ""))] "(! TARGET_V9 || (! TARGET_ARCH64 && ((GET_CODE (operands[0]) == REG @@ -3128,30 +3138,37 @@ rtx set_src = operands[1]; rtx dest1, dest2; rtx src1, src2; + enum machine_mode half_mode; - dest1 = gen_highpart (SFmode, set_dest); - dest2 = gen_lowpart (SFmode, set_dest); - src1 = gen_highpart (SFmode, set_src); - src2 = gen_lowpart (SFmode, set_src); + /* We can be expanded for DFmode or integral vector modes. */ + if (mode == DFmode) + half_mode = SFmode; + else + half_mode = SImode; + + dest1 = gen_highpart (half_mode, set_dest); + dest2 = gen_lowpart (half_mode, set_dest); + src1 = gen_highpart (half_mode, set_src); + src2 = gen_lowpart (half_mode, set_src); /* Now emit using the real source and destination we found, swapping the order if we detect overlap. */ if (reg_overlap_mentioned_p (dest1, src2)) { - emit_insn (gen_movsf (dest2, src2)); - emit_insn (gen_movsf (dest1, src1)); + emit_move_insn_1 (dest2, src2); + emit_move_insn_1 (dest1, src1); } else { - emit_insn (gen_movsf (dest1, src1)); - emit_insn (gen_movsf (dest2, src2)); + emit_move_insn_1 (dest1, src1); + emit_move_insn_1 (dest2, src2); } DONE; }) (define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "memory_operand" ""))] + [(set (match_operand:V64 0 "register_operand" "") + (match_operand:V64 1 "memory_operand" ""))] "reload_completed && ! TARGET_ARCH64 && (((REGNO (operands[0]) % 2) != 0) @@ -3159,29 +3176,34 @@ && offsettable_memref_p (operands[1])" [(clobber (const_int 0))] { - rtx word0 = adjust_address (operands[1], SFmode, 0); - rtx word1 = adjust_address (operands[1], SFmode, 4); + enum machine_mode half_mode; + rtx word0, word1; + + /* We can be expanded for DFmode or integral vector modes. */ + if (mode == DFmode) + half_mode = SFmode; + else + half_mode = SImode; + + word0 = adjust_address (operands[1], half_mode, 0); + word1 = adjust_address (operands[1], half_mode, 4); - if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1)) + if (reg_overlap_mentioned_p (gen_highpart (half_mode, operands[0]), word1)) { - emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]), - word1)); - emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]), - word0)); + emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1); + emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0); } else { - emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]), - word0)); - emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]), - word1)); + emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0); + emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1); } DONE; }) (define_split - [(set (match_operand:DF 0 "memory_operand" "") - (match_operand:DF 1 "register_operand" ""))] + [(set (match_operand:V64 0 "memory_operand" "") + (match_operand:V64 1 "register_operand" ""))] "reload_completed && ! TARGET_ARCH64 && (((REGNO (operands[1]) % 2) != 0) @@ -3189,19 +3211,26 @@ && offsettable_memref_p (operands[0])" [(clobber (const_int 0))] { - rtx word0 = adjust_address (operands[0], SFmode, 0); - rtx word1 = adjust_address (operands[0], SFmode, 4); + enum machine_mode half_mode; + rtx word0, word1; - emit_insn (gen_movsf (word0, - gen_highpart (SFmode, operands[1]))); - emit_insn (gen_movsf (word1, - gen_lowpart (SFmode, operands[1]))); + /* We can be expanded for DFmode or integral vector modes. */ + if (mode == DFmode) + half_mode = SFmode; + else + half_mode = SImode; + + word0 = adjust_address (operands[0], half_mode, 0); + word1 = adjust_address (operands[0], half_mode, 4); + + emit_move_insn_1 (word0, gen_highpart (half_mode, operands[1])); + emit_move_insn_1 (word1, gen_lowpart (half_mode, operands[1])); DONE; }) (define_split - [(set (match_operand:DF 0 "memory_operand" "") - (match_operand:DF 1 "fp_zero_operand" ""))] + [(set (match_operand:V64 0 "memory_operand" "") + (match_operand:V64 1 "fp_zero_operand" ""))] "reload_completed && (! TARGET_V9 || (! TARGET_ARCH64 @@ -3209,19 +3238,26 @@ && offsettable_memref_p (operands[0])" [(clobber (const_int 0))] { + enum machine_mode half_mode; rtx dest1, dest2; - dest1 = adjust_address (operands[0], SFmode, 0); - dest2 = adjust_address (operands[0], SFmode, 4); + /* We can be expanded for DFmode or integral vector modes. */ + if (mode == DFmode) + half_mode = SFmode; + else + half_mode = SImode; + + dest1 = adjust_address (operands[0], half_mode, 0); + dest2 = adjust_address (operands[0], half_mode, 4); - emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode))); - emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode))); + emit_move_insn_1 (dest1, CONST0_RTX (half_mode)); + emit_move_insn_1 (dest2, CONST0_RTX (half_mode)); DONE; }) (define_split - [(set (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "fp_zero_operand" ""))] + [(set (match_operand:V64 0 "register_operand" "") + (match_operand:V64 1 "fp_zero_operand" ""))] "reload_completed && ! TARGET_ARCH64 && ((GET_CODE (operands[0]) == REG @@ -3231,13 +3267,20 @@ && REGNO (SUBREG_REG (operands[0])) < 32))" [(clobber (const_int 0))] { + enum machine_mode half_mode; rtx set_dest = operands[0]; rtx dest1, dest2; - dest1 = gen_highpart (SFmode, set_dest); - dest2 = gen_lowpart (SFmode, set_dest); - emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode))); - emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode))); + /* We can be expanded for DFmode or integral vector modes. */ + if (mode == DFmode) + half_mode = SFmode; + else + half_mode = SImode; + + dest1 = gen_highpart (half_mode, set_dest); + dest2 = gen_lowpart (half_mode, set_dest); + emit_move_insn_1 (dest1, CONST0_RTX (half_mode)); + emit_move_insn_1 (dest2, CONST0_RTX (half_mode)); DONE; }) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 6f3d8f3e41b..adf9fe5d195 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -2367,7 +2367,10 @@ Memory address aligned to an 8-byte boundary Even register @item W -Memory address for @samp{e} constraint registers. +Memory address for @samp{e} constraint registers + +@item Y +Vector zero @end table -- 2.30.2