diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1d547b0..6f260ec 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -236,6 +236,7 @@ static rtx arm_trampoline_adjust_address (rtx);
 static rtx arm_pic_static_addr (rtx orig, rtx reg);
 static bool cortex_a9_sched_adjust_cost (rtx, rtx, rtx, int *);
 static bool xscale_sched_adjust_cost (rtx, rtx, rtx, int *);
+static unsigned int arm_units_per_simd_word (enum machine_mode);
 
 
 /* Table of machine attributes.  */
@@ -363,6 +364,8 @@ static const struct attribute_spec arm_attribute_table[] =
 #define TARGET_SHIFT_TRUNCATION_MASK arm_shift_truncation_mask
 #undef TARGET_VECTOR_MODE_SUPPORTED_P
 #define TARGET_VECTOR_MODE_SUPPORTED_P arm_vector_mode_supported_p
+#undef TARGET_VECTORIZE_UNITS_PER_SIMD_WORD
+#define TARGET_VECTORIZE_UNITS_PER_SIMD_WORD arm_units_per_simd_word
 
 #undef  TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG arm_reorg
@@ -21869,6 +21872,17 @@ arm_vector_mode_supported_p (enum machine_mode mode)
   return false;
 }
 
+/* Use the option -mvectorize-with-neon-quad to override the use of doubleword
+   registers when autovectorizing for Neon, at least until multiple vector
+   widths are supported properly by the middle-end.  */
+
+static unsigned int
+arm_units_per_simd_word (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return (TARGET_NEON
+	  ? (TARGET_NEON_VECTORIZE_QUAD ? 16 : 8) : UNITS_PER_WORD);
+}
+
 /* Implements target hook small_register_classes_for_mode_p.  */
 bool
 arm_small_register_classes_for_mode_p (enum machine_mode mode ATTRIBUTE_UNUSED)
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 5b66510..36b618a 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -580,12 +580,6 @@ extern int arm_arch_hwdiv;
 
 #define UNITS_PER_WORD	4
 
-/* Use the option -mvectorize-with-neon-quad to override the use of doubleword
-   registers when autovectorizing for Neon, at least until multiple vector
-   widths are supported properly by the middle-end.  */
-#define UNITS_PER_SIMD_WORD(MODE) \
-  (TARGET_NEON ? (TARGET_NEON_VECTORIZE_QUAD ? 16 : 8) : UNITS_PER_WORD)
-
 /* True if natural alignment is used for doubleword types.  */
 #define ARM_DOUBLEWORD_ALIGN	TARGET_AAPCS_BASED
 
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index c4c61f7..900b424 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -50,7 +50,6 @@ extern bool x86_extended_QIreg_mentioned_p (rtx);
 extern bool x86_extended_reg_mentioned_p (rtx);
 extern bool x86_maybe_negate_const_int (rtx *, enum machine_mode);
 extern enum machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx);
-extern unsigned int ix86_units_per_simd_word (enum machine_mode);
 
 extern int avx_vpermilp_parallel (rtx par, enum machine_mode mode);
 extern int avx_vperm2f128_parallel (rtx par, enum machine_mode mode);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a1bc205..1d4e4ae 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -32341,7 +32341,7 @@ has_dispatch (rtx insn, int action)
 /* ??? No autovectorization into MMX or 3DNOW until we can reliably
    place emms and femms instructions.  */
 
-unsigned int
+static unsigned int
 ix86_units_per_simd_word (enum machine_mode mode)
 {
   /* Disable double precision vectorizer if needed.  */
@@ -32609,6 +32609,9 @@ ix86_units_per_simd_word (enum machine_mode mode)
 #undef TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK
 #define TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK \
   ix86_vectorize_builtin_vec_perm_ok
+#undef TARGET_VECTORIZE_UNITS_PER_SIMD_WORD
+#define TARGET_VECTORIZE_UNITS_PER_SIMD_WORD \
+  ix86_units_per_simd_word
 
 #undef TARGET_SET_CURRENT_FUNCTION
 #define TARGET_SET_CURRENT_FUNCTION ix86_set_current_function
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 6fc2249..fe48efd 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1033,8 +1033,6 @@ enum target_cpu_default
    || (MODE) == V2SImode || (MODE) == SImode				\
    || (MODE) == V4HImode || (MODE) == V8QImode)
 
-#define UNITS_PER_SIMD_WORD(MODE) ix86_units_per_simd_word (MODE)
-
 #define VALID_DFP_MODE_P(MODE) \
   ((MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode)
 
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 20b63c7..945ee42 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -11140,6 +11140,14 @@ mips_scalar_mode_supported_p (enum machine_mode mode)
   return default_scalar_mode_supported_p (mode);
 }
 
+/* Implement TARGET_VECTORIZE_UNITS_PER_SIMD_WORD.  */
+
+static bool
+mips_units_per_simd_word (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return TARGET_PAIRED_SINGLE_FLOAT ? 8 : UNITS_PER_WORD;
+}
+
 /* Implement TARGET_INIT_LIBFUNCS.  */
 
 #include "config/gofast.h"
@@ -16506,6 +16514,9 @@ mips_shift_truncation_mask (enum machine_mode mode)
 #undef TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P mips_scalar_mode_supported_p
 
+#undef TARGET_VECTORIZE_UNITS_PER_SIMD_WORD
+#define TARGET_VECTORIZE_UNITS_PER_SIMD_WORD mips_units_per_simd_word
+
 #undef TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS mips_init_builtins
 #undef TARGET_EXPAND_BUILTIN
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 74bf3d2..4f44130 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1328,9 +1328,6 @@ enum mips_code_readable_setting {
 /* The number of bytes in a double.  */
 #define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT)
 
-#define UNITS_PER_SIMD_WORD(MODE) \
-  (TARGET_PAIRED_SINGLE_FLOAT ? 8 : UNITS_PER_WORD)
-
 /* Set the sizes of the core types.  */
 #define SHORT_TYPE_SIZE 16
 #define INT_TYPE_SIZE 32
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index ab5da58..2ebe484 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3570,6 +3570,18 @@ rs6000_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
     }
 }
 
+/* Implement targetm.vectorize.units_per_simd_word.  */
+
+static int
+rs6000_units_per_simd_word (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return (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))));
+}
+
 /* Handle generic options of the form -mfoo=yes/no.
    NAME is the option name.
    VALUE is the option value.
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 63f1bba..5b0e4c7 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -1150,13 +1150,6 @@ extern unsigned rs6000_pointer_size;
 #define PAIRED_VECTOR_MODE(MODE)        \
          ((MODE) == V2SFmode)            
 
-#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.  */
 #define HARD_REGNO_MODE_OK(REGNO, MODE) \
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index ba034e6..71c94e1 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -434,6 +434,7 @@ static bool sparc_can_eliminate (const int, const int);
 static const char *sparc_mangle_type (const_tree);
 #endif
 static void sparc_trampoline_init (rtx, tree, rtx);
+static bool sparc_units_per_simd_word (enum machine_mode);
 
 #ifdef SUBTARGET_ATTRIBUTE_TABLE
 /* Table of valid machine attributes.  */
@@ -571,6 +572,9 @@ static bool fpu_option_set = false;
 #undef TARGET_VECTOR_MODE_SUPPORTED_P
 #define TARGET_VECTOR_MODE_SUPPORTED_P sparc_vector_mode_supported_p
 
+#undef TARGET_VECTORIZE_UNITS_PER_SIMD_WORD
+#define TARGET_VECTORIZE_UNITS_PER_SIMD_WORD sparc_units_per_simd_word
+
 #undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
 #define TARGET_DWARF_HANDLE_FRAME_UNSPEC sparc_dwarf_handle_frame_unspec
 
@@ -6233,6 +6237,14 @@ sparc_vector_mode_supported_p (enum machine_mode mode)
   return TARGET_VIS && VECTOR_MODE_P (mode) ? true : false;
 }
 
+/* Implement the TARGET_VECTORIZE_UNITS_PER_SIMD_WORD target hook.  */
+
+static bool
+sparc_units_per_simd_word (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return TARGET_VIS ? 8 : UNITS_PER_WORD;
+}
+
 /* Return the string to output an unconditional branch to LABEL, which is
    the operand number of the label.
 
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index eae3959..21694eb 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -607,8 +607,6 @@ extern struct sparc_cpu_select sparc_select[];
 #define MIN_UNITS_PER_WORD	4
 #endif
 
-#define UNITS_PER_SIMD_WORD(MODE) (TARGET_VIS ? 8 : UNITS_PER_WORD)
-
 /* Now define the sizes of the C data types.  */
 
 #define SHORT_TYPE_SIZE		16
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 62b8228..a50052e 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -949,12 +949,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define HAS_LONG_UNCOND_BRANCH 0
 #endif
 
-/* By default, only attempt to parallelize bitwise operations, and
-   possibly adds/subtracts using bit-twiddling.  */
-#ifndef UNITS_PER_SIMD_WORD
-#define UNITS_PER_SIMD_WORD(MODE) UNITS_PER_WORD
-#endif
-
 /* Determine whether __cxa_atexit, rather than atexit, is used to
    register C++ destructors for local statics and global objects.  */
 #ifndef DEFAULT_USE_CXA_ATEXIT
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 91fbaf7..8e66da5 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -995,13 +995,6 @@ Minimum number of units in a word.  If this is undefined, the default is
 smallest value that @code{UNITS_PER_WORD} can have at run-time.
 @end defmac
 
-@defmac UNITS_PER_SIMD_WORD (@var{mode})
-Number of units in the vectors that the vectorizer can produce for
-scalar mode @var{mode}.  The default is equal to @code{UNITS_PER_WORD},
-because the vectorizer can do some transformations even in absence of
-specialized @acronym{SIMD} hardware.
-@end defmac
-
 @defmac POINTER_SIZE
 Width of a pointer, in bits.  You must specify a value no wider than the
 width of @code{Pmode}.  If it is not equal to the width of @code{Pmode},
@@ -5765,6 +5758,13 @@ the elements in the vectors should be of type @var{type}.  @var{is_packed}
 parameter is true if the memory access is defined in a packed struct.
 @end deftypefn
 
+@deftypefn {Target Hook} {unsigned int} TARGET_VECTORIZE_UNITS_PER_SIMD_WORD (enum machine_mode @var{mode})
+This hook should return th number of units in the vectors that the
+vectorizer can produce for scalar mode @var{mode}.  The default is
+equal to @code{UNITS_PER_WORD}, because the vectorizer can do some
+transformations even in absence of specialized @acronym{SIMD} hardware.
+@end deftypefn
+
 @node Anchored Addresses
 @section Anchored Addresses
 @cindex anchored addresses
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index a180a56..d25ead1 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -995,13 +995,6 @@ Minimum number of units in a word.  If this is undefined, the default is
 smallest value that @code{UNITS_PER_WORD} can have at run-time.
 @end defmac
 
-@defmac UNITS_PER_SIMD_WORD (@var{mode})
-Number of units in the vectors that the vectorizer can produce for
-scalar mode @var{mode}.  The default is equal to @code{UNITS_PER_WORD},
-because the vectorizer can do some transformations even in absence of
-specialized @acronym{SIMD} hardware.
-@end defmac
-
 @defmac POINTER_SIZE
 Width of a pointer, in bits.  You must specify a value no wider than the
 width of @code{Pmode}.  If it is not equal to the width of @code{Pmode},
@@ -5765,6 +5758,13 @@ the elements in the vectors should be of type @var{type}.  @var{is_packed}
 parameter is true if the memory access is defined in a packed struct.
 @end deftypefn
 
+@hook TARGET_VECTORIZE_UNITS_PER_SIMD_WORD
+This hook should return th number of units in the vectors that the
+vectorizer can produce for scalar mode @var{mode}.  The default is
+equal to @code{UNITS_PER_WORD}, because the vectorizer can do some
+transformations even in absence of specialized @acronym{SIMD} hardware.
+@end deftypefn
+
 @node Anchored Addresses
 @section Anchored Addresses
 @cindex anchored addresses
diff --git a/gcc/system.h b/gcc/system.h
index a5cfaba..35f9ac8 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -715,7 +715,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
 	ALLOCATE_INITIAL_VALUE LEGITIMIZE_ADDRESS FRAME_POINTER_REQUIRED \
 	CAN_ELIMINATE TRAMPOLINE_TEMPLATE INITIALIZE_TRAMPOLINE		\
 	TRAMPOLINE_ADJUST_ADDRESS STATIC_CHAIN STATIC_CHAIN_INCOMING	\
-	RETURN_POPS_ARGS
+	RETURN_POPS_ARGS UNITS_PER_SIMD_WORD
 
 /* Other obsolete target macros, or macros that used to be in target
    headers and were not used, and may be obsolete or may never have
diff --git a/gcc/target.def b/gcc/target.def
index cecf882..155f0fd 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -880,6 +880,14 @@ DEFHOOK
  (enum machine_mode mode, const_tree type, int misalignment, bool is_packed),
  default_builtin_support_vector_misalignment)
 
+/* Return units per SIMD word.  */
+DEFHOOK
+(units_per_simd_word,
+ "",
+ unsigned int,
+ (enum machine_mode mode),
+ default_units_per_simd_word)
+
 HOOK_VECTOR_END (vectorize)
 
 #undef HOOK_PREFIX
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index a0e24c0..046c07f 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -984,6 +984,15 @@ default_builtin_support_vector_misalignment (enum machine_mode mode,
   return false;
 }
 
+/* By default, only attempt to parallelize bitwise operations, and
+   possibly adds/subtracts using bit-twiddling.  */
+
+unsigned int
+default_units_per_simd_word (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return UNITS_PER_WORD;
+}
+
 /* Determine whether or not a pointer mode is valid. Assume defaults
    of ptr_mode or Pmode - can be overridden.  */
 bool
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 4073cbe..a6231f9 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -86,6 +86,7 @@ extern bool
 default_builtin_support_vector_misalignment (enum machine_mode mode,
 					     const_tree,
 					     int, bool);
+extern unsigned int default_units_per_simd_word (enum machine_mode mode);
 
 /* These are here, and not in hooks.[ch], because not all users of
    hooks.h include tm.h, and thus we don't have CUMULATIVE_ARGS.  */
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 2ed8c76..5c35080 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -126,9 +126,10 @@ along with GCC; see the file COPYING3.  If not see
    Target modeling:
    =================
         Currently the only target specific information that is used is the
-   size of the vector (in bytes) - "UNITS_PER_SIMD_WORD". Targets that can
-   support different sizes of vectors, for now will need to specify one value
-   for "UNITS_PER_SIMD_WORD". More flexibility will be added in the future.
+   size of the vector (in bytes) - "TARGET_VECTORIZE_UNITS_PER_SIMD_WORD".
+   Targets that can support different sizes of vectors, for now will need
+   to specify one value for "TARGET_VECTORIZE_UNITS_PER_SIMD_WORD". More
+   flexibility will be added in the future.
 
         Since we only vectorize operations which vector form can be
    expressed using existing tree codes, to verify that an operation is
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 6d15bda..9ae79a8 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -4675,7 +4675,8 @@ get_vectype_for_scalar_type (tree scalar_type)
   int nunits;
   tree vectype;
 
-  if (nbytes == 0 || nbytes >= UNITS_PER_SIMD_WORD (inner_mode))
+  if (nbytes == 0
+      || (nbytes >= targetm.vectorize.units_per_simd_word (inner_mode)))
     return NULL_TREE;
 
   /* We can't build a vector type of elements with alignment bigger than
@@ -4691,9 +4692,9 @@ get_vectype_for_scalar_type (tree scalar_type)
       && GET_MODE_BITSIZE (inner_mode) != TYPE_PRECISION (scalar_type))
     return NULL_TREE;
 
-  /* FORNOW: Only a single vector size per mode (UNITS_PER_SIMD_WORD)
-     is expected.  */
-  nunits = UNITS_PER_SIMD_WORD (inner_mode) / nbytes;
+  /* FORNOW: Only a single vector size per mode
+    (TARGET_VECTORIZE_UNITS_PER_SIMD_WORD) is expected.  */
+  nunits = targetm.vectorize.units_per_simd_word (inner_mode) / nbytes;
 
   vectype = build_vector_type (scalar_type, nunits);
   if (vect_print_dump_info (REPORT_DETAILS))
