aboutsummaryrefslogtreecommitdiffstats
path: root/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106753.patch
diff options
context:
space:
mode:
Diffstat (limited to 'toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106753.patch')
-rw-r--r--toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106753.patch5027
1 files changed, 5027 insertions, 0 deletions
diff --git a/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106753.patch b/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106753.patch
new file mode 100644
index 0000000000..bda39e8faa
--- /dev/null
+++ b/toolchain-layer/recipes-devtools/gcc/gcc-4.6/linaro/gcc-4.6-linaro-r106753.patch
@@ -0,0 +1,5027 @@
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ * gimple.c (gimple_build_call_internal_1): Add missing call to
+ gimple_call_reset_alias_info.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/testsuite/
+ Backport from mainline:
+
+ 2011-05-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * gcc.dg/vect/vect-strided-u16-i3.c: New test.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/testsuite/
+ Backport from mainline:
+
+ 2011-05-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * lib/target-supports.exp (check_effective_target_vect_strided):
+ Replace with...
+ (check_effective_target_vect_strided2)
+ (check_effective_target_vect_strided3)
+ (check_effective_target_vect_strided4)
+ (check_effective_target_vect_strided8): ...these new functions.
+
+ * gcc.dg/vect/O3-pr39675-2.c: Update accordingly.
+ * gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c: Likewise.
+ * gcc.dg/vect/fast-math-slp-27.c: Likewise.
+ * gcc.dg/vect/if-cvt-stores-vect-ifcvt-18.c: Likewise.
+ * gcc.dg/vect/pr37539.c: Likewise.
+ * gcc.dg/vect/slp-11a.c: Likewise.
+ * gcc.dg/vect/slp-11b.c: Likewise.
+ * gcc.dg/vect/slp-11c.c: Likewise.
+ * gcc.dg/vect/slp-12a.c: Likewise.
+ * gcc.dg/vect/slp-12b.c: Likewise.
+ * gcc.dg/vect/slp-18.c: Likewise.
+ * gcc.dg/vect/slp-19a.c: Likewise.
+ * gcc.dg/vect/slp-19b.c: Likewise.
+ * gcc.dg/vect/slp-21.c: Likewise.
+ * gcc.dg/vect/slp-23.c: Likewise.
+ * gcc.dg/vect/vect-cselim-1.c: Likewise.
+
+ * gcc.dg/vect/fast-math-vect-complex-3.c: Use vect_stridedN
+ instead of vect_interleave && vect_extract_even_odd.
+ * gcc.dg/vect/no-scevccp-outer-10a.c: Likewise.
+ * gcc.dg/vect/no-scevccp-outer-10b.c: Likewise.
+ * gcc.dg/vect/no-scevccp-outer-20.c: Likewise.
+ * gcc.dg/vect/vect-1.c: Likewise.
+ * gcc.dg/vect/vect-10.c: Likewise.
+ * gcc.dg/vect/vect-98.c: Likewise.
+ * gcc.dg/vect/vect-107.c: Likewise.
+ * gcc.dg/vect/vect-strided-a-mult.c: Likewise.
+ * gcc.dg/vect/vect-strided-a-u16-i2.c: Likewise.
+ * gcc.dg/vect/vect-strided-a-u16-i4.c: Likewise.
+ * gcc.dg/vect/vect-strided-a-u16-mult.c: Likewise.
+ * gcc.dg/vect/vect-strided-a-u32-mult.c: Likewise.
+ * gcc.dg/vect/vect-strided-a-u8-i2-gap.c: Likewise.
+ * gcc.dg/vect/vect-strided-a-u8-i8-gap2.c: Likewise.
+ * gcc.dg/vect/vect-strided-a-u8-i8-gap7.c: Likewise.
+ * gcc.dg/vect/vect-strided-float.c: Likewise.
+ * gcc.dg/vect/vect-strided-mult-char-ls.c: Likewise.
+ * gcc.dg/vect/vect-strided-mult.c: Likewise.
+ * gcc.dg/vect/vect-strided-same-dr.c: Likewise.
+ * gcc.dg/vect/vect-strided-u16-i2.c: Likewise.
+ * gcc.dg/vect/vect-strided-u16-i4.c: Likewise.
+ * gcc.dg/vect/vect-strided-u32-i4.c: Likewise.
+ * gcc.dg/vect/vect-strided-u32-i8.c: Likewise.
+ * gcc.dg/vect/vect-strided-u32-mult.c: Likewise.
+ * gcc.dg/vect/vect-strided-u8-i2-gap.c: Likewise.
+ * gcc.dg/vect/vect-strided-u8-i2.c: Likewise.
+ * gcc.dg/vect/vect-strided-u8-i8-gap2.c: Likewise.
+ * gcc.dg/vect/vect-strided-u8-i8-gap4.c: Likewise.
+ * gcc.dg/vect/vect-strided-u8-i8-gap7.c: Likewise.
+ * gcc.dg/vect/vect-strided-u8-i8.c: Likewise.
+ * gcc.dg/vect/vect-vfa-03.c: Likewise.
+
+ * gcc.dg/vect/no-scevccp-outer-18.c: Add vect_stridedN to the
+ target condition.
+ * gcc.dg/vect/pr30843.c: Likewise.
+ * gcc.dg/vect/pr33866.c: Likewise.
+ * gcc.dg/vect/slp-reduc-6.c: Likewise.
+ * gcc.dg/vect/vect-strided-store-a-u8-i2.c: Likewise.
+ * gcc.dg/vect/vect-strided-store-u16-i4.c: Likewise.
+ * gcc.dg/vect/vect-strided-store-u32-i2.c: Likewise.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/testsuite/
+ Backport from mainline:
+
+ 2011-05-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * gcc.dg/vect/slp-11.c: Split into...
+ * gcc.dg/vect/slp-11a.c, gcc.dg/vect/slp-11b.c,
+ gcc.dg/vect/slp-11c.c: ...these tests.
+ * gcc.dg/vect/slp-12a.c: Split 4-stride loop into...
+ * gcc.dg/vect/slp-12c.c: ...this new test.
+ * gcc.dg/vect/slp-19.c: Split into...
+ * gcc.dg/vect/slp-19a.c, gcc.dg/vect/slp-19b.c,
+ gcc.dg/vect/slp-19c.c: ...these new tests.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/testsuite/
+ Backport from mainline:
+
+ 2011-05-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * lib/target-supports.exp
+ (check_effective_target_vect_extract_even_odd_wide): Delete.
+ (check_effective_target_vect_strided_wide): Likewise.
+ * gcc.dg/vect/O3-pr39675-2.c: Use the non-wide versions instead.
+ * gcc.dg/vect/fast-math-pr35982.c: Likewise.
+ * gcc.dg/vect/fast-math-vect-complex-3.c: Likewise.
+ * gcc.dg/vect/pr37539.c: Likewise.
+ * gcc.dg/vect/slp-11.c: Likewise.
+ * gcc.dg/vect/slp-12a.c: Likewise.
+ * gcc.dg/vect/slp-12b.c: Likewise.
+ * gcc.dg/vect/slp-19.c: Likewise.
+ * gcc.dg/vect/slp-23.c: Likewise.
+ * gcc.dg/vect/vect-1.c: Likewise.
+ * gcc.dg/vect/vect-98.c: Likewise.
+ * gcc.dg/vect/vect-107.c: Likewise.
+ * gcc.dg/vect/vect-strided-float.c: Likewise.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/testsuite/
+ Backport from mainline:
+
+ 2011-04-21 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * gcc.dg/vect/vect.exp: Run the main tests twice, one with -flto
+ and once without.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ Backport from mainlie:
+
+ 2011-05-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * config/arm/neon.md (vec_load_lanes<mode><mode>): New expanders,
+ (vec_store_lanes<mode><mode>): Likewise.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ Backport from mainline:
+
+ 2011-05-03 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * doc/md.texi (vec_load_lanes, vec_store_lanes): Document.
+ * optabs.h (COI_vec_load_lanes, COI_vec_store_lanes): New
+ convert_optab_index values.
+ (vec_load_lanes_optab, vec_store_lanes_optab): New convert optabs.
+ * genopinit.c (optabs): Initialize the new optabs.
+ * internal-fn.def (LOAD_LANES, STORE_LANES): New internal functions.
+ * internal-fn.c (get_multi_vector_move, expand_LOAD_LANES)
+ (expand_STORE_LANES): New functions.
+ * tree.h (build_array_type_nelts): Declare.
+ * tree.c (build_array_type_nelts): New function.
+ * tree-vectorizer.h (vect_model_store_cost): Add a bool argument.
+ (vect_model_load_cost): Likewise.
+ (vect_store_lanes_supported, vect_load_lanes_supported)
+ (vect_record_strided_load_vectors): Declare.
+ * tree-vect-data-refs.c (vect_lanes_optab_supported_p)
+ (vect_store_lanes_supported, vect_load_lanes_supported): New functions.
+ (vect_transform_strided_load): Split out statement recording into...
+ (vect_record_strided_load_vectors): ...this new function.
+ * tree-vect-stmts.c (create_vector_array, read_vector_array)
+ (write_vector_array, create_array_ref): New functions.
+ (vect_model_store_cost): Add store_lanes_p argument.
+ (vect_model_load_cost): Add load_lanes_p argument.
+ (vectorizable_store): Try to use store-lanes functions for
+ interleaved stores.
+ (vectorizable_load): Likewise load-lanes and loads.
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Update call
+ to vect_model_store_cost.
+ (vect_build_slp_tree): Likewise vect_model_load_cost.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ Backport from mainline:
+
+ 2011-04-20 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-vect-stmts.c (vectorizable_store): Only chain one related
+ statement per copy.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ * tree-inline.c (estimate_num_insns): Likewise.
+
+ Backport from mainline:
+
+ 2011-04-20 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * Makefile.in (INTERNAL_FN_DEF, INTERNAL_FN_H): Define.
+ (GIMPLE_H): Include $(INTERNAL_FN_H).
+ (OBJS-common): Add internal-fn.o.
+ (internal-fn.o): New rule.
+ * internal-fn.def: New file.
+ * internal-fn.h: Likewise.
+ * internal-fn.c: Likewise.
+ * gimple.h: Include internal-fn.h.
+ (GF_CALL_INTERNAL): New gf_mask.
+ (gimple_statement_call): Put fntype into a union with a new
+ internal_fn field.
+ (gimple_build_call_internal): Declare.
+ (gimple_build_call_internal_vec): Likewise.
+ (gimple_call_same_target_p): Likewise.
+ (gimple_call_internal_p): New function.
+ (gimple_call_internal_fn): Likewise.
+ (gimple_call_set_fn): Assert that the function is not internal.
+ (gimple_call_set_fndecl): Likewise.
+ (gimple_call_set_internal_fn): New function.
+ (gimple_call_addr_fndecl): Handle null functions.
+ (gimple_call_return_type): Likewise.
+ [---- Plus backport adjustments:
+ (GF_CALL_INTERNAL_FN_SHIFT): New macro.
+ (GF_CALL_INTERNAL_FN): New gf_mask.
+ ----]
+ * gimple.c (gimple_build_call_internal_1): New function.
+ (gimple_build_call_internal): Likewise.
+ (gimple_build_call_internal_vec): Likewise.
+ (gimple_call_same_target_p): Likewise.
+ (gimple_call_flags): Handle calls to internal functions.
+ (gimple_call_fnspec): New function.
+ (gimple_call_arg_flags, gimple_call_return_flags): Use it.
+ (gimple_has_side_effects): Handle null functions.
+ (gimple_rhs_has_side_effects): Likewise.
+ (gimple_call_copy_skip_args): Handle calls to internal functions.
+ * cfgexpand.c (expand_call_stmt): Likewise.
+ * expr.c (expand_expr_real_1): Assert that the call isn't internal.
+ * gimple-low.c (gimple_check_call_args): Handle calls to internal
+ functions.
+ * gimple-pretty-print.c (dump_gimple_call): Likewise.
+ * ipa-prop.c (ipa_analyze_call_uses): Handle null functions.
+ * tree-cfg.c (verify_gimple_call): Handle calls to internal functions.
+ (do_warn_unused_result): Likewise.
+ [---- Plus backport adjustments:
+ (verify_stmt): Likewise.
+ ----]
+ * tree-eh.c (same_handler_p): Use gimple_call_same_target_p.
+ * tree-ssa-ccp.c (ccp_fold_stmt): Handle calls to internal functions.
+ [---- Plus backport adjustments:
+ (fold_gimple_call): Likewise.
+ ----]
+ * tree-ssa-dom.c (hashable_expr): Use the gimple statement to record
+ the target of a call.
+ (initialize_hash_element): Update accordingly.
+ (hashable_expr_equal_p): Use gimple_call_same_target_p.
+ (iterative_hash_hashable_expr): Handle calls to internal functions.
+ (print_expr_hash_elt): Likewise.
+ * tree-ssa-pre.c (can_value_number_call): Likewise.
+ (eliminate): Handle null functions.
+ * tree-ssa-sccvn.c (visit_use): Handle calls to internal functions.
+ * tree-ssa-structalias.c (find_func_aliases): Likewise.
+ * value-prof.c (gimple_ic_transform): Likewise.
+ (gimple_indirect_call_to_profile): Likewise.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ Backport from mainline:
+
+ 2011-04-14 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-vectorizer.h (vect_strided_store_supported): Add a
+ HOST_WIDE_INT argument.
+ (vect_strided_load_supported): Likewise.
+ (vect_permute_store_chain): Return void.
+ (vect_transform_strided_load): Likewise.
+ (vect_permute_load_chain): Delete.
+ * tree-vect-data-refs.c (vect_strided_store_supported): Take a
+ count argument. Check that the count is a power of two.
+ (vect_strided_load_supported): Likewise.
+ (vect_permute_store_chain): Return void. Update after above changes.
+ Assert that the access is supported.
+ (vect_permute_load_chain): Likewise.
+ (vect_transform_strided_load): Return void.
+ * tree-vect-stmts.c (vectorizable_store): Update calls after
+ above interface changes.
+ (vectorizable_load): Likewise.
+ (vect_analyze_stmt): Don't check for strided powers of two here.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ Backport from mainline:
+
+ 2011-04-14 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-vectorizer.h (vect_create_data_ref_ptr): Add an extra
+ type parameter.
+ * tree-vect-data-refs.c (vect_create_data_ref_ptr): Add an aggr_type
+ parameter. Generalise code to handle arrays as well as vectors.
+ (vect_setup_realignment): Update accordingly.
+ * tree-vect-stmts.c (vectorizable_store): Likewise.
+ (vectorizable_load): Likewise.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ Backport from mainline:
+
+ 2011-04-14 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-vect-stmts.c (vectorizable_load): Allocate and free dr_chain
+ within the per-copy loop.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ Backport from mainline:
+
+ 2011-04-14 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * tree-vect-stmts.c (vectorizable_load): Print the number of copies
+ in the dump file.
+
+2001-06-02 Richard Sandiford <richard.sandiford@linaro.org>
+
+ gcc/
+ Backport from mainline:
+
+ 2011-03-25 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * config/arm/arm.h (CANNOT_CHANGE_MODE_CLASS): Restrict FPA_REGS
+ case to VFPv1.
+
+=== modified file 'gcc/Makefile.in'
+--- old/gcc/Makefile.in 2011-05-26 14:27:33 +0000
++++ new/gcc/Makefile.in 2011-06-02 12:12:00 +0000
+@@ -888,6 +888,8 @@
+ READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
+ PARAMS_H = params.h params.def
+ BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def
++INTERNAL_FN_DEF = internal-fn.def
++INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
+ TREE_H = tree.h all-tree.def tree.def c-family/c-common.def \
+ $(lang_tree_files) $(MACHMODE_H) tree-check.h $(BUILTINS_DEF) \
+ $(INPUT_H) statistics.h $(VEC_H) treestruct.def $(HASHTAB_H) \
+@@ -897,7 +899,7 @@
+ BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) cfghooks.h
+ GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
+ $(GGC_H) $(BASIC_BLOCK_H) $(TARGET_H) tree-ssa-operands.h \
+- tree-ssa-alias.h vecir.h
++ tree-ssa-alias.h vecir.h $(INTERNAL_FN_H)
+ GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
+ COVERAGE_H = coverage.h $(GCOV_IO_H)
+ DEMANGLE_H = $(srcdir)/../include/demangle.h
+@@ -1269,6 +1271,7 @@
+ init-regs.o \
+ input.o \
+ integrate.o \
++ internal-fn.o \
+ intl.o \
+ ira.o \
+ ira-build.o \
+@@ -2751,6 +2754,8 @@
+ $(TM_H) $(TREE_H) $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) \
+ $(TREE_PASS_H) tree-ssa-propagate.h tree-pretty-print.h \
+ gimple-pretty-print.h
++internal-fn.o : internal-fn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
++ $(GIMPLE_H) $(TREE_H) $(EXPR_H) $(OPTABS_H) $(RECOG_H)
+ gimple.o : gimple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
+ $(GGC_H) $(GIMPLE_H) $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_H) gt-gimple.h \
+ $(TREE_FLOW_H) value-prof.h $(FLAGS_H) $(DEMANGLE_H) \
+
+=== modified file 'gcc/cfgexpand.c'
+--- old/gcc/cfgexpand.c 2011-04-20 11:18:50 +0000
++++ new/gcc/cfgexpand.c 2011-06-02 12:12:00 +0000
+@@ -1839,12 +1839,17 @@
+ static void
+ expand_call_stmt (gimple stmt)
+ {
+- tree exp;
+- tree lhs = gimple_call_lhs (stmt);
++ tree exp, lhs;
+ size_t i;
+ bool builtin_p;
+ tree decl;
+
++ if (gimple_call_internal_p (stmt))
++ {
++ expand_internal_call (stmt);
++ return;
++ }
++
+ exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
+
+ CALL_EXPR_FN (exp) = gimple_call_fn (stmt);
+@@ -1882,6 +1887,7 @@
+ SET_EXPR_LOCATION (exp, gimple_location (stmt));
+ TREE_BLOCK (exp) = gimple_block (stmt);
+
++ lhs = gimple_call_lhs (stmt);
+ if (lhs)
+ expand_assignment (lhs, exp, false);
+ else
+
+=== modified file 'gcc/config/arm/arm.h'
+--- old/gcc/config/arm/arm.h 2011-04-26 14:42:21 +0000
++++ new/gcc/config/arm/arm.h 2011-06-02 12:12:00 +0000
+@@ -1169,12 +1169,12 @@
+ }
+
+ /* FPA registers can't do subreg as all values are reformatted to internal
+- precision. VFP registers may only be accessed in the mode they
+- were set. */
+-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+- ? reg_classes_intersect_p (FPA_REGS, (CLASS)) \
+- || reg_classes_intersect_p (VFP_REGS, (CLASS)) \
++ precision. In VFPv1, VFP registers could only be accessed in the mode
++ they were set, so subregs would be invalid there too. However, we don't
++ support VFPv1 at the moment, and the restriction was lifted in VFPv2. */
++#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
++ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
++ ? reg_classes_intersect_p (FPA_REGS, (CLASS)) \
+ : 0)
+
+ /* The class value for index registers, and the one for base regs. */
+
+=== modified file 'gcc/config/arm/neon.md'
+--- old/gcc/config/arm/neon.md 2011-05-06 11:28:27 +0000
++++ new/gcc/config/arm/neon.md 2011-06-02 12:12:00 +0000
+@@ -4248,6 +4248,12 @@
+ DONE;
+ })
+
++(define_expand "vec_load_lanes<mode><mode>"
++ [(set (match_operand:VDQX 0 "s_register_operand")
++ (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand")]
++ UNSPEC_VLD1))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vld1<mode>"
+ [(set (match_operand:VDQX 0 "s_register_operand" "=w")
+ (unspec:VDQX [(match_operand:VDQX 1 "neon_struct_operand" "Um")]
+@@ -4345,6 +4351,12 @@
+ (const_string "neon_vld1_1_2_regs")))]
+ )
+
++(define_expand "vec_store_lanes<mode><mode>"
++ [(set (match_operand:VDQX 0 "neon_struct_operand")
++ (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand")]
++ UNSPEC_VST1))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vst1<mode>"
+ [(set (match_operand:VDQX 0 "neon_struct_operand" "=Um")
+ (unspec:VDQX [(match_operand:VDQX 1 "s_register_operand" "w")]
+@@ -4401,6 +4413,13 @@
+ [(set_attr "neon_type" "neon_vst1_vst2_lane")]
+ )
+
++(define_expand "vec_load_lanesti<mode>"
++ [(set (match_operand:TI 0 "s_register_operand")
++ (unspec:TI [(match_operand:TI 1 "neon_struct_operand")
++ (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ UNSPEC_VLD2))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vld2<mode>"
+ [(set (match_operand:TI 0 "s_register_operand" "=w")
+ (unspec:TI [(match_operand:TI 1 "neon_struct_operand" "Um")
+@@ -4419,6 +4438,13 @@
+ (const_string "neon_vld2_2_regs_vld1_vld2_all_lanes")))]
+ )
+
++(define_expand "vec_load_lanesoi<mode>"
++ [(set (match_operand:OI 0 "s_register_operand")
++ (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
++ (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ UNSPEC_VLD2))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vld2<mode>"
+ [(set (match_operand:OI 0 "s_register_operand" "=w")
+ (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
+@@ -4501,6 +4527,13 @@
+ (const_string "neon_vld1_1_2_regs")))]
+ )
+
++(define_expand "vec_store_lanesti<mode>"
++ [(set (match_operand:TI 0 "neon_struct_operand")
++ (unspec:TI [(match_operand:TI 1 "s_register_operand")
++ (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ UNSPEC_VST2))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vst2<mode>"
+ [(set (match_operand:TI 0 "neon_struct_operand" "=Um")
+ (unspec:TI [(match_operand:TI 1 "s_register_operand" "w")
+@@ -4519,6 +4552,13 @@
+ (const_string "neon_vst1_1_2_regs_vst2_2_regs")))]
+ )
+
++(define_expand "vec_store_lanesoi<mode>"
++ [(set (match_operand:OI 0 "neon_struct_operand")
++ (unspec:OI [(match_operand:OI 1 "s_register_operand")
++ (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ UNSPEC_VST2))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vst2<mode>"
+ [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
+ (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
+@@ -4584,6 +4624,13 @@
+ [(set_attr "neon_type" "neon_vst1_vst2_lane")]
+ )
+
++(define_expand "vec_load_lanesei<mode>"
++ [(set (match_operand:EI 0 "s_register_operand")
++ (unspec:EI [(match_operand:EI 1 "neon_struct_operand")
++ (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ UNSPEC_VLD3))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vld3<mode>"
+ [(set (match_operand:EI 0 "s_register_operand" "=w")
+ (unspec:EI [(match_operand:EI 1 "neon_struct_operand" "Um")
+@@ -4602,6 +4649,16 @@
+ (const_string "neon_vld3_vld4")))]
+ )
+
++(define_expand "vec_load_lanesci<mode>"
++ [(match_operand:CI 0 "s_register_operand")
++ (match_operand:CI 1 "neon_struct_operand")
++ (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ "TARGET_NEON"
++{
++ emit_insn (gen_neon_vld3<mode> (operands[0], operands[1]));
++ DONE;
++})
++
+ (define_expand "neon_vld3<mode>"
+ [(match_operand:CI 0 "s_register_operand")
+ (match_operand:CI 1 "neon_struct_operand")
+@@ -4741,6 +4798,13 @@
+ (const_string "neon_vld3_vld4_all_lanes")
+ (const_string "neon_vld1_1_2_regs")))])
+
++(define_expand "vec_store_lanesei<mode>"
++ [(set (match_operand:EI 0 "neon_struct_operand")
++ (unspec:EI [(match_operand:EI 1 "s_register_operand")
++ (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ UNSPEC_VST3))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vst3<mode>"
+ [(set (match_operand:EI 0 "neon_struct_operand" "=Um")
+ (unspec:EI [(match_operand:EI 1 "s_register_operand" "w")
+@@ -4758,6 +4822,16 @@
+ (const_string "neon_vst1_1_2_regs_vst2_2_regs")
+ (const_string "neon_vst2_4_regs_vst3_vst4")))])
+
++(define_expand "vec_store_lanesci<mode>"
++ [(match_operand:CI 0 "neon_struct_operand")
++ (match_operand:CI 1 "s_register_operand")
++ (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ "TARGET_NEON"
++{
++ emit_insn (gen_neon_vst3<mode> (operands[0], operands[1]));
++ DONE;
++})
++
+ (define_expand "neon_vst3<mode>"
+ [(match_operand:CI 0 "neon_struct_operand")
+ (match_operand:CI 1 "s_register_operand")
+@@ -4869,6 +4943,13 @@
+ }
+ [(set_attr "neon_type" "neon_vst3_vst4_lane")])
+
++(define_expand "vec_load_lanesoi<mode>"
++ [(set (match_operand:OI 0 "s_register_operand")
++ (unspec:OI [(match_operand:OI 1 "neon_struct_operand")
++ (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ UNSPEC_VLD4))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vld4<mode>"
+ [(set (match_operand:OI 0 "s_register_operand" "=w")
+ (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um")
+@@ -4887,6 +4968,16 @@
+ (const_string "neon_vld3_vld4")))]
+ )
+
++(define_expand "vec_load_lanesxi<mode>"
++ [(match_operand:XI 0 "s_register_operand")
++ (match_operand:XI 1 "neon_struct_operand")
++ (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ "TARGET_NEON"
++{
++ emit_insn (gen_neon_vld4<mode> (operands[0], operands[1]));
++ DONE;
++})
++
+ (define_expand "neon_vld4<mode>"
+ [(match_operand:XI 0 "s_register_operand")
+ (match_operand:XI 1 "neon_struct_operand")
+@@ -5033,6 +5124,13 @@
+ (const_string "neon_vld1_1_2_regs")))]
+ )
+
++(define_expand "vec_store_lanesoi<mode>"
++ [(set (match_operand:OI 0 "neon_struct_operand")
++ (unspec:OI [(match_operand:OI 1 "s_register_operand")
++ (unspec:VDX [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ UNSPEC_VST4))]
++ "TARGET_NEON")
++
+ (define_insn "neon_vst4<mode>"
+ [(set (match_operand:OI 0 "neon_struct_operand" "=Um")
+ (unspec:OI [(match_operand:OI 1 "s_register_operand" "w")
+@@ -5051,6 +5149,16 @@
+ (const_string "neon_vst2_4_regs_vst3_vst4")))]
+ )
+
++(define_expand "vec_store_lanesxi<mode>"
++ [(match_operand:XI 0 "neon_struct_operand")
++ (match_operand:XI 1 "s_register_operand")
++ (unspec:VQ [(const_int 0)] UNSPEC_VSTRUCTDUMMY)]
++ "TARGET_NEON"
++{
++ emit_insn (gen_neon_vst4<mode> (operands[0], operands[1]));
++ DONE;
++})
++
+ (define_expand "neon_vst4<mode>"
+ [(match_operand:XI 0 "neon_struct_operand")
+ (match_operand:XI 1 "s_register_operand")
+
+=== modified file 'gcc/doc/md.texi'
+--- old/gcc/doc/md.texi 2011-01-03 20:52:22 +0000
++++ new/gcc/doc/md.texi 2011-05-05 15:43:06 +0000
+@@ -3935,6 +3935,48 @@
+ consecutive memory locations, operand 1 is the first register, and
+ operand 2 is a constant: the number of consecutive registers.
+
++@cindex @code{vec_load_lanes@var{m}@var{n}} instruction pattern
++@item @samp{vec_load_lanes@var{m}@var{n}}
++Perform an interleaved load of several vectors from memory operand 1
++into register operand 0. Both operands have mode @var{m}. The register
++operand is viewed as holding consecutive vectors of mode @var{n},
++while the memory operand is a flat array that contains the same number
++of elements. The operation is equivalent to:
++
++@smallexample
++int c = GET_MODE_SIZE (@var{m}) / GET_MODE_SIZE (@var{n});
++for (j = 0; j < GET_MODE_NUNITS (@var{n}); j++)
++ for (i = 0; i < c; i++)
++ operand0[i][j] = operand1[j * c + i];
++@end smallexample
++
++For example, @samp{vec_load_lanestiv4hi} loads 8 16-bit values
++from memory into a register of mode @samp{TI}@. The register
++contains two consecutive vectors of mode @samp{V4HI}@.
++
++This pattern can only be used if:
++@smallexample
++TARGET_ARRAY_MODE_SUPPORTED_P (@var{n}, @var{c})
++@end smallexample
++is true. GCC assumes that, if a target supports this kind of
++instruction for some mode @var{n}, it also supports unaligned
++loads for vectors of mode @var{n}.
++
++@cindex @code{vec_store_lanes@var{m}@var{n}} instruction pattern
++@item @samp{vec_store_lanes@var{m}@var{n}}
++Equivalent to @samp{vec_load_lanes@var{m}@var{n}}, with the memory
++and register operands reversed. That is, the instruction is
++equivalent to:
++
++@smallexample
++int c = GET_MODE_SIZE (@var{m}) / GET_MODE_SIZE (@var{n});
++for (j = 0; j < GET_MODE_NUNITS (@var{n}); j++)
++ for (i = 0; i < c; i++)
++ operand0[j * c + i] = operand1[i][j];
++@end smallexample
++
++for a memory operand 0 and register operand 1.
++
+ @cindex @code{vec_set@var{m}} instruction pattern
+ @item @samp{vec_set@var{m}}
+ Set given field in the vector value. Operand 0 is the vector to modify,
+
+=== modified file 'gcc/expr.c'
+--- old/gcc/expr.c 2011-05-26 14:27:33 +0000
++++ new/gcc/expr.c 2011-06-02 12:12:00 +0000
+@@ -8537,10 +8537,13 @@
+ if (code == SSA_NAME
+ && (g = SSA_NAME_DEF_STMT (ssa_name))
+ && gimple_code (g) == GIMPLE_CALL)
+- pmode = promote_function_mode (type, mode, &unsignedp,
+- TREE_TYPE
+- (TREE_TYPE (gimple_call_fn (g))),
+- 2);
++ {
++ gcc_assert (!gimple_call_internal_p (g));
++ pmode = promote_function_mode (type, mode, &unsignedp,
++ TREE_TYPE
++ (TREE_TYPE (gimple_call_fn (g))),
++ 2);
++ }
+ else
+ pmode = promote_decl_mode (exp, &unsignedp);
+ gcc_assert (GET_MODE (decl_rtl) == pmode);
+
+=== modified file 'gcc/genopinit.c'
+--- old/gcc/genopinit.c 2011-01-03 20:52:22 +0000
++++ new/gcc/genopinit.c 2011-05-05 15:43:06 +0000
+@@ -74,6 +74,8 @@
+ "set_convert_optab_handler (fractuns_optab, $B, $A, CODE_FOR_$(fractuns$Q$a$I$b2$))",
+ "set_convert_optab_handler (satfract_optab, $B, $A, CODE_FOR_$(satfract$a$Q$b2$))",
+ "set_convert_optab_handler (satfractuns_optab, $B, $A, CODE_FOR_$(satfractuns$I$a$Q$b2$))",
++ "set_convert_optab_handler (vec_load_lanes_optab, $A, $B, CODE_FOR_$(vec_load_lanes$a$b$))",
++ "set_convert_optab_handler (vec_store_lanes_optab, $A, $B, CODE_FOR_$(vec_store_lanes$a$b$))",
+ "set_optab_handler (add_optab, $A, CODE_FOR_$(add$P$a3$))",
+ "set_optab_handler (addv_optab, $A, CODE_FOR_$(add$F$a3$)),\n\
+ set_optab_handler (add_optab, $A, CODE_FOR_$(add$F$a3$))",
+
+=== modified file 'gcc/gimple-low.c'
+--- old/gcc/gimple-low.c 2011-02-08 11:15:53 +0000
++++ new/gcc/gimple-low.c 2011-05-05 15:42:22 +0000
+@@ -218,6 +218,10 @@
+ tree fndecl, parms, p;
+ unsigned int i, nargs;
+
++ /* Calls to internal functions always match their signature. */
++ if (gimple_call_internal_p (stmt))
++ return true;
++
+ nargs = gimple_call_num_args (stmt);
+
+ /* Get argument types for verification. */
+
+=== modified file 'gcc/gimple-pretty-print.c'
+--- old/gcc/gimple-pretty-print.c 2011-02-15 18:36:16 +0000
++++ new/gcc/gimple-pretty-print.c 2011-05-05 15:42:22 +0000
+@@ -596,8 +596,12 @@
+
+ if (flags & TDF_RAW)
+ {
+- dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T",
+- gs, gimple_call_fn (gs), lhs);
++ if (gimple_call_internal_p (gs))
++ dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T", gs,
++ internal_fn_name (gimple_call_internal_fn (gs)), lhs);
++ else
++ dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T",
++ gs, gimple_call_fn (gs), lhs);
+ if (gimple_call_num_args (gs) > 0)
+ {
+ pp_string (buffer, ", ");
+@@ -617,7 +621,10 @@
+
+ pp_space (buffer);
+ }
+- print_call_name (buffer, gimple_call_fn (gs), flags);
++ if (gimple_call_internal_p (gs))
++ pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs)));
++ else
++ print_call_name (buffer, gimple_call_fn (gs), flags);
+ pp_string (buffer, " (");
+ dump_gimple_call_args (buffer, gs, flags);
+ pp_character (buffer, ')');
+
+=== modified file 'gcc/gimple.c'
+--- old/gcc/gimple.c 2011-05-18 13:33:53 +0000
++++ new/gcc/gimple.c 2011-06-02 12:12:00 +0000
+@@ -276,6 +276,59 @@
+ }
+
+
++/* Helper for gimple_build_call_internal and gimple_build_call_internal_vec.
++ Build the basic components of a GIMPLE_CALL statement to internal
++ function FN with NARGS arguments. */
++
++static inline gimple
++gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
++{
++ gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
++ s->gsbase.subcode |= GF_CALL_INTERNAL;
++ gimple_call_set_internal_fn (s, fn);
++ gimple_call_reset_alias_info (s);
++ return s;
++}
++
++
++/* Build a GIMPLE_CALL statement to internal function FN. NARGS is
++ the number of arguments. The ... are the arguments. */
++
++gimple
++gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
++{
++ va_list ap;
++ gimple call;
++ unsigned i;
++
++ call = gimple_build_call_internal_1 (fn, nargs);
++ va_start (ap, nargs);
++ for (i = 0; i < nargs; i++)
++ gimple_call_set_arg (call, i, va_arg (ap, tree));
++ va_end (ap);
++
++ return call;
++}
++
++
++/* Build a GIMPLE_CALL statement to internal function FN with the arguments
++ specified in vector ARGS. */
++
++gimple
++gimple_build_call_internal_vec (enum internal_fn fn, VEC(tree, heap) *args)
++{
++ unsigned i, nargs;
++ gimple call;
++
++ nargs = VEC_length (tree, args);
++ call = gimple_build_call_internal_1 (fn, nargs);
++ for (i = 0; i < nargs; i++)
++ gimple_call_set_arg (call, i, VEC_index (tree, args, i));
++
++ return call;
++}
++
++
+ /* Build a GIMPLE_CALL statement from CALL_EXPR T. Note that T is
+ assumed to be in GIMPLE form already. Minimal checking is done of
+ this fact. */
+@@ -1774,6 +1827,20 @@
+ return (gimple_body (fndecl) || (fn && fn->cfg));
+ }
+
++/* Return true if calls C1 and C2 are known to go to the same function. */
++
++bool
++gimple_call_same_target_p (const_gimple c1, const_gimple c2)
++{
++ if (gimple_call_internal_p (c1))
++ return (gimple_call_internal_p (c2)
++ && gimple_call_internal_fn (c1) == gimple_call_internal_fn (c2));
++ else
++ return (gimple_call_fn (c1) == gimple_call_fn (c2)
++ || (gimple_call_fndecl (c1)
++ && gimple_call_fndecl (c1) == gimple_call_fndecl (c2)));
++}
++
+ /* Detect flags from a GIMPLE_CALL. This is just like
+ call_expr_flags, but for gimple tuples. */
+
+@@ -1786,6 +1853,8 @@
+
+ if (decl)
+ flags = flags_from_decl_or_type (decl);
++ else if (gimple_call_internal_p (stmt))
++ flags = internal_fn_flags (gimple_call_internal_fn (stmt));
+ else
+ {
+ t = TREE_TYPE (gimple_call_fn (stmt));
+@@ -1801,18 +1870,35 @@
+ return flags;
+ }
+
++/* Return the "fn spec" string for call STMT. */
++
++static tree
++gimple_call_fnspec (const_gimple stmt)
++{
++ tree fn, type, attr;
++
++ fn = gimple_call_fn (stmt);
++ if (!fn)
++ return NULL_TREE;
++
++ type = TREE_TYPE (TREE_TYPE (fn));
++ if (!type)
++ return NULL_TREE;
++
++ attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
++ if (!attr)
++ return NULL_TREE;
++
++ return TREE_VALUE (TREE_VALUE (attr));
++}
++
+ /* Detects argument flags for argument number ARG on call STMT. */
+
+ int
+ gimple_call_arg_flags (const_gimple stmt, unsigned arg)
+ {
+- tree type = TREE_TYPE (TREE_TYPE (gimple_call_fn (stmt)));
+- tree attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
+- if (!attr)
+- return 0;
+-
+- attr = TREE_VALUE (TREE_VALUE (attr));
+- if (1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
++ tree attr = gimple_call_fnspec (stmt);
++ if (!attr || 1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
+ return 0;
+
+ switch (TREE_STRING_POINTER (attr)[1 + arg])
+@@ -1850,13 +1936,8 @@
+ if (gimple_call_flags (stmt) & ECF_MALLOC)
+ return ERF_NOALIAS;
+
+- type = TREE_TYPE (TREE_TYPE (gimple_call_fn (stmt)));
+- attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
+- if (!attr)
+- return 0;
+-
+- attr = TREE_VALUE (TREE_VALUE (attr));
+- if (TREE_STRING_LENGTH (attr) < 1)
++ attr = gimple_call_fnspec (stmt);
++ if (!attr || TREE_STRING_LENGTH (attr) < 1)
+ return 0;
+
+ switch (TREE_STRING_POINTER (attr)[0])
+@@ -2293,6 +2374,7 @@
+ if (is_gimple_call (s))
+ {
+ unsigned nargs = gimple_call_num_args (s);
++ tree fn;
+
+ if (!(gimple_call_flags (s) & (ECF_CONST | ECF_PURE)))
+ return true;
+@@ -2307,7 +2389,8 @@
+ return true;
+ }
+
+- if (TREE_SIDE_EFFECTS (gimple_call_fn (s)))
++ fn = gimple_call_fn (s);
++ if (fn && TREE_SIDE_EFFECTS (fn))
+ return true;
+
+ for (i = 0; i < nargs; i++)
+@@ -2349,14 +2432,15 @@
+ if (is_gimple_call (s))
+ {
+ unsigned nargs = gimple_call_num_args (s);
++ tree fn;
+
+ if (!(gimple_call_flags (s) & (ECF_CONST | ECF_PURE)))
+ return true;
+
+ /* We cannot use gimple_has_volatile_ops here,
+ because we must ignore a volatile LHS. */
+- if (TREE_SIDE_EFFECTS (gimple_call_fn (s))
+- || TREE_THIS_VOLATILE (gimple_call_fn (s)))
++ fn = gimple_call_fn (s);
++ if (fn && (TREE_SIDE_EFFECTS (fn) || TREE_THIS_VOLATILE (fn)))
+ {
+ gcc_assert (gimple_has_volatile_ops (s));
+ return true;
+@@ -3113,7 +3197,6 @@
+ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
+ {
+ int i;
+- tree fn = gimple_call_fn (stmt);
+ int nargs = gimple_call_num_args (stmt);
+ VEC(tree, heap) *vargs = VEC_alloc (tree, heap, nargs);
+ gimple new_stmt;
+@@ -3122,7 +3205,11 @@
+ if (!bitmap_bit_p (args_to_skip, i))
+ VEC_quick_push (tree, vargs, gimple_call_arg (stmt, i));
+
+- new_stmt = gimple_build_call_vec (fn, vargs);
++ if (gimple_call_internal_p (stmt))
++ new_stmt = gimple_build_call_internal_vec (gimple_call_internal_fn (stmt),
++ vargs);
++ else
++ new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
+ VEC_free (tree, heap, vargs);
+ if (gimple_call_lhs (stmt))
+ gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
+
+=== modified file 'gcc/gimple.h'
+--- old/gcc/gimple.h 2011-04-18 21:58:03 +0000
++++ new/gcc/gimple.h 2011-06-02 12:12:00 +0000
+@@ -30,6 +30,7 @@
+ #include "basic-block.h"
+ #include "tree-ssa-operands.h"
+ #include "tree-ssa-alias.h"
++#include "internal-fn.h"
+
+ struct gimple_seq_node_d;
+ typedef struct gimple_seq_node_d *gimple_seq_node;
+@@ -82,6 +83,8 @@
+ name, a _DECL, a _REF, etc. */
+ };
+
++#define GF_CALL_INTERNAL_FN_SHIFT 8
++
+ /* Specific flags for individual GIMPLE statements. These flags are
+ always stored in gimple_statement_base.subcode and they may only be
+ defined for statement codes that do not use sub-codes.
+@@ -102,6 +105,8 @@
+ GF_CALL_TAILCALL = 1 << 3,
+ GF_CALL_VA_ARG_PACK = 1 << 4,
+ GF_CALL_NOTHROW = 1 << 5,
++ GF_CALL_INTERNAL = 1 << 6,
++ GF_CALL_INTERNAL_FN = 0xff << GF_CALL_INTERNAL_FN_SHIFT,
+ GF_OMP_PARALLEL_COMBINED = 1 << 0,
+
+ /* True on an GIMPLE_OMP_RETURN statement if the return does not require
+@@ -817,6 +822,8 @@
+
+ gimple gimple_build_call_vec (tree, VEC(tree, heap) *);
+ gimple gimple_build_call (tree, unsigned, ...);
++gimple gimple_build_call_internal (enum internal_fn, unsigned, ...);
++gimple gimple_build_call_internal_vec (enum internal_fn, VEC(tree, heap) *);
+ gimple gimple_build_call_from_tree (tree);
+ gimple gimplify_assign (tree, tree, gimple_seq *);
+ gimple gimple_build_cond (enum tree_code, tree, tree, tree, tree);
+@@ -861,6 +868,7 @@
+ void gimple_seq_free (gimple_seq);
+ void gimple_seq_add_seq (gimple_seq *, gimple_seq);
+ gimple_seq gimple_seq_copy (gimple_seq);
++bool gimple_call_same_target_p (const_gimple, const_gimple);
+ int gimple_call_flags (const_gimple);
+ int gimple_call_return_flags (const_gimple);
+ int gimple_call_arg_flags (const_gimple, unsigned);
+@@ -2012,6 +2020,27 @@
+ }
+
+
++/* Return true if call GS calls an internal-only function, as enumerated
++ by internal_fn. */
++
++static inline bool
++gimple_call_internal_p (const_gimple gs)
++{
++ GIMPLE_CHECK (gs, GIMPLE_CALL);
++ return (gs->gsbase.subcode & GF_CALL_INTERNAL) != 0;
++}
++
++
++/* Return the target of internal call GS. */
++
++static inline enum internal_fn
++gimple_call_internal_fn (const_gimple gs)
++{
++ gcc_assert (gimple_call_internal_p (gs));
++ return (enum internal_fn) (gs->gsbase.subcode >> GF_CALL_INTERNAL_FN_SHIFT);
++}
++
++
+ /* Return a pointer to the tree node representing the function called by call
+ statement GS. */
+
+@@ -2029,6 +2058,7 @@
+ gimple_call_set_fn (gimple gs, tree fn)
+ {
+ GIMPLE_CHECK (gs, GIMPLE_CALL);
++ gcc_assert (!gimple_call_internal_p (gs));
+ gimple_set_op (gs, 1, fn);
+ }
+
+@@ -2039,10 +2069,23 @@
+ gimple_call_set_fndecl (gimple gs, tree decl)
+ {
+ GIMPLE_CHECK (gs, GIMPLE_CALL);
++ gcc_assert (!gimple_call_internal_p (gs));
+ gimple_set_op (gs, 1, build_fold_addr_expr_loc (gimple_location (gs), decl));
+ }
+
+
++/* Set internal function FN to be the function called by call statement GS. */
++
++static inline void
++gimple_call_set_internal_fn (gimple gs, enum internal_fn fn)
++{
++ GIMPLE_CHECK (gs, GIMPLE_CALL);
++ gcc_assert (gimple_call_internal_p (gs));
++ gs->gsbase.subcode &= ~GF_CALL_INTERNAL_FN;
++ gs->gsbase.subcode |= (int) fn << GF_CALL_INTERNAL_FN_SHIFT;
++}
++
++
+ /* If a given GIMPLE_CALL's callee is a FUNCTION_DECL, return it.
+ Otherwise return NULL. This function is analogous to
+ get_callee_fndecl in tree land. */
+@@ -2051,7 +2094,7 @@
+ gimple_call_fndecl (const_gimple gs)
+ {
+ tree addr = gimple_call_fn (gs);
+- if (TREE_CODE (addr) == ADDR_EXPR)
++ if (addr && TREE_CODE (addr) == ADDR_EXPR)
+ {
+ tree fndecl = TREE_OPERAND (addr, 0);
+ if (TREE_CODE (fndecl) == MEM_REF)
+@@ -2073,8 +2116,13 @@
+ static inline tree
+ gimple_call_return_type (const_gimple gs)
+ {
+- tree fn = gimple_call_fn (gs);
+- tree type = TREE_TYPE (fn);
++ tree fn, type;
++
++ fn = gimple_call_fn (gs);
++ if (fn == NULL_TREE)
++ return TREE_TYPE (gimple_call_lhs (gs));
++
++ type = TREE_TYPE (fn);
+
+ /* See through the pointer. */
+ type = TREE_TYPE (type);
+
+=== added file 'gcc/internal-fn.c'
+--- old/gcc/internal-fn.c 1970-01-01 00:00:00 +0000
++++ new/gcc/internal-fn.c 2011-05-05 15:43:06 +0000
+@@ -0,0 +1,147 @@
++/* Internal functions.
++ Copyright (C) 2011 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++#include "config.h"
++#include "system.h"
++#include "coretypes.h"
++#include "gimple.h"
++#include "tree.h"
++#include "expr.h"
++#include "optabs.h"
++#include "recog.h"
++
++/* The names of each internal function, indexed by function number. */
++const char *const internal_fn_name_array[] = {
++#define DEF_INTERNAL_FN(CODE, FLAGS) #CODE,
++#include "internal-fn.def"
++#undef DEF_INTERNAL_FN
++ "<invalid-fn>"
++};
++
++/* The ECF_* flags of each internal function, indexed by function number. */
++const int internal_fn_flags_array[] = {
++#define DEF_INTERNAL_FN(CODE, FLAGS) FLAGS,
++#include "internal-fn.def"
++#undef DEF_INTERNAL_FN
++ 0
++};
++
++/* ARRAY_TYPE is an array of vector modes. Return the associated insn
++ for load-lanes-style optab OPTAB. The insn must exist. */
++
++static enum insn_code
++get_multi_vector_move (tree array_type, convert_optab optab)
++{
++ enum insn_code icode;
++ enum machine_mode imode;
++ enum machine_mode vmode;
++
++ gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
++ imode = TYPE_MODE (array_type);
++ vmode = TYPE_MODE (TREE_TYPE (array_type));
++
++ icode = convert_optab_handler (optab, imode, vmode);
++ gcc_assert (icode != CODE_FOR_nothing);
++ return icode;
++}
++
++/* Expand LOAD_LANES call STMT. */
++
++static void
++expand_LOAD_LANES (gimple stmt)
++{
++ tree type, lhs, rhs;
++ rtx target, mem;
++ enum insn_code icode;
++ const struct insn_operand_data *operand;
++
++ lhs = gimple_call_lhs (stmt);
++ rhs = gimple_call_arg (stmt, 0);
++ type = TREE_TYPE (lhs);
++
++ target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
++ mem = expand_normal (rhs);
++
++ gcc_assert (REG_P (target));
++ gcc_assert (MEM_P (mem));
++ PUT_MODE (mem, TYPE_MODE (type));
++
++ icode = get_multi_vector_move (type, vec_load_lanes_optab);
++
++ operand = &insn_data[(int) icode].operand[1];
++ if (operand->predicate && !operand->predicate (mem, operand->mode))
++ mem = replace_equiv_address (mem, force_reg (Pmode, XEXP (mem, 0)));
++
++ emit_insn (GEN_FCN (icode) (target, mem));
++}
++
++/* Expand STORE_LANES call STMT. */
++
++static void
++expand_STORE_LANES (gimple stmt)
++{
++ tree type, lhs, rhs;
++ rtx target, reg;
++ enum insn_code icode;
++ const struct insn_operand_data *operand;
++
++ lhs = gimple_call_lhs (stmt);
++ rhs = gimple_call_arg (stmt, 0);
++ type = TREE_TYPE (rhs);
++
++ target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
++ reg = expand_normal (rhs);
++
++ gcc_assert (MEM_P (target));
++ PUT_MODE (target, TYPE_MODE (type));
++
++ icode = get_multi_vector_move (type, vec_store_lanes_optab);
++
++ operand = &insn_data[(int) icode].operand[0];
++ if (operand->predicate && !operand->predicate (target, operand->mode))
++ target = replace_equiv_address (target,
++ force_reg (Pmode, XEXP (target, 0)));
++
++ operand = &insn_data[(int) icode].operand[1];
++ if (operand->predicate && !operand->predicate (reg, operand->mode))
++ reg = force_reg (TYPE_MODE (type), reg);
++
++ emit_insn (GEN_FCN (icode) (target, reg));
++}
++
++/* Routines to expand each internal function, indexed by function number.
++ Each routine has the prototype:
++
++ expand_<NAME> (gimple stmt)
++
++ where STMT is the statement that performs the call. */
++static void (*const internal_fn_expanders[]) (gimple) = {
++#define DEF_INTERNAL_FN(CODE, FLAGS) expand_##CODE,
++#include "internal-fn.def"
++#undef DEF_INTERNAL_FN
++ 0
++};
++
++/* Expand STMT, which is a call to internal function FN. */
++
++void
++expand_internal_call (gimple stmt)
++{
++ internal_fn_expanders[(int) gimple_call_internal_fn (stmt)] (stmt);
++}
+
+=== added file 'gcc/internal-fn.def'
+--- old/gcc/internal-fn.def 1970-01-01 00:00:00 +0000
++++ new/gcc/internal-fn.def 2011-05-05 15:43:06 +0000
+@@ -0,0 +1,42 @@
++/* Internal functions.
++ Copyright (C) 2011 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++/* This file specifies a list of internal "functions". These functions
++ differ from built-in functions in that they have no linkage and cannot
++ be called directly by the user. They represent operations that are only
++ synthesised by GCC itself.
++
++ Internal functions are used instead of tree codes if the operation
++ and its operands are more naturally represented as a GIMPLE_CALL
++ than a GIMPLE_ASSIGN.
++
++ Each entry in this file has the form:
++
++ DEF_INTERNAL_FN (NAME, FLAGS)
++
++ where NAME is the name of the function and FLAGS is a set of
++ ECF_* flags. Each entry must have a corresponding expander
++ of the form:
++
++ void expand_NAME (gimple stmt)
++
++ where STMT is the statement that performs the call. */
++
++DEF_INTERNAL_FN (LOAD_LANES, ECF_CONST | ECF_LEAF)
++DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF)
+
+=== added file 'gcc/internal-fn.h'
+--- old/gcc/internal-fn.h 1970-01-01 00:00:00 +0000
++++ new/gcc/internal-fn.h 2011-05-05 15:42:22 +0000
+@@ -0,0 +1,52 @@
++/* Internal functions.
++ Copyright (C) 2011 Free Software Foundation, Inc.
++
++This file is part of GCC.
++
++GCC is free software; you can redistribute it and/or modify it under
++the terms of the GNU General Public License as published by the Free
++Software Foundation; either version 3, or (at your option) any later
++version.
++
++GCC is distributed in the hope that it will be useful, but WITHOUT ANY
++WARRANTY; without even the implied warranty of MERCHANTABILITY or
++FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
++for more details.
++
++You should have received a copy of the GNU General Public License
++along with GCC; see the file COPYING3. If not see
++<http://www.gnu.org/licenses/>. */
++
++#ifndef GCC_INTERNAL_FN_H
++#define GCC_INTERNAL_FN_H
++
++enum internal_fn {
++#define DEF_INTERNAL_FN(CODE, FLAGS) IFN_##CODE,
++#include "internal-fn.def"
++#undef DEF_INTERNAL_FN
++ IFN_LAST
++};
++
++extern const char *const internal_fn_name_array[];
++extern const int internal_fn_flags_array[];
++
++/* Return the name of internal function FN. The name is only meaningful
++ for dumps; it has no linkage. */
++
++static inline const char *
++internal_fn_name (enum internal_fn fn)
++{
++ return internal_fn_name_array[(int) fn];
++}
++
++/* Return the ECF_* flags for function FN. */
++
++static inline int
++internal_fn_flags (enum internal_fn fn)
++{
++ return internal_fn_flags_array[(int) fn];
++}
++
++extern void expand_internal_call (gimple);
++
++#endif
+
+=== modified file 'gcc/ipa-prop.c'
+--- old/gcc/ipa-prop.c 2011-04-18 21:58:03 +0000
++++ new/gcc/ipa-prop.c 2011-06-02 12:12:00 +0000
+@@ -1418,6 +1418,8 @@
+ {
+ tree target = gimple_call_fn (call);
+
++ if (!target)
++ return;
+ if (TREE_CODE (target) == SSA_NAME)
+ ipa_analyze_indirect_call_uses (node, info, parms_info, call, target);
+ else if (TREE_CODE (target) == OBJ_TYPE_REF)
+
+=== modified file 'gcc/optabs.h'
+--- old/gcc/optabs.h 2011-01-03 20:52:22 +0000
++++ new/gcc/optabs.h 2011-05-05 15:43:06 +0000
+@@ -578,6 +578,9 @@
+ COI_satfract,
+ COI_satfractuns,
+
++ COI_vec_load_lanes,
++ COI_vec_store_lanes,
++
+ COI_MAX
+ };
+
+@@ -598,6 +601,8 @@
+ #define fractuns_optab (&convert_optab_table[COI_fractuns])
+ #define satfract_optab (&convert_optab_table[COI_satfract])
+ #define satfractuns_optab (&convert_optab_table[COI_satfractuns])
++#define vec_load_lanes_optab (&convert_optab_table[COI_vec_load_lanes])
++#define vec_store_lanes_optab (&convert_optab_table[COI_vec_store_lanes])
+
+ /* Contains the optab used for each rtx code. */
+ extern optab code_to_optab[NUM_RTX_CODE + 1];
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/O3-pr39675-2.c'
+--- old/gcc/testsuite/gcc.dg/vect/O3-pr39675-2.c 2009-04-20 10:26:18 +0000
++++ new/gcc/testsuite/gcc.dg/vect/O3-pr39675-2.c 2011-05-05 15:46:10 +0000
+@@ -26,7 +26,7 @@
+ }
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided_wide } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_strided_wide } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided4 } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_strided4 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c'
+--- old/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-12.c 2011-05-05 15:46:10 +0000
+@@ -113,7 +113,7 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" {target { vect_strided && vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" {target { vect_strided && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" {target { vect_strided8 && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" {target { vect_strided8 && vect_int_mult } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/fast-math-pr35982.c'
+--- old/gcc/testsuite/gcc.dg/vect/fast-math-pr35982.c 2008-08-26 08:14:37 +0000
++++ new/gcc/testsuite/gcc.dg/vect/fast-math-pr35982.c 2011-05-05 15:44:00 +0000
+@@ -20,7 +20,7 @@
+ return avg;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_extract_even_odd_wide } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail vect_extract_even_odd_wide } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_extract_even_odd } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail vect_extract_even_odd } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/fast-math-slp-27.c'
+--- old/gcc/testsuite/gcc.dg/vect/fast-math-slp-27.c 2010-08-26 11:13:58 +0000
++++ new/gcc/testsuite/gcc.dg/vect/fast-math-slp-27.c 2011-05-05 15:46:10 +0000
+@@ -13,5 +13,5 @@
+ }
+ }
+
+-/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target vect_strided } } } */
++/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/fast-math-vect-complex-3.c'
+--- old/gcc/testsuite/gcc.dg/vect/fast-math-vect-complex-3.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/fast-math-vect-complex-3.c 2011-05-05 15:46:10 +0000
+@@ -56,5 +56,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd_wide } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/if-cvt-stores-vect-ifcvt-18.c'
+--- old/gcc/testsuite/gcc.dg/vect/if-cvt-stores-vect-ifcvt-18.c 2011-04-24 07:45:49 +0000
++++ new/gcc/testsuite/gcc.dg/vect/if-cvt-stores-vect-ifcvt-18.c 2011-05-05 15:46:10 +0000
+@@ -65,5 +65,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align || {! vect_strided } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align || { ! vect_strided2 } } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/no-scevccp-outer-10a.c'
+--- old/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-10a.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-10a.c 2011-05-05 15:46:10 +0000
+@@ -54,5 +54,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/no-scevccp-outer-10b.c'
+--- old/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-10b.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-10b.c 2011-05-05 15:46:10 +0000
+@@ -53,5 +53,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/no-scevccp-outer-18.c'
+--- old/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-18.c 2007-10-21 09:01:16 +0000
++++ new/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-18.c 2011-05-05 15:46:10 +0000
+@@ -47,5 +47,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target vect_interleave } } } */
++/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target { vect_interleave || vect_strided2 } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/no-scevccp-outer-20.c'
+--- old/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-20.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-20.c 2011-05-05 15:46:10 +0000
+@@ -50,5 +50,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/pr30843.c'
+--- old/gcc/testsuite/gcc.dg/vect/pr30843.c 2007-02-22 12:30:12 +0000
++++ new/gcc/testsuite/gcc.dg/vect/pr30843.c 2011-05-05 15:46:10 +0000
+@@ -20,6 +20,6 @@
+ }
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave || vect_strided4 } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/pr33866.c'
+--- old/gcc/testsuite/gcc.dg/vect/pr33866.c 2007-10-30 08:26:14 +0000
++++ new/gcc/testsuite/gcc.dg/vect/pr33866.c 2011-05-05 15:46:10 +0000
+@@ -27,6 +27,6 @@
+ }
+
+ /* Needs interleaving support. */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave || vect_strided2 } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/pr37539.c'
+--- old/gcc/testsuite/gcc.dg/vect/pr37539.c 2009-11-26 02:03:50 +0000
++++ new/gcc/testsuite/gcc.dg/vect/pr37539.c 2011-05-05 15:46:10 +0000
+@@ -40,7 +40,7 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target vect_strided_wide } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target { vect_strided4 && vect_strided2 } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+
+=== removed file 'gcc/testsuite/gcc.dg/vect/slp-11.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-11.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-11.c 1970-01-01 00:00:00 +0000
+@@ -1,113 +0,0 @@
+-/* { dg-require-effective-target vect_int } */
+-
+-#include <stdarg.h>
+-#include "tree-vect.h"
+-
+-#define N 8
+-
+-int
+-main1 ()
+-{
+- int i;
+- unsigned int out[N*8], a0, a1, a2, a3, a4, a5, a6, a7, b1, b0, b2, b3, b4, b5, b6, b7;
+- unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
+- float out2[N*8];
+-
+- /* Different operations - not SLPable. */
+- for (i = 0; i < N; i++)
+- {
+- a0 = in[i*8] + 5;
+- a1 = in[i*8 + 1] * 6;
+- a2 = in[i*8 + 2] + 7;
+- a3 = in[i*8 + 3] + 8;
+- a4 = in[i*8 + 4] + 9;
+- a5 = in[i*8 + 5] + 10;
+- a6 = in[i*8 + 6] + 11;
+- a7 = in[i*8 + 7] + 12;
+-
+- b0 = a0 * 3;
+- b1 = a1 * 2;
+- b2 = a2 * 12;
+- b3 = a3 * 5;
+- b4 = a4 * 8;
+- b5 = a5 * 4;
+- b6 = a6 * 3;
+- b7 = a7 * 2;
+-
+- out[i*8] = b0 - 2;
+- out[i*8 + 1] = b1 - 3;
+- out[i*8 + 2] = b2 - 2;
+- out[i*8 + 3] = b3 - 1;
+- out[i*8 + 4] = b4 - 8;
+- out[i*8 + 5] = b5 - 7;
+- out[i*8 + 6] = b6 - 3;
+- out[i*8 + 7] = b7 - 7;
+- }
+-
+- /* check results: */
+- for (i = 0; i < N; i++)
+- {
+- if (out[i*8] != (in[i*8] + 5) * 3 - 2
+- || out[i*8 + 1] != (in[i*8 + 1] * 6) * 2 - 3
+- || out[i*8 + 2] != (in[i*8 + 2] + 7) * 12 - 2
+- || out[i*8 + 3] != (in[i*8 + 3] + 8) * 5 - 1
+- || out[i*8 + 4] != (in[i*8 + 4] + 9) * 8 - 8
+- || out[i*8 + 5] != (in[i*8 + 5] + 10) * 4 - 7
+- || out[i*8 + 6] != (in[i*8 + 6] + 11) * 3 - 3
+- || out[i*8 + 7] != (in[i*8 + 7] + 12) * 2 - 7)
+- abort ();
+- }
+-
+- /* Requires permutation - not SLPable. */
+- for (i = 0; i < N*2; i++)
+- {
+- out[i*4] = (in[i*4] + 2) * 3;
+- out[i*4 + 1] = (in[i*4 + 2] + 2) * 7;
+- out[i*4 + 2] = (in[i*4 + 1] + 7) * 3;
+- out[i*4 + 3] = (in[i*4 + 3] + 3) * 4;
+- }
+-
+- /* check results: */
+- for (i = 0; i < N*2; i++)
+- {
+- if (out[i*4] != (in[i*4] + 2) * 3
+- || out[i*4 + 1] != (in[i*4 + 2] + 2) * 7
+- || out[i*4 + 2] != (in[i*4 + 1] + 7) * 3
+- || out[i*4 + 3] != (in[i*4 + 3] + 3) * 4)
+- abort ();
+- }
+-
+- /* Different operations - not SLPable. */
+- for (i = 0; i < N*4; i++)
+- {
+- out2[i*2] = ((float) in[i*2] * 2 + 6) ;
+- out2[i*2 + 1] = (float) (in[i*2 + 1] * 3 + 7);
+- }
+-
+- /* check results: */
+- for (i = 0; i < N*4; i++)
+- {
+- if (out2[i*2] != ((float) in[i*2] * 2 + 6)
+- || out2[i*2 + 1] != (float) (in[i*2 + 1] * 3 + 7))
+- abort ();
+- }
+-
+-
+- return 0;
+-}
+-
+-int main (void)
+-{
+- check_vect ();
+-
+- main1 ();
+-
+- return 0;
+-}
+-
+-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target { { vect_uintfloat_cvt && vect_strided_wide } && vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target { { { ! vect_uintfloat_cvt } && vect_strided_wide } && vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" {target { ! { vect_int_mult && vect_strided_wide } } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */
+-/* { dg-final { cleanup-tree-dump "vect" } } */
+-
+
+=== added file 'gcc/testsuite/gcc.dg/vect/slp-11a.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-11a.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-11a.c 2011-05-05 15:46:10 +0000
+@@ -0,0 +1,75 @@
++/* { dg-require-effective-target vect_int } */
++
++#include <stdarg.h>
++#include "tree-vect.h"
++
++#define N 8
++
++int
++main1 ()
++{
++ int i;
++ unsigned int out[N*8], a0, a1, a2, a3, a4, a5, a6, a7, b1, b0, b2, b3, b4, b5, b6, b7;
++ unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
++
++ /* Different operations - not SLPable. */
++ for (i = 0; i < N; i++)
++ {
++ a0 = in[i*8] + 5;
++ a1 = in[i*8 + 1] * 6;
++ a2 = in[i*8 + 2] + 7;
++ a3 = in[i*8 + 3] + 8;
++ a4 = in[i*8 + 4] + 9;
++ a5 = in[i*8 + 5] + 10;
++ a6 = in[i*8 + 6] + 11;
++ a7 = in[i*8 + 7] + 12;
++
++ b0 = a0 * 3;
++ b1 = a1 * 2;
++ b2 = a2 * 12;
++ b3 = a3 * 5;
++ b4 = a4 * 8;
++ b5 = a5 * 4;
++ b6 = a6 * 3;
++ b7 = a7 * 2;
++
++ out[i*8] = b0 - 2;
++ out[i*8 + 1] = b1 - 3;
++ out[i*8 + 2] = b2 - 2;
++ out[i*8 + 3] = b3 - 1;
++ out[i*8 + 4] = b4 - 8;
++ out[i*8 + 5] = b5 - 7;
++ out[i*8 + 6] = b6 - 3;
++ out[i*8 + 7] = b7 - 7;
++ }
++
++ /* check results: */
++ for (i = 0; i < N; i++)
++ {
++ if (out[i*8] != (in[i*8] + 5) * 3 - 2
++ || out[i*8 + 1] != (in[i*8 + 1] * 6) * 2 - 3
++ || out[i*8 + 2] != (in[i*8 + 2] + 7) * 12 - 2
++ || out[i*8 + 3] != (in[i*8 + 3] + 8) * 5 - 1
++ || out[i*8 + 4] != (in[i*8 + 4] + 9) * 8 - 8
++ || out[i*8 + 5] != (in[i*8 + 5] + 10) * 4 - 7
++ || out[i*8 + 6] != (in[i*8 + 6] + 11) * 3 - 3
++ || out[i*8 + 7] != (in[i*8 + 7] + 12) * 2 - 7)
++ abort ();
++ }
++
++ return 0;
++}
++
++int main (void)
++{
++ check_vect ();
++
++ main1 ();
++
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_strided8 && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_strided8 && vect_int_mult } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */
++/* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== added file 'gcc/testsuite/gcc.dg/vect/slp-11b.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-11b.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-11b.c 2011-05-05 15:46:10 +0000
+@@ -0,0 +1,49 @@
++/* { dg-require-effective-target vect_int } */
++
++#include <stdarg.h>
++#include "tree-vect.h"
++
++#define N 8
++
++int
++main1 ()
++{
++ int i;
++ unsigned int out[N*8], a0, a1, a2, a3, a4, a5, a6, a7, b1, b0, b2, b3, b4, b5, b6, b7;
++ unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
++
++ /* Requires permutation - not SLPable. */
++ for (i = 0; i < N*2; i++)
++ {
++ out[i*4] = (in[i*4] + 2) * 3;
++ out[i*4 + 1] = (in[i*4 + 2] + 2) * 7;
++ out[i*4 + 2] = (in[i*4 + 1] + 7) * 3;
++ out[i*4 + 3] = (in[i*4 + 3] + 3) * 4;
++ }
++
++ /* check results: */
++ for (i = 0; i < N*2; i++)
++ {
++ if (out[i*4] != (in[i*4] + 2) * 3
++ || out[i*4 + 1] != (in[i*4 + 2] + 2) * 7
++ || out[i*4 + 2] != (in[i*4 + 1] + 7) * 3
++ || out[i*4 + 3] != (in[i*4 + 3] + 3) * 4)
++ abort ();
++ }
++
++ return 0;
++}
++
++int main (void)
++{
++ check_vect ();
++
++ main1 ();
++
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_strided4 && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_strided4 && vect_int_mult } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */
++/* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== added file 'gcc/testsuite/gcc.dg/vect/slp-11c.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-11c.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-11c.c 2011-05-05 15:46:10 +0000
+@@ -0,0 +1,46 @@
++/* { dg-require-effective-target vect_int } */
++
++#include <stdarg.h>
++#include "tree-vect.h"
++
++#define N 8
++
++int
++main1 ()
++{
++ int i;
++ unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
++ float out[N*8];
++
++ /* Different operations - not SLPable. */
++ for (i = 0; i < N*4; i++)
++ {
++ out[i*2] = ((float) in[i*2] * 2 + 6) ;
++ out[i*2 + 1] = (float) (in[i*2 + 1] * 3 + 7);
++ }
++
++ /* check results: */
++ for (i = 0; i < N*4; i++)
++ {
++ if (out[i*2] != ((float) in[i*2] * 2 + 6)
++ || out[i*2 + 1] != (float) (in[i*2 + 1] * 3 + 7))
++ abort ();
++ }
++
++
++ return 0;
++}
++
++int main (void)
++{
++ check_vect ();
++
++ main1 ();
++
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { { vect_uintfloat_cvt && vect_strided2 } && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { { vect_uintfloat_cvt && vect_strided2 } && vect_int_mult } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */
++/* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/slp-12a.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-12a.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-12a.c 2011-05-05 15:46:10 +0000
+@@ -11,7 +11,7 @@
+ int i;
+ unsigned int out[N*8], a0, a1, a2, a3, a4, a5, a6, a7, b1, b0, b2, b3, b4, b5, b6, b7;
+ unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
+- unsigned int ia[N], ib[N*2];
++ unsigned int ia[N];
+
+ for (i = 0; i < N; i++)
+ {
+@@ -61,27 +61,6 @@
+ abort ();
+ }
+
+- for (i = 0; i < N*2; i++)
+- {
+- out[i*4] = (in[i*4] + 2) * 3;
+- out[i*4 + 1] = (in[i*4 + 1] + 2) * 7;
+- out[i*4 + 2] = (in[i*4 + 2] + 7) * 3;
+- out[i*4 + 3] = (in[i*4 + 3] + 7) * 7;
+-
+- ib[i] = 7;
+- }
+-
+- /* check results: */
+- for (i = 0; i < N*2; i++)
+- {
+- if (out[i*4] != (in[i*4] + 2) * 3
+- || out[i*4 + 1] != (in[i*4 + 1] + 2) * 7
+- || out[i*4 + 2] != (in[i*4 + 2] + 7) * 3
+- || out[i*4 + 3] != (in[i*4 + 3] + 7) * 7
+- || ib[i] != 7)
+- abort ();
+- }
+-
+ return 0;
+ }
+
+@@ -94,11 +73,8 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" {target { vect_strided_wide && vect_int_mult} } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" {target { {! {vect_strided_wide}} && vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" {target { ! vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" {target { vect_strided_wide && vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" {target { {! {vect_strided_wide}} && vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" {target { ! vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_strided8 && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_strided8 && vect_int_mult } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_strided8 && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! { vect_strided8 && vect_int_mult } } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+-
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/slp-12b.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-12b.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-12b.c 2011-05-05 15:46:10 +0000
+@@ -43,9 +43,9 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" {target { vect_strided_wide && vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" {target { { ! { vect_int_mult }} || { ! {vect_strided_wide}}} } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" {target { vect_strided_wide && vect_int_mult } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" {target { { ! { vect_int_mult }} || { ! {vect_strided_wide}}} } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_strided2 && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_strided2 && vect_int_mult } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { vect_strided2 && vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! { vect_strided2 && vect_int_mult } } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== added file 'gcc/testsuite/gcc.dg/vect/slp-12c.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-12c.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-12c.c 2011-05-05 15:44:41 +0000
+@@ -0,0 +1,53 @@
++/* { dg-require-effective-target vect_int } */
++
++#include <stdarg.h>
++#include "tree-vect.h"
++
++#define N 8
++
++int
++main1 ()
++{
++ int i;
++ unsigned int out[N*8], a0, a1, a2, a3, a4, a5, a6, a7, b1, b0, b2, b3, b4, b5, b6, b7;
++ unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
++ unsigned int ia[N*2];
++
++ for (i = 0; i < N*2; i++)
++ {
++ out[i*4] = (in[i*4] + 2) * 3;
++ out[i*4 + 1] = (in[i*4 + 1] + 2) * 7;
++ out[i*4 + 2] = (in[i*4 + 2] + 7) * 3;
++ out[i*4 + 3] = (in[i*4 + 3] + 7) * 7;
++
++ ia[i] = 7;
++ }
++
++ /* check results: */
++ for (i = 0; i < N*2; i++)
++ {
++ if (out[i*4] != (in[i*4] + 2) * 3
++ || out[i*4 + 1] != (in[i*4 + 1] + 2) * 7
++ || out[i*4 + 2] != (in[i*4 + 2] + 7) * 3
++ || out[i*4 + 3] != (in[i*4 + 3] + 7) * 7
++ || ia[i] != 7)
++ abort ();
++ }
++
++ return 0;
++}
++
++int main (void)
++{
++ check_vect ();
++
++ main1 ();
++
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! vect_int_mult } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_int_mult } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! vect_int_mult } } } } */
++/* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/slp-18.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-18.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-18.c 2011-05-05 15:46:10 +0000
+@@ -91,7 +91,7 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_strided } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target { vect_strided } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_strided8 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== removed file 'gcc/testsuite/gcc.dg/vect/slp-19.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-19.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-19.c 1970-01-01 00:00:00 +0000
+@@ -1,154 +0,0 @@
+-/* { dg-require-effective-target vect_int } */
+-
+-#include <stdarg.h>
+-#include "tree-vect.h"
+-
+-#define N 16
+-
+-int
+-main1 ()
+-{
+- unsigned int i;
+- unsigned int out[N*8];
+- unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
+- unsigned int ia[N*2], a0, a1, a2, a3;
+-
+- for (i = 0; i < N; i++)
+- {
+- out[i*8] = in[i*8];
+- out[i*8 + 1] = in[i*8 + 1];
+- out[i*8 + 2] = in[i*8 + 2];
+- out[i*8 + 3] = in[i*8 + 3];
+- out[i*8 + 4] = in[i*8 + 4];
+- out[i*8 + 5] = in[i*8 + 5];
+- out[i*8 + 6] = in[i*8 + 6];
+- out[i*8 + 7] = in[i*8 + 7];
+-
+- ia[i] = in[i*8 + 2];
+- }
+-
+- /* check results: */
+- for (i = 0; i < N; i++)
+- {
+- if (out[i*8] != in[i*8]
+- || out[i*8 + 1] != in[i*8 + 1]
+- || out[i*8 + 2] != in[i*8 + 2]
+- || out[i*8 + 3] != in[i*8 + 3]
+- || out[i*8 + 4] != in[i*8 + 4]
+- || out[i*8 + 5] != in[i*8 + 5]
+- || out[i*8 + 6] != in[i*8 + 6]
+- || out[i*8 + 7] != in[i*8 + 7]
+- || ia[i] != in[i*8 + 2])
+- abort ();
+- }
+-
+- for (i = 0; i < N*2; i++)
+- {
+- a0 = in[i*4] + 1;
+- a1 = in[i*4 + 1] + 2;
+- a2 = in[i*4 + 2] + 3;
+- a3 = in[i*4 + 3] + 4;
+-
+- out[i*4] = a0;
+- out[i*4 + 1] = a1;
+- out[i*4 + 2] = a2;
+- out[i*4 + 3] = a3;
+-
+- ia[i] = a2;
+- }
+-
+- /* check results: */
+- for (i = 0; i < N*2; i++)
+- {
+- if (out[i*4] != in[i*4] + 1
+- || out[i*4 + 1] != in[i*4 + 1] + 2
+- || out[i*4 + 2] != in[i*4 + 2] + 3
+- || out[i*4 + 3] != in[i*4 + 3] + 4
+- || ia[i] != in[i*4 + 2] + 3)
+- abort ();
+- }
+-
+- /* The last stmt requires interleaving of not power of 2 size - not
+- vectorizable. */
+- for (i = 0; i < N/2; i++)
+- {
+- out[i*12] = in[i*12];
+- out[i*12 + 1] = in[i*12 + 1];
+- out[i*12 + 2] = in[i*12 + 2];
+- out[i*12 + 3] = in[i*12 + 3];
+- out[i*12 + 4] = in[i*12 + 4];
+- out[i*12 + 5] = in[i*12 + 5];
+- out[i*12 + 6] = in[i*12 + 6];
+- out[i*12 + 7] = in[i*12 + 7];
+- out[i*12 + 8] = in[i*12 + 8];
+- out[i*12 + 9] = in[i*12 + 9];
+- out[i*12 + 10] = in[i*12 + 10];
+- out[i*12 + 11] = in[i*12 + 11];
+-
+- ia[i] = in[i*12 + 7];
+- }
+-
+- /* check results: */
+- for (i = 0; i < N/2; i++)
+- {
+- if (out[i*12] != in[i*12]
+- || out[i*12 + 1] != in[i*12 + 1]
+- || out[i*12 + 2] != in[i*12 + 2]
+- || out[i*12 + 3] != in[i*12 + 3]
+- || out[i*12 + 4] != in[i*12 + 4]
+- || out[i*12 + 5] != in[i*12 + 5]
+- || out[i*12 + 6] != in[i*12 + 6]
+- || out[i*12 + 7] != in[i*12 + 7]
+- || out[i*12 + 8] != in[i*12 + 8]
+- || out[i*12 + 9] != in[i*12 + 9]
+- || out[i*12 + 10] != in[i*12 + 10]
+- || out[i*12 + 11] != in[i*12 + 11]
+- || ia[i] != in[i*12 + 7])
+- abort ();
+- }
+-
+- /* Hybrid SLP with unrolling by 2. */
+- for (i = 0; i < N; i++)
+- {
+- out[i*6] = in[i*6];
+- out[i*6 + 1] = in[i*6 + 1];
+- out[i*6 + 2] = in[i*6 + 2];
+- out[i*6 + 3] = in[i*6 + 3];
+- out[i*6 + 4] = in[i*6 + 4];
+- out[i*6 + 5] = in[i*6 + 5];
+-
+- ia[i] = i;
+- }
+-
+- /* check results: */
+- for (i = 0; i < N/2; i++)
+- {
+- if (out[i*6] != in[i*6]
+- || out[i*6 + 1] != in[i*6 + 1]
+- || out[i*6 + 2] != in[i*6 + 2]
+- || out[i*6 + 3] != in[i*6 + 3]
+- || out[i*6 + 4] != in[i*6 + 4]
+- || out[i*6 + 5] != in[i*6 + 5]
+- || ia[i] != i)
+- abort ();
+- }
+-
+-
+- return 0;
+-}
+-
+-int main (void)
+-{
+- check_vect ();
+-
+- main1 ();
+-
+- return 0;
+-}
+-
+-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target vect_strided_wide } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { vect_strided_wide } } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" { target vect_strided_wide } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target { ! { vect_strided_wide } } } } } */
+-/* { dg-final { cleanup-tree-dump "vect" } } */
+-
+
+=== added file 'gcc/testsuite/gcc.dg/vect/slp-19a.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-19a.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-19a.c 2011-05-05 15:46:10 +0000
+@@ -0,0 +1,61 @@
++/* { dg-require-effective-target vect_int } */
++
++#include <stdarg.h>
++#include "tree-vect.h"
++
++#define N 16
++
++int
++main1 ()
++{
++ unsigned int i;
++ unsigned int out[N*8];
++ unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
++ unsigned int ia[N*2];
++
++ for (i = 0; i < N; i++)
++ {
++ out[i*8] = in[i*8];
++ out[i*8 + 1] = in[i*8 + 1];
++ out[i*8 + 2] = in[i*8 + 2];
++ out[i*8 + 3] = in[i*8 + 3];
++ out[i*8 + 4] = in[i*8 + 4];
++ out[i*8 + 5] = in[i*8 + 5];
++ out[i*8 + 6] = in[i*8 + 6];
++ out[i*8 + 7] = in[i*8 + 7];
++
++ ia[i] = in[i*8 + 2];
++ }
++
++ /* check results: */
++ for (i = 0; i < N; i++)
++ {
++ if (out[i*8] != in[i*8]
++ || out[i*8 + 1] != in[i*8 + 1]
++ || out[i*8 + 2] != in[i*8 + 2]
++ || out[i*8 + 3] != in[i*8 + 3]
++ || out[i*8 + 4] != in[i*8 + 4]
++ || out[i*8 + 5] != in[i*8 + 5]
++ || out[i*8 + 6] != in[i*8 + 6]
++ || out[i*8 + 7] != in[i*8 + 7]
++ || ia[i] != in[i*8 + 2])
++ abort ();
++ }
++
++ return 0;
++}
++
++int main (void)
++{
++ check_vect ();
++
++ main1 ();
++
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! vect_strided8 } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_strided8 } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! vect_strided8} } } } */
++/* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== added file 'gcc/testsuite/gcc.dg/vect/slp-19b.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-19b.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-19b.c 2011-05-05 15:46:10 +0000
+@@ -0,0 +1,58 @@
++/* { dg-require-effective-target vect_int } */
++
++#include <stdarg.h>
++#include "tree-vect.h"
++
++#define N 16
++
++int
++main1 ()
++{
++ unsigned int i;
++ unsigned int out[N*8];
++ unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
++ unsigned int ia[N*2], a0, a1, a2, a3;
++
++ for (i = 0; i < N*2; i++)
++ {
++ a0 = in[i*4] + 1;
++ a1 = in[i*4 + 1] + 2;
++ a2 = in[i*4 + 2] + 3;
++ a3 = in[i*4 + 3] + 4;
++
++ out[i*4] = a0;
++ out[i*4 + 1] = a1;
++ out[i*4 + 2] = a2;
++ out[i*4 + 3] = a3;
++
++ ia[i] = a2;
++ }
++
++ /* check results: */
++ for (i = 0; i < N*2; i++)
++ {
++ if (out[i*4] != in[i*4] + 1
++ || out[i*4 + 1] != in[i*4 + 1] + 2
++ || out[i*4 + 2] != in[i*4 + 2] + 3
++ || out[i*4 + 3] != in[i*4 + 3] + 4
++ || ia[i] != in[i*4 + 2] + 3)
++ abort ();
++ }
++
++ return 0;
++}
++
++int main (void)
++{
++ check_vect ();
++
++ main1 ();
++
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided4 } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! vect_strided4 } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { target vect_strided4 } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! vect_strided4 } } } } */
++/* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== added file 'gcc/testsuite/gcc.dg/vect/slp-19c.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-19c.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-19c.c 2011-05-05 15:44:41 +0000
+@@ -0,0 +1,95 @@
++/* { dg-require-effective-target vect_int } */
++
++#include <stdarg.h>
++#include "tree-vect.h"
++
++#define N 16
++
++int
++main1 ()
++{
++ unsigned int i;
++ unsigned int out[N*8];
++ unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
++ unsigned int ia[N*2], a0, a1, a2, a3;
++
++ /* The last stmt requires interleaving of not power of 2 size - not
++ vectorizable. */
++ for (i = 0; i < N/2; i++)
++ {
++ out[i*12] = in[i*12];
++ out[i*12 + 1] = in[i*12 + 1];
++ out[i*12 + 2] = in[i*12 + 2];
++ out[i*12 + 3] = in[i*12 + 3];
++ out[i*12 + 4] = in[i*12 + 4];
++ out[i*12 + 5] = in[i*12 + 5];
++ out[i*12 + 6] = in[i*12 + 6];
++ out[i*12 + 7] = in[i*12 + 7];
++ out[i*12 + 8] = in[i*12 + 8];
++ out[i*12 + 9] = in[i*12 + 9];
++ out[i*12 + 10] = in[i*12 + 10];
++ out[i*12 + 11] = in[i*12 + 11];
++
++ ia[i] = in[i*12 + 7];
++ }
++
++ /* check results: */
++ for (i = 0; i < N/2; i++)
++ {
++ if (out[i*12] != in[i*12]
++ || out[i*12 + 1] != in[i*12 + 1]
++ || out[i*12 + 2] != in[i*12 + 2]
++ || out[i*12 + 3] != in[i*12 + 3]
++ || out[i*12 + 4] != in[i*12 + 4]
++ || out[i*12 + 5] != in[i*12 + 5]
++ || out[i*12 + 6] != in[i*12 + 6]
++ || out[i*12 + 7] != in[i*12 + 7]
++ || out[i*12 + 8] != in[i*12 + 8]
++ || out[i*12 + 9] != in[i*12 + 9]
++ || out[i*12 + 10] != in[i*12 + 10]
++ || out[i*12 + 11] != in[i*12 + 11]
++ || ia[i] != in[i*12 + 7])
++ abort ();
++ }
++
++ /* Hybrid SLP with unrolling by 2. */
++ for (i = 0; i < N; i++)
++ {
++ out[i*6] = in[i*6];
++ out[i*6 + 1] = in[i*6 + 1];
++ out[i*6 + 2] = in[i*6 + 2];
++ out[i*6 + 3] = in[i*6 + 3];
++ out[i*6 + 4] = in[i*6 + 4];
++ out[i*6 + 5] = in[i*6 + 5];
++
++ ia[i] = i;
++ }
++
++ /* check results: */
++ for (i = 0; i < N/2; i++)
++ {
++ if (out[i*6] != in[i*6]
++ || out[i*6 + 1] != in[i*6 + 1]
++ || out[i*6 + 2] != in[i*6 + 2]
++ || out[i*6 + 3] != in[i*6 + 3]
++ || out[i*6 + 4] != in[i*6 + 4]
++ || out[i*6 + 5] != in[i*6 + 5]
++ || ia[i] != i)
++ abort ();
++ }
++
++ return 0;
++}
++
++int main (void)
++{
++ check_vect ();
++
++ main1 ();
++
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" } } */
++/* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/slp-21.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-21.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-21.c 2011-05-05 15:46:10 +0000
+@@ -199,9 +199,9 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target { vect_strided || vect_extract_even_odd } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { vect_strided || vect_extract_even_odd } } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_strided } } } */
+-/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! { vect_strided } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target { vect_strided4 || vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { vect_strided4 || vect_extract_even_odd } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_strided4 } } } */
++/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" { target { ! { vect_strided4 } } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/slp-23.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-23.c 2011-01-10 12:51:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-23.c 2011-05-05 15:46:10 +0000
+@@ -106,8 +106,8 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target { vect_strided_wide } && {! { vect_no_align} } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { vect_strided_wide || vect_no_align} } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target { vect_strided8 && { ! { vect_no_align} } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! { vect_strided8 || vect_no_align } } } } } */
+ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/slp-reduc-6.c'
+--- old/gcc/testsuite/gcc.dg/vect/slp-reduc-6.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/slp-reduc-6.c 2011-05-05 15:46:10 +0000
+@@ -42,7 +42,7 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail { vect_no_int_add || { ! vect_unpack } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail { vect_no_int_add || { ! { vect_unpack || vect_strided2 } } } } } } */
+ /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect" } } */
+ /* { dg-final { scan-tree-dump-times "different interleaving chains in one node" 1 "vect" { target { ! vect_no_int_add } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-1.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-1.c 2010-08-19 10:23:50 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-1.c 2011-05-05 15:46:10 +0000
+@@ -85,6 +85,6 @@
+ fbar (a);
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 6 loops" 1 "vect" { target vect_extract_even_odd_wide } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 5 loops" 1 "vect" { xfail vect_extract_even_odd_wide } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 6 loops" 1 "vect" { target vect_strided2 } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 5 loops" 1 "vect" { xfail vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-10.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-10.c 2010-05-27 12:23:45 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-10.c 2011-05-05 15:46:10 +0000
+@@ -22,5 +22,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { ! vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { ! vect_strided2 } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-107.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-107.c 2008-08-19 08:06:54 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-107.c 2011-05-05 15:46:10 +0000
+@@ -40,6 +40,6 @@
+ return main1 ();
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_extract_even_odd_wide } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail vect_extract_even_odd_wide } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-98.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-98.c 2008-08-02 11:05:47 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-98.c 2011-05-05 15:46:10 +0000
+@@ -38,6 +38,6 @@
+ }
+
+ /* Needs interleaving support. */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd_wide } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { xfail { vect_interleave && vect_extract_even_odd_wide } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided4 } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { xfail vect_strided4 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-cselim-1.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-cselim-1.c 2011-03-27 09:38:18 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-cselim-1.c 2011-05-05 15:46:10 +0000
+@@ -82,5 +82,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align || {! vect_strided } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { vect_no_align || { ! vect_strided2 } } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-a-mult.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-a-mult.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-a-mult.c 2011-05-05 15:46:10 +0000
+@@ -71,6 +71,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i2.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i2.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i2.c 2011-05-05 15:46:10 +0000
+@@ -55,6 +55,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i4.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i4.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i4.c 2011-05-05 15:46:10 +0000
+@@ -68,6 +68,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided4 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-mult.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-mult.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-mult.c 2011-05-05 15:46:10 +0000
+@@ -62,6 +62,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-a-u32-mult.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-a-u32-mult.c 2010-05-27 12:23:45 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-a-u32-mult.c 2011-05-05 15:46:10 +0000
+@@ -61,6 +61,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i2-gap.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i2-gap.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i2-gap.c 2011-05-05 15:46:10 +0000
+@@ -69,6 +69,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i8-gap2.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i8-gap2.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i8-gap2.c 2011-05-05 15:46:10 +0000
+@@ -76,6 +76,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i8-gap7.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i8-gap7.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-a-u8-i8-gap7.c 2011-05-05 15:46:10 +0000
+@@ -81,6 +81,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-float.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-float.c 2008-08-19 08:06:54 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-float.c 2011-05-05 15:46:10 +0000
+@@ -39,7 +39,7 @@
+ }
+
+ /* Needs interleaving support. */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd_wide } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail { vect_interleave && vect_extract_even_odd_wide } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-mult-char-ls.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-mult-char-ls.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-mult-char-ls.c 2011-05-05 15:46:10 +0000
+@@ -71,6 +71,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-mult.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-mult.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-mult.c 2011-05-05 15:46:10 +0000
+@@ -71,6 +71,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-same-dr.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-same-dr.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-same-dr.c 2011-05-05 15:46:10 +0000
+@@ -72,5 +72,5 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-store-a-u8-i2.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-store-a-u8-i2.c 2008-08-12 05:31:57 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-store-a-u8-i2.c 2011-05-05 15:46:10 +0000
+@@ -55,6 +55,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave || vect_strided2 } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-store-u16-i4.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-store-u16-i4.c 2007-10-21 09:01:16 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-store-u16-i4.c 2011-05-05 15:46:10 +0000
+@@ -65,8 +65,8 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target { vect_interleave && vect_pack_trunc } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { { ! { vect_interleave } } && { vect_pack_trunc } } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target { { vect_interleave || vect_strided4 } && vect_pack_trunc } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { { ! { vect_interleave || vect_strided4 } } && { vect_pack_trunc } } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-store-u32-i2.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-store-u32-i2.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-store-u32-i2.c 2011-05-05 15:46:10 +0000
+@@ -39,7 +39,7 @@
+ }
+
+ /* Needs interleaving support. */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail { vect_interleave } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave || vect_strided2 } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail { vect_interleave || vect_strided2 } } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u16-i2.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u16-i2.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u16-i2.c 2011-05-05 15:46:10 +0000
+@@ -55,6 +55,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== added file 'gcc/testsuite/gcc.dg/vect/vect-strided-u16-i3.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u16-i3.c 1970-01-01 00:00:00 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u16-i3.c 2011-05-05 15:46:25 +0000
+@@ -0,0 +1,112 @@
++#include <stdarg.h>
++#include "tree-vect.h"
++
++#define N 128
++
++typedef struct {
++ unsigned short a;
++ unsigned short b;
++ unsigned short c;
++} s;
++
++#define A(I) (I)
++#define B(I) ((I) * 2)
++#define C(I) ((unsigned short) ~((I) ^ 0x18))
++
++void __attribute__ ((noinline))
++check1 (s *res)
++{
++ int i;
++
++ for (i = 0; i < N; i++)
++ if (res[i].a != C (i)
++ || res[i].b != A (i)
++ || res[i].c != B (i))
++ abort ();
++}
++
++void __attribute__ ((noinline))
++check2 (unsigned short *res)
++{
++ int i;
++
++ for (i = 0; i < N; i++)
++ if (res[i] != (unsigned short) (A (i) + B (i) + C (i)))
++ abort ();
++}
++
++void __attribute__ ((noinline))
++check3 (s *res)
++{
++ int i;
++
++ for (i = 0; i < N; i++)
++ if (res[i].a != i
++ || res[i].b != i
++ || res[i].c != i)
++ abort ();
++}
++
++void __attribute__ ((noinline))
++check4 (unsigned short *res)
++{
++ int i;
++
++ for (i = 0; i < N; i++)
++ if (res[i] != (unsigned short) (A (i) + B (i)))
++ abort ();
++}
++
++void __attribute__ ((noinline))
++main1 (s *arr)
++{
++ int i;
++ s *ptr = arr;
++ s res1[N];
++ unsigned short res2[N];
++
++ for (i = 0; i < N; i++)
++ {
++ res1[i].a = arr[i].c;
++ res1[i].b = arr[i].a;
++ res1[i].c = arr[i].b;
++ }
++ check1 (res1);
++
++ for (i = 0; i < N; i++)
++ res2[i] = arr[i].a + arr[i].b + arr[i].c;
++ check2 (res2);
++
++ for (i = 0; i < N; i++)
++ {
++ res1[i].a = i;
++ res1[i].b = i;
++ res1[i].c = i;
++ }
++ check3 (res1);
++
++ for (i = 0; i < N; i++)
++ res2[i] = arr[i].a + arr[i].b;
++ check4 (res2);
++}
++
++int main (void)
++{
++ int i;
++ s arr[N];
++
++ check_vect ();
++
++ for (i = 0; i < N; i++)
++ {
++ arr[i].a = A (i);
++ arr[i].b = B (i);
++ arr[i].c = C (i);
++ }
++ main1 (arr);
++
++ return 0;
++}
++
++/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect" { target vect_strided3 } } } */
++/* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u16-i4.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u16-i4.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u16-i4.c 2011-05-05 15:46:10 +0000
+@@ -68,6 +68,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided4 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u32-i4.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u32-i4.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u32-i4.c 2011-05-05 15:46:10 +0000
+@@ -63,6 +63,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided4 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u32-i8.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u32-i8.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u32-i8.c 2011-05-05 15:46:10 +0000
+@@ -77,6 +77,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u32-mult.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u32-mult.c 2010-05-27 12:23:45 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u32-mult.c 2011-05-05 15:46:10 +0000
+@@ -60,6 +60,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u8-i2-gap.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i2-gap.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i2-gap.c 2011-05-05 15:46:10 +0000
+@@ -71,6 +71,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u8-i2.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i2.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i2.c 2011-05-05 15:46:10 +0000
+@@ -54,6 +54,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap2.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap2.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap2.c 2011-05-05 15:46:10 +0000
+@@ -78,6 +78,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap4.c 2011-05-05 15:46:10 +0000
+@@ -98,6 +98,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap7.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap7.c 2007-09-04 12:05:19 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8-gap7.c 2011-05-05 15:46:10 +0000
+@@ -83,6 +83,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8.c 2010-11-22 12:16:52 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-strided-u8-i8.c 2011-05-05 15:46:10 +0000
+@@ -85,6 +85,6 @@
+ return 0;
+ }
+
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided8 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect-vfa-03.c'
+--- old/gcc/testsuite/gcc.dg/vect/vect-vfa-03.c 2007-09-09 07:46:12 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect-vfa-03.c 2011-05-05 15:46:10 +0000
+@@ -53,6 +53,6 @@
+ }
+
+ /* Needs interleaving support. */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */
+-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { xfail { vect_interleave && vect_extract_even_odd } } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_strided2 } } } */
++/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { xfail vect_strided2 } } } */
+ /* { dg-final { cleanup-tree-dump "vect" } } */
+
+=== modified file 'gcc/testsuite/gcc.dg/vect/vect.exp'
+--- old/gcc/testsuite/gcc.dg/vect/vect.exp 2011-04-24 07:45:49 +0000
++++ new/gcc/testsuite/gcc.dg/vect/vect.exp 2011-05-05 15:43:31 +0000
+@@ -75,15 +75,20 @@
+ lappend VECT_SLP_CFLAGS "-fdump-tree-slp-details"
+
+ # Main loop.
+-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pr*.\[cS\]]] \
+- "" $DEFAULT_VECTCFLAGS
+-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[cS\]]] \
+- "" $DEFAULT_VECTCFLAGS
+-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/slp-*.\[cS\]]] \
+- "" $DEFAULT_VECTCFLAGS
+-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/bb-slp*.\[cS\]]] \
+- "" $VECT_SLP_CFLAGS
+-
++set VECT_ADDITIONAL_FLAGS [list ""]
++if { [check_effective_target_lto] } {
++ lappend VECT_ADDITIONAL_FLAGS "-flto"
++}
++foreach flags $VECT_ADDITIONAL_FLAGS {
++ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pr*.\[cS\]]] \
++ $flags $DEFAULT_VECTCFLAGS
++ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[cS\]]] \
++ $flags $DEFAULT_VECTCFLAGS
++ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/slp-*.\[cS\]]] \
++ $flags $DEFAULT_VECTCFLAGS
++ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/bb-slp*.\[cS\]]] \
++ $flags $VECT_SLP_CFLAGS
++}
+
+ #### Tests with special options
+ global SAVED_DEFAULT_VECTCFLAGS
+
+=== modified file 'gcc/testsuite/lib/target-supports.exp'
+--- old/gcc/testsuite/lib/target-supports.exp 2011-05-06 11:28:27 +0000
++++ new/gcc/testsuite/lib/target-supports.exp 2011-06-02 12:12:00 +0000
+@@ -3139,29 +3139,6 @@
+ return $et_vect_extract_even_odd_saved
+ }
+
+-# Return 1 if the target supports vector even/odd elements extraction of
+-# vectors with SImode elements or larger, 0 otherwise.
+-
+-proc check_effective_target_vect_extract_even_odd_wide { } {
+- global et_vect_extract_even_odd_wide_saved
+-
+- if [info exists et_vect_extract_even_odd_wide_saved] {
+- verbose "check_effective_target_vect_extract_even_odd_wide: using cached result" 2
+- } else {
+- set et_vect_extract_even_odd_wide_saved 0
+- if { [istarget powerpc*-*-*]
+- || [istarget i?86-*-*]
+- || [istarget x86_64-*-*]
+- || [istarget ia64-*-*]
+- || [istarget spu-*-*] } {
+- set et_vect_extract_even_odd_wide_saved 1
+- }
+- }
+-
+- verbose "check_effective_target_vect_extract_even_wide_odd: returning $et_vect_extract_even_odd_wide_saved" 2
+- return $et_vect_extract_even_odd_wide_saved
+-}
+-
+ # Return 1 if the target supports vector interleaving, 0 otherwise.
+
+ proc check_effective_target_vect_interleave { } {
+@@ -3184,41 +3161,30 @@
+ return $et_vect_interleave_saved
+ }
+
+-# Return 1 if the target supports vector interleaving and extract even/odd, 0 otherwise.
+-proc check_effective_target_vect_strided { } {
+- global et_vect_strided_saved
+-
+- if [info exists et_vect_strided_saved] {
+- verbose "check_effective_target_vect_strided: using cached result" 2
+- } else {
+- set et_vect_strided_saved 0
+- if { [check_effective_target_vect_interleave]
+- && [check_effective_target_vect_extract_even_odd] } {
+- set et_vect_strided_saved 1
+- }
+- }
+-
+- verbose "check_effective_target_vect_strided: returning $et_vect_strided_saved" 2
+- return $et_vect_strided_saved
+-}
+-
+-# Return 1 if the target supports vector interleaving and extract even/odd
+-# for wide element types, 0 otherwise.
+-proc check_effective_target_vect_strided_wide { } {
+- global et_vect_strided_wide_saved
+-
+- if [info exists et_vect_strided_wide_saved] {
+- verbose "check_effective_target_vect_strided_wide: using cached result" 2
+- } else {
+- set et_vect_strided_wide_saved 0
+- if { [check_effective_target_vect_interleave]
+- && [check_effective_target_vect_extract_even_odd_wide] } {
+- set et_vect_strided_wide_saved 1
+- }
+- }
+-
+- verbose "check_effective_target_vect_strided_wide: returning $et_vect_strided_wide_saved" 2
+- return $et_vect_strided_wide_saved
++foreach N {2 3 4 8} {
++ eval [string map [list N $N] {
++ # Return 1 if the target supports 2-vector interleaving
++ proc check_effective_target_vect_stridedN { } {
++ global et_vect_stridedN_saved
++
++ if [info exists et_vect_stridedN_saved] {
++ verbose "check_effective_target_vect_stridedN: using cached result" 2
++ } else {
++ set et_vect_stridedN_saved 0
++ if { (N & -N) == N
++ && [check_effective_target_vect_interleave]
++ && [check_effective_target_vect_extract_even_odd] } {
++ set et_vect_stridedN_saved 1
++ }
++ if { [istarget arm*-*-*] && N >= 2 && N <= 4 } {
++ set et_vect_stridedN_saved 1
++ }
++ }
++
++ verbose "check_effective_target_vect_stridedN: returning $et_vect_stridedN_saved" 2
++ return $et_vect_stridedN_saved
++ }
++ }]
+ }
+
+ # Return 1 if the target supports section-anchors
+
+=== modified file 'gcc/tree-cfg.c'
+--- old/gcc/tree-cfg.c 2011-02-12 21:11:33 +0000
++++ new/gcc/tree-cfg.c 2011-05-05 15:42:22 +0000
+@@ -3046,7 +3046,26 @@
+ tree fntype;
+ unsigned i;
+
+- if (TREE_CODE (fn) != OBJ_TYPE_REF
++ if (gimple_call_internal_p (stmt))
++ {
++ if (fn)
++ {
++ error ("gimple call has two targets");
++ debug_generic_stmt (fn);
++ return true;
++ }
++ }
++ else
++ {
++ if (!fn)
++ {
++ error ("gimple call has no target");
++ return true;
++ }
++ }
++
++ if (fn
++ && TREE_CODE (fn) != OBJ_TYPE_REF
+ && !is_gimple_val (fn))
+ {
+ error ("invalid function in gimple call");
+@@ -3054,9 +3073,10 @@
+ return true;
+ }
+
+- if (!POINTER_TYPE_P (TREE_TYPE (fn))
+- || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
+- && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE))
++ if (fn
++ && (!POINTER_TYPE_P (TREE_TYPE (fn))
++ || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
++ && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE)))
+ {
+ error ("non-function in gimple call");
+ return true;
+@@ -3076,8 +3096,12 @@
+ return true;
+ }
+
+- fntype = TREE_TYPE (TREE_TYPE (fn));
+- if (gimple_call_lhs (stmt)
++ if (fn)
++ fntype = TREE_TYPE (TREE_TYPE (fn));
++ else
++ fntype = NULL_TREE;
++ if (fntype
++ && gimple_call_lhs (stmt)
+ && !useless_type_conversion_p (TREE_TYPE (gimple_call_lhs (stmt)),
+ TREE_TYPE (fntype))
+ /* ??? At least C++ misses conversions at assignments from
+@@ -4130,9 +4154,10 @@
+ didn't see a function declaration before the call. */
+ if (is_gimple_call (stmt))
+ {
+- tree decl;
++ tree fn, decl;
+
+- if (!is_gimple_call_addr (gimple_call_fn (stmt)))
++ fn = gimple_call_fn (stmt);
++ if (fn && !is_gimple_call_addr (fn))
+ {
+ error ("invalid function in call statement");
+ return true;
+@@ -7484,6 +7509,8 @@
+ case GIMPLE_CALL:
+ if (gimple_call_lhs (g))
+ break;
++ if (gimple_call_internal_p (g))
++ break;
+
+ /* This is a naked call, as opposed to a GIMPLE_CALL with an
+ LHS. All calls whose value is ignored should be
+
+=== modified file 'gcc/tree-eh.c'
+--- old/gcc/tree-eh.c 2011-05-10 06:31:59 +0000
++++ new/gcc/tree-eh.c 2011-06-02 12:12:00 +0000
+@@ -2745,7 +2745,7 @@
+ || gimple_call_lhs (twos)
+ || gimple_call_chain (ones)
+ || gimple_call_chain (twos)
+- || !operand_equal_p (gimple_call_fn (ones), gimple_call_fn (twos), 0)
++ || !gimple_call_same_target_p (ones, twos)
+ || gimple_call_num_args (ones) != gimple_call_num_args (twos))
+ return false;
+
+
+=== modified file 'gcc/tree-inline.c'
+--- old/gcc/tree-inline.c 2011-05-05 21:02:06 +0000
++++ new/gcc/tree-inline.c 2011-06-02 12:12:00 +0000
+@@ -3471,10 +3471,13 @@
+ {
+ tree decl = gimple_call_fndecl (stmt);
+ tree addr = gimple_call_fn (stmt);
+- tree funtype = TREE_TYPE (addr);
++ tree funtype = NULL_TREE;
+ bool stdarg = false;
+
+- if (POINTER_TYPE_P (funtype))
++ if (addr)
++ funtype = TREE_TYPE (addr);
++
++ if (funtype && POINTER_TYPE_P (funtype))
+ funtype = TREE_TYPE (funtype);
+
+ /* Do not special case builtins where we see the body.
+@@ -3514,7 +3517,7 @@
+ if (decl)
+ funtype = TREE_TYPE (decl);
+
+- if (!VOID_TYPE_P (TREE_TYPE (funtype)))
++ if (funtype && !VOID_TYPE_P (TREE_TYPE (funtype)))
+ cost += estimate_move_cost (TREE_TYPE (funtype));
+
+ if (funtype)
+
+=== modified file 'gcc/tree-ssa-ccp.c'
+--- old/gcc/tree-ssa-ccp.c 2011-01-31 16:52:22 +0000
++++ new/gcc/tree-ssa-ccp.c 2011-05-05 15:42:22 +0000
+@@ -1279,7 +1279,10 @@
+
+ case GIMPLE_CALL:
+ {
+- tree fn = valueize_op (gimple_call_fn (stmt));
++ tree fn = gimple_call_fn (stmt);
++ if (!fn)
++ return NULL_TREE;
++ fn = valueize_op (fn);
+ if (TREE_CODE (fn) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+ && DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
+@@ -2310,6 +2313,11 @@
+ return true;
+ }
+
++ /* Internal calls provide no argument types, so the extra laxity
++ for normal calls does not apply. */
++ if (gimple_call_internal_p (stmt))
++ return false;
++
+ /* Propagate into the call arguments. Compared to replace_uses_in
+ this can use the argument slot types for type verification
+ instead of the current argument type. We also can safely
+
+=== modified file 'gcc/tree-ssa-dom.c'
+--- old/gcc/tree-ssa-dom.c 2011-02-14 17:59:10 +0000
++++ new/gcc/tree-ssa-dom.c 2011-05-05 15:42:22 +0000
+@@ -64,7 +64,7 @@
+ struct { enum tree_code op; tree opnd; } unary;
+ struct { enum tree_code op; tree opnd0, opnd1; } binary;
+ struct { enum tree_code op; tree opnd0, opnd1, opnd2; } ternary;
+- struct { tree fn; bool pure; size_t nargs; tree *args; } call;
++ struct { gimple fn_from; bool pure; size_t nargs; tree *args; } call;
+ } ops;
+ };
+
+@@ -258,7 +258,7 @@
+
+ expr->type = TREE_TYPE (gimple_call_lhs (stmt));
+ expr->kind = EXPR_CALL;
+- expr->ops.call.fn = gimple_call_fn (stmt);
++ expr->ops.call.fn_from = stmt;
+
+ if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
+ expr->ops.call.pure = true;
+@@ -422,8 +422,8 @@
+
+ /* If the calls are to different functions, then they
+ clearly cannot be equal. */
+- if (! operand_equal_p (expr0->ops.call.fn,
+- expr1->ops.call.fn, 0))
++ if (!gimple_call_same_target_p (expr0->ops.call.fn_from,
++ expr1->ops.call.fn_from))
+ return false;
+
+ if (! expr0->ops.call.pure)
+@@ -503,9 +503,15 @@
+ {
+ size_t i;
+ enum tree_code code = CALL_EXPR;
++ gimple fn_from;
+
+ val = iterative_hash_object (code, val);
+- val = iterative_hash_expr (expr->ops.call.fn, val);
++ fn_from = expr->ops.call.fn_from;
++ if (gimple_call_internal_p (fn_from))
++ val = iterative_hash_hashval_t
++ ((hashval_t) gimple_call_internal_fn (fn_from), val);
++ else
++ val = iterative_hash_expr (gimple_call_fn (fn_from), val);
+ for (i = 0; i < expr->ops.call.nargs; i++)
+ val = iterative_hash_expr (expr->ops.call.args[i], val);
+ }
+@@ -565,8 +571,14 @@
+ {
+ size_t i;
+ size_t nargs = element->expr.ops.call.nargs;
++ gimple fn_from;
+
+- print_generic_expr (stream, element->expr.ops.call.fn, 0);
++ fn_from = element->expr.ops.call.fn_from;
++ if (gimple_call_internal_p (fn_from))
++ fputs (internal_fn_name (gimple_call_internal_fn (fn_from)),
++ stream);
++ else
++ print_generic_expr (stream, gimple_call_fn (fn_from), 0);
+ fprintf (stream, " (");
+ for (i = 0; i < nargs; i++)
+ {
+
+=== modified file 'gcc/tree-ssa-pre.c'
+--- old/gcc/tree-ssa-pre.c 2011-02-15 13:04:47 +0000
++++ new/gcc/tree-ssa-pre.c 2011-05-05 15:42:22 +0000
+@@ -2657,11 +2657,13 @@
+ }
+
+ /* Return true if we can value number the call in STMT. This is true
+- if we have a pure or constant call. */
++ if we have a pure or constant call to a real function. */
+
+ static bool
+ can_value_number_call (gimple stmt)
+ {
++ if (gimple_call_internal_p (stmt))
++ return false;
+ if (gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
+ return true;
+ return false;
+@@ -4187,6 +4189,7 @@
+ gimple_stmt_iterator gsi;
+ gimple stmt;
+ unsigned i;
++ tree fn;
+
+ FOR_EACH_BB (b)
+ {
+@@ -4378,9 +4381,10 @@
+ /* Visit indirect calls and turn them into direct calls if
+ possible. */
+ if (is_gimple_call (stmt)
+- && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME)
++ && (fn = gimple_call_fn (stmt))
++ && TREE_CODE (fn) == SSA_NAME)
+ {
+- tree fn = VN_INFO (gimple_call_fn (stmt))->valnum;
++ fn = VN_INFO (fn)->valnum;
+ if (TREE_CODE (fn) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
+ {
+
+=== modified file 'gcc/tree-ssa-sccvn.c'
+--- old/gcc/tree-ssa-sccvn.c 2011-05-12 14:08:00 +0000
++++ new/gcc/tree-ssa-sccvn.c 2011-06-02 12:12:00 +0000
+@@ -2982,7 +2982,8 @@
+ /* ??? We should handle stores from calls. */
+ else if (TREE_CODE (lhs) == SSA_NAME)
+ {
+- if (gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
++ if (!gimple_call_internal_p (stmt)
++ && gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
+ changed = visit_reference_op_call (lhs, stmt);
+ else
+ changed = defs_to_varying (stmt);
+
+=== modified file 'gcc/tree-ssa-structalias.c'
+--- old/gcc/tree-ssa-structalias.c 2011-02-10 15:29:52 +0000
++++ new/gcc/tree-ssa-structalias.c 2011-05-05 15:42:22 +0000
+@@ -4319,6 +4319,7 @@
+ /* Fallthru to general call handling. */;
+ }
+ if (!in_ipa_mode
++ || gimple_call_internal_p (t)
+ || (fndecl
+ && (!(fi = lookup_vi_for_tree (fndecl))
+ || !fi->is_fn_info)))
+
+=== modified file 'gcc/tree-vect-data-refs.c'
+--- old/gcc/tree-vect-data-refs.c 2011-05-06 11:28:27 +0000
++++ new/gcc/tree-vect-data-refs.c 2011-06-02 12:12:00 +0000
+@@ -43,6 +43,45 @@
+ #include "expr.h"
+ #include "optabs.h"
+
++/* Return true if load- or store-lanes optab OPTAB is implemented for
++ COUNT vectors of type VECTYPE. NAME is the name of OPTAB. */
++
++static bool
++vect_lanes_optab_supported_p (const char *name, convert_optab optab,
++ tree vectype, unsigned HOST_WIDE_INT count)
++{
++ enum machine_mode mode, array_mode;
++ bool limit_p;
++
++ mode = TYPE_MODE (vectype);
++ limit_p = !targetm.array_mode_supported_p (mode, count);
++ array_mode = mode_for_size (count * GET_MODE_BITSIZE (mode),
++ MODE_INT, limit_p);
++
++ if (array_mode == BLKmode)
++ {
++ if (vect_print_dump_info (REPORT_DETAILS))
++ fprintf (vect_dump, "no array mode for %s[" HOST_WIDE_INT_PRINT_DEC "]",
++ GET_MODE_NAME (mode), count);
++ return false;
++ }
++
++ if (convert_optab_handler (optab, array_mode, mode) == CODE_FOR_nothing)
++ {
++ if (vect_print_dump_info (REPORT_DETAILS))
++ fprintf (vect_dump, "cannot use %s<%s><%s>",
++ name, GET_MODE_NAME (array_mode), GET_MODE_NAME (mode));
++ return false;
++ }
++
++ if (vect_print_dump_info (REPORT_DETAILS))
++ fprintf (vect_dump, "can use %s<%s><%s>",
++ name, GET_MODE_NAME (array_mode), GET_MODE_NAME (mode));
++
++ return true;
++}
++
++
+ /* Return the smallest scalar part of STMT.
+ This is used to determine the vectype of the stmt. We generally set the
+ vectype according to the type of the result (lhs). For stmts whose
+@@ -2196,19 +2235,6 @@
+ return false;
+ }
+
+- /* FORNOW: we handle only interleaving that is a power of 2.
+- We don't fail here if it may be still possible to vectorize the
+- group using SLP. If not, the size of the group will be checked in
+- vect_analyze_operations, and the vectorization will fail. */
+- if (exact_log2 (stride) == -1)
+- {
+- if (vect_print_dump_info (REPORT_DETAILS))
+- fprintf (vect_dump, "interleaving is not a power of 2");
+-
+- if (slp_impossible)
+- return false;
+- }
+-
+ if (stride == 0)
+ stride = count;
+
+@@ -2911,31 +2937,33 @@
+
+ /* Function vect_create_data_ref_ptr.
+
+- Create a new pointer to vector type (vp), that points to the first location
+- accessed in the loop by STMT, along with the def-use update chain to
+- appropriately advance the pointer through the loop iterations. Also set
+- aliasing information for the pointer. This vector pointer is used by the
+- callers to this function to create a memory reference expression for vector
+- load/store access.
++ Create a new pointer-to-AGGR_TYPE variable (ap), that points to the first
++ location accessed in the loop by STMT, along with the def-use update
++ chain to appropriately advance the pointer through the loop iterations.
++ Also set aliasing information for the pointer. This pointer is used by
++ the callers to this function to create a memory reference expression for
++ vector load/store access.
+
+ Input:
+ 1. STMT: a stmt that references memory. Expected to be of the form
+ GIMPLE_ASSIGN <name, data-ref> or
+ GIMPLE_ASSIGN <data-ref, name>.
+- 2. AT_LOOP: the loop where the vector memref is to be created.
+- 3. OFFSET (optional): an offset to be added to the initial address accessed
++ 2. AGGR_TYPE: the type of the reference, which should be either a vector
++ or an array.
++ 3. AT_LOOP: the loop where the vector memref is to be created.
++ 4. OFFSET (optional): an offset to be added to the initial address accessed
+ by the data-ref in STMT.
+- 4. ONLY_INIT: indicate if vp is to be updated in the loop, or remain
++ 5. ONLY_INIT: indicate if vp is to be updated in the loop, or remain
+ pointing to the initial address.
+- 5. TYPE: if not NULL indicates the required type of the data-ref.
++ 6. TYPE: if not NULL indicates the required type of the data-ref.
+
+ Output:
+ 1. Declare a new ptr to vector_type, and have it point to the base of the
+ data reference (initial addressed accessed by the data reference).
+ For example, for vector of type V8HI, the following code is generated:
+
+- v8hi *vp;
+- vp = (v8hi *)initial_address;
++ v8hi *ap;
++ ap = (v8hi *)initial_address;
+
+ if OFFSET is not supplied:
+ initial_address = &a[init];
+@@ -2955,7 +2983,7 @@
+ 4. Return the pointer. */
+
+ tree
+-vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
++vect_create_data_ref_ptr (gimple stmt, tree aggr_type, struct loop *at_loop,
+ tree offset, tree *initial_address, gimple *ptr_incr,
+ bool only_init, bool *inv_p)
+ {
+@@ -2965,17 +2993,16 @@
+ struct loop *loop = NULL;
+ bool nested_in_vect_loop = false;
+ struct loop *containing_loop = NULL;
+- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+- tree vect_ptr_type;
+- tree vect_ptr;
++ tree aggr_ptr_type;
++ tree aggr_ptr;
+ tree new_temp;
+ gimple vec_stmt;
+ gimple_seq new_stmt_list = NULL;
+ edge pe = NULL;
+ basic_block new_bb;
+- tree vect_ptr_init;
++ tree aggr_ptr_init;
+ struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+- tree vptr;
++ tree aptr;
+ gimple_stmt_iterator incr_gsi;
+ bool insert_after;
+ bool negative;
+@@ -2986,6 +3013,9 @@
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ tree base;
+
++ gcc_assert (TREE_CODE (aggr_type) == ARRAY_TYPE
++ || TREE_CODE (aggr_type) == VECTOR_TYPE);
++
+ if (loop_vinfo)
+ {
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
+@@ -3020,8 +3050,9 @@
+ if (vect_print_dump_info (REPORT_DETAILS))
+ {
+ tree data_ref_base = base_name;
+- fprintf (vect_dump, "create vector-pointer variable to type: ");
+- print_generic_expr (vect_dump, vectype, TDF_SLIM);
++ fprintf (vect_dump, "create %s-pointer variable to type: ",
++ tree_code_name[(int) TREE_CODE (aggr_type)]);
++ print_generic_expr (vect_dump, aggr_type, TDF_SLIM);
+ if (TREE_CODE (data_ref_base) == VAR_DECL
+ || TREE_CODE (data_ref_base) == ARRAY_REF)
+ fprintf (vect_dump, " vectorizing an array ref: ");
+@@ -3032,27 +3063,28 @@
+ print_generic_expr (vect_dump, base_name, TDF_SLIM);
+ }
+
+- /* (1) Create the new vector-pointer variable. */
+- vect_ptr_type = build_pointer_type (vectype);
++ /* (1) Create the new aggregate-pointer variable. */
++ aggr_ptr_type = build_pointer_type (aggr_type);
+ base = get_base_address (DR_REF (dr));
+ if (base
+ && TREE_CODE (base) == MEM_REF)
+- vect_ptr_type
+- = build_qualified_type (vect_ptr_type,
++ aggr_ptr_type
++ = build_qualified_type (aggr_ptr_type,
+ TYPE_QUALS (TREE_TYPE (TREE_OPERAND (base, 0))));
+- vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
++ aggr_ptr = vect_get_new_vect_var (aggr_ptr_type, vect_pointer_var,
+ get_name (base_name));
+
+- /* Vector types inherit the alias set of their component type by default so
+- we need to use a ref-all pointer if the data reference does not conflict
+- with the created vector data reference because it is not addressable. */
+- if (!alias_sets_conflict_p (get_deref_alias_set (vect_ptr),
++ /* Vector and array types inherit the alias set of their component
++ type by default so we need to use a ref-all pointer if the data
++ reference does not conflict with the created aggregated data
++ reference because it is not addressable. */
++ if (!alias_sets_conflict_p (get_deref_alias_set (aggr_ptr),
+ get_alias_set (DR_REF (dr))))
+ {
+- vect_ptr_type
+- = build_pointer_type_for_mode (vectype,
+- TYPE_MODE (vect_ptr_type), true);
+- vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
++ aggr_ptr_type
++ = build_pointer_type_for_mode (aggr_type,
++ TYPE_MODE (aggr_ptr_type), true);
++ aggr_ptr = vect_get_new_vect_var (aggr_ptr_type, vect_pointer_var,
+ get_name (base_name));
+ }
+
+@@ -3063,14 +3095,14 @@
+ do
+ {
+ tree lhs = gimple_assign_lhs (orig_stmt);
+- if (!alias_sets_conflict_p (get_deref_alias_set (vect_ptr),
++ if (!alias_sets_conflict_p (get_deref_alias_set (aggr_ptr),
+ get_alias_set (lhs)))
+ {
+- vect_ptr_type
+- = build_pointer_type_for_mode (vectype,
+- TYPE_MODE (vect_ptr_type), true);
+- vect_ptr
+- = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
++ aggr_ptr_type
++ = build_pointer_type_for_mode (aggr_type,
++ TYPE_MODE (aggr_ptr_type), true);
++ aggr_ptr
++ = vect_get_new_vect_var (aggr_ptr_type, vect_pointer_var,
+ get_name (base_name));
+ break;
+ }
+@@ -3080,7 +3112,7 @@
+ while (orig_stmt);
+ }
+
+- add_referenced_var (vect_ptr);
++ add_referenced_var (aggr_ptr);
+
+ /* Note: If the dataref is in an inner-loop nested in LOOP, and we are
+ vectorizing LOOP (i.e., outer-loop vectorization), we need to create two
+@@ -3113,8 +3145,8 @@
+ vp2 = vp1 + step
+ if () goto LOOP */
+
+- /* (2) Calculate the initial address the vector-pointer, and set
+- the vector-pointer to point to it before the loop. */
++ /* (2) Calculate the initial address of the aggregate-pointer, and set
++ the aggregate-pointer to point to it before the loop. */
+
+ /* Create: (&(base[init_val+offset]) in the loop preheader. */
+
+@@ -3133,17 +3165,17 @@
+
+ *initial_address = new_temp;
+
+- /* Create: p = (vectype *) initial_base */
++ /* Create: p = (aggr_type *) initial_base */
+ if (TREE_CODE (new_temp) != SSA_NAME
+- || !useless_type_conversion_p (vect_ptr_type, TREE_TYPE (new_temp)))
++ || !useless_type_conversion_p (aggr_ptr_type, TREE_TYPE (new_temp)))
+ {
+- vec_stmt = gimple_build_assign (vect_ptr,
+- fold_convert (vect_ptr_type, new_temp));
+- vect_ptr_init = make_ssa_name (vect_ptr, vec_stmt);
++ vec_stmt = gimple_build_assign (aggr_ptr,
++ fold_convert (aggr_ptr_type, new_temp));
++ aggr_ptr_init = make_ssa_name (aggr_ptr, vec_stmt);
+ /* Copy the points-to information if it exists. */
+ if (DR_PTR_INFO (dr))
+- duplicate_ssa_name_ptr_info (vect_ptr_init, DR_PTR_INFO (dr));
+- gimple_assign_set_lhs (vec_stmt, vect_ptr_init);
++ duplicate_ssa_name_ptr_info (aggr_ptr_init, DR_PTR_INFO (dr));
++ gimple_assign_set_lhs (vec_stmt, aggr_ptr_init);
+ if (pe)
+ {
+ new_bb = gsi_insert_on_edge_immediate (pe, vec_stmt);
+@@ -3153,19 +3185,19 @@
+ gsi_insert_before (&gsi, vec_stmt, GSI_SAME_STMT);
+ }
+ else
+- vect_ptr_init = new_temp;
++ aggr_ptr_init = new_temp;
+
+- /* (3) Handle the updating of the vector-pointer inside the loop.
++ /* (3) Handle the updating of the aggregate-pointer inside the loop.
+ This is needed when ONLY_INIT is false, and also when AT_LOOP is the
+ inner-loop nested in LOOP (during outer-loop vectorization). */
+
+ /* No update in loop is required. */
+ if (only_init && (!loop_vinfo || at_loop == loop))
+- vptr = vect_ptr_init;
++ aptr = aggr_ptr_init;
+ else
+ {
+- /* The step of the vector pointer is the Vector Size. */
+- tree step = TYPE_SIZE_UNIT (vectype);
++ /* The step of the aggregate pointer is the type size. */
++ tree step = TYPE_SIZE_UNIT (aggr_type);
+ /* One exception to the above is when the scalar step of the load in
+ LOOP is zero. In this case the step here is also zero. */
+ if (*inv_p)
+@@ -3175,9 +3207,9 @@
+
+ standard_iv_increment_position (loop, &incr_gsi, &insert_after);
+
+- create_iv (vect_ptr_init,
+- fold_convert (vect_ptr_type, step),
+- vect_ptr, loop, &incr_gsi, insert_after,
++ create_iv (aggr_ptr_init,
++ fold_convert (aggr_ptr_type, step),
++ aggr_ptr, loop, &incr_gsi, insert_after,
+ &indx_before_incr, &indx_after_incr);
+ incr = gsi_stmt (incr_gsi);
+ set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo, NULL));
+@@ -3191,14 +3223,14 @@
+ if (ptr_incr)
+ *ptr_incr = incr;
+
+- vptr = indx_before_incr;
++ aptr = indx_before_incr;
+ }
+
+ if (!nested_in_vect_loop || only_init)
+- return vptr;
+-
+-
+- /* (4) Handle the updating of the vector-pointer inside the inner-loop
++ return aptr;
++
++
++ /* (4) Handle the updating of the aggregate-pointer inside the inner-loop
+ nested in LOOP, if exists. */
+
+ gcc_assert (nested_in_vect_loop);
+@@ -3206,7 +3238,7 @@
+ {
+ standard_iv_increment_position (containing_loop, &incr_gsi,
+ &insert_after);
+- create_iv (vptr, fold_convert (vect_ptr_type, DR_STEP (dr)), vect_ptr,
++ create_iv (aptr, fold_convert (aggr_ptr_type, DR_STEP (dr)), aggr_ptr,
+ containing_loop, &incr_gsi, insert_after, &indx_before_incr,
+ &indx_after_incr);
+ incr = gsi_stmt (incr_gsi);
+@@ -3343,13 +3375,22 @@
+ and FALSE otherwise. */
+
+ bool
+-vect_strided_store_supported (tree vectype)
++vect_strided_store_supported (tree vectype, unsigned HOST_WIDE_INT count)
+ {
+ optab interleave_high_optab, interleave_low_optab;
+ enum machine_mode mode;
+
+ mode = TYPE_MODE (vectype);
+
++ /* vect_permute_store_chain requires the group size to be a power of two. */
++ if (exact_log2 (count) == -1)
++ {
++ if (vect_print_dump_info (REPORT_DETAILS))
++ fprintf (vect_dump, "the size of the group of strided accesses"
++ " is not a power of 2");
++ return false;
++ }
++
+ /* Check that the operation is supported. */
+ interleave_high_optab = optab_for_tree_code (VEC_INTERLEAVE_HIGH_EXPR,
+ vectype, optab_default);
+@@ -3374,6 +3415,18 @@
+ }
+
+
++/* Return TRUE if vec_store_lanes is available for COUNT vectors of
++ type VECTYPE. */
++
++bool
++vect_store_lanes_supported (tree vectype, unsigned HOST_WIDE_INT count)
++{
++ return vect_lanes_optab_supported_p ("vec_store_lanes",
++ vec_store_lanes_optab,
++ vectype, count);
++}
++
++
+ /* Function vect_permute_store_chain.
+
+ Given a chain of interleaved stores in DR_CHAIN of LENGTH that must be
+@@ -3435,7 +3488,7 @@
+ I3: 4 12 20 28 5 13 21 30
+ I4: 6 14 22 30 7 15 23 31. */
+
+-bool
++void
+ vect_permute_store_chain (VEC(tree,heap) *dr_chain,
+ unsigned int length,
+ gimple stmt,
+@@ -3449,9 +3502,7 @@
+ unsigned int j;
+ enum tree_code high_code, low_code;
+
+- /* Check that the operation is supported. */
+- if (!vect_strided_store_supported (vectype))
+- return false;
++ gcc_assert (vect_strided_store_supported (vectype, length));
+
+ *result_chain = VEC_copy (tree, heap, dr_chain);
+
+@@ -3504,7 +3555,6 @@
+ }
+ dr_chain = VEC_copy (tree, heap, *result_chain);
+ }
+- return true;
+ }
+
+ /* Function vect_setup_realignment
+@@ -3674,8 +3724,9 @@
+
+ gcc_assert (!compute_in_loop);
+ vec_dest = vect_create_destination_var (scalar_dest, vectype);
+- ptr = vect_create_data_ref_ptr (stmt, loop_for_initial_load, NULL_TREE,
+- &init_addr, &inc, true, &inv_p);
++ ptr = vect_create_data_ref_ptr (stmt, vectype, loop_for_initial_load,
++ NULL_TREE, &init_addr, &inc,
++ true, &inv_p);
+ new_stmt = gimple_build_assign_with_ops
+ (BIT_AND_EXPR, NULL_TREE, ptr,
+ build_int_cst (TREE_TYPE (ptr),
+@@ -3780,13 +3831,22 @@
+ and FALSE otherwise. */
+
+ bool
+-vect_strided_load_supported (tree vectype)
++vect_strided_load_supported (tree vectype, unsigned HOST_WIDE_INT count)
+ {
+ optab perm_even_optab, perm_odd_optab;
+ enum machine_mode mode;
+
+ mode = TYPE_MODE (vectype);
+
++ /* vect_permute_load_chain requires the group size to be a power of two. */
++ if (exact_log2 (count) == -1)
++ {
++ if (vect_print_dump_info (REPORT_DETAILS))
++ fprintf (vect_dump, "the size of the group of strided accesses"
++ " is not a power of 2");
++ return false;
++ }
++
+ perm_even_optab = optab_for_tree_code (VEC_EXTRACT_EVEN_EXPR, vectype,
+ optab_default);
+ if (!perm_even_optab)
+@@ -3821,6 +3881,16 @@
+ return true;
+ }
+
++/* Return TRUE if vec_load_lanes is available for COUNT vectors of
++ type VECTYPE. */
++
++bool
++vect_load_lanes_supported (tree vectype, unsigned HOST_WIDE_INT count)
++{
++ return vect_lanes_optab_supported_p ("vec_load_lanes",
++ vec_load_lanes_optab,
++ vectype, count);
++}
+
+ /* Function vect_permute_load_chain.
+
+@@ -3898,7 +3968,7 @@
+ 3rd vec (E2): 2 6 10 14 18 22 26 30
+ 4th vec (E4): 3 7 11 15 19 23 27 31. */
+
+-bool
++static void
+ vect_permute_load_chain (VEC(tree,heap) *dr_chain,
+ unsigned int length,
+ gimple stmt,
+@@ -3911,9 +3981,7 @@
+ int i;
+ unsigned int j;
+
+- /* Check that the operation is supported. */
+- if (!vect_strided_load_supported (vectype))
+- return false;
++ gcc_assert (vect_strided_load_supported (vectype, length));
+
+ *result_chain = VEC_copy (tree, heap, dr_chain);
+ for (i = 0; i < exact_log2 (length); i++)
+@@ -3956,7 +4024,6 @@
+ }
+ dr_chain = VEC_copy (tree, heap, *result_chain);
+ }
+- return true;
+ }
+
+
+@@ -3967,24 +4034,32 @@
+ the scalar statements.
+ */
+
+-bool
++void
+ vect_transform_strided_load (gimple stmt, VEC(tree,heap) *dr_chain, int size,
+ gimple_stmt_iterator *gsi)
+ {
+- stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+- gimple first_stmt = DR_GROUP_FIRST_DR (stmt_info);
+- gimple next_stmt, new_stmt;
+ VEC(tree,heap) *result_chain = NULL;
+- unsigned int i, gap_count;
+- tree tmp_data_ref;
+
+ /* DR_CHAIN contains input data-refs that are a part of the interleaving.
+ RESULT_CHAIN is the output of vect_permute_load_chain, it contains permuted
+ vectors, that are ready for vector computation. */
+ result_chain = VEC_alloc (tree, heap, size);
+- /* Permute. */
+- if (!vect_permute_load_chain (dr_chain, size, stmt, gsi, &result_chain))
+- return false;
++ vect_permute_load_chain (dr_chain, size, stmt, gsi, &result_chain);
++ vect_record_strided_load_vectors (stmt, result_chain);
++ VEC_free (tree, heap, result_chain);
++}
++
++/* RESULT_CHAIN contains the output of a group of strided loads that were
++ generated as part of the vectorization of STMT. Assign the statement
++ for each vector to the associated scalar statement. */
++
++void
++vect_record_strided_load_vectors (gimple stmt, VEC(tree,heap) *result_chain)
++{
++ gimple first_stmt = DR_GROUP_FIRST_DR (vinfo_for_stmt (stmt));
++ gimple next_stmt, new_stmt;
++ unsigned int i, gap_count;
++ tree tmp_data_ref;
+
+ /* Put a permuted data-ref in the VECTORIZED_STMT field.
+ Since we scan the chain starting from it's first node, their order
+@@ -4046,9 +4121,6 @@
+ break;
+ }
+ }
+-
+- VEC_free (tree, heap, result_chain);
+- return true;
+ }
+
+ /* Function vect_force_dr_alignment_p.
+
+=== modified file 'gcc/tree-vect-slp.c'
+--- old/gcc/tree-vect-slp.c 2010-12-23 16:25:52 +0000
++++ new/gcc/tree-vect-slp.c 2011-05-05 15:43:06 +0000
+@@ -215,7 +215,8 @@
+ vect_model_simple_cost (stmt_info, ncopies_for_cost, dt, slp_node);
+ else
+ /* Store. */
+- vect_model_store_cost (stmt_info, ncopies_for_cost, dt[0], slp_node);
++ vect_model_store_cost (stmt_info, ncopies_for_cost, false,
++ dt[0], slp_node);
+ }
+
+ else
+@@ -579,7 +580,7 @@
+
+ /* Analyze costs (for the first stmt in the group). */
+ vect_model_load_cost (vinfo_for_stmt (stmt),
+- ncopies_for_cost, *node);
++ ncopies_for_cost, false, *node);
+ }
+
+ /* Store the place of this load in the interleaving chain. In
+
+=== modified file 'gcc/tree-vect-stmts.c'
+--- old/gcc/tree-vect-stmts.c 2011-04-18 07:38:11 +0000
++++ new/gcc/tree-vect-stmts.c 2011-06-02 12:12:00 +0000
+@@ -42,6 +42,82 @@
+ #include "langhooks.h"
+
+
++/* Return a variable of type ELEM_TYPE[NELEMS]. */
++
++static tree
++create_vector_array (tree elem_type, unsigned HOST_WIDE_INT nelems)
++{
++ return create_tmp_var (build_array_type_nelts (elem_type, nelems),
++ "vect_array");
++}
++
++/* ARRAY is an array of vectors created by create_vector_array.
++ Return an SSA_NAME for the vector in index N. The reference
++ is part of the vectorization of STMT and the vector is associated
++ with scalar destination SCALAR_DEST. */
++
++static tree
++read_vector_array (gimple stmt, gimple_stmt_iterator *gsi, tree scalar_dest,
++ tree array, unsigned HOST_WIDE_INT n)
++{
++ tree vect_type, vect, vect_name, array_ref;
++ gimple new_stmt;
++
++ gcc_assert (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE);
++ vect_type = TREE_TYPE (TREE_TYPE (array));
++ vect = vect_create_destination_var (scalar_dest, vect_type);
++ array_ref = build4 (ARRAY_REF, vect_type, array,
++ build_int_cst (size_type_node, n),
++ NULL_TREE, NULL_TREE);
++
++ new_stmt = gimple_build_assign (vect, array_ref);
++ vect_name = make_ssa_name (vect, new_stmt);
++ gimple_assign_set_lhs (new_stmt, vect_name);
++ vect_finish_stmt_generation (stmt, new_stmt, gsi);
++ mark_symbols_for_renaming (new_stmt);
++
++ return vect_name;
++}
++
++/* ARRAY is an array of vectors created by create_vector_array.
++ Emit code to store SSA_NAME VECT in index N of the array.
++ The store is part of the vectorization of STMT. */
++
++static void
++write_vector_array (gimple stmt, gimple_stmt_iterator *gsi, tree vect,
++ tree array, unsigned HOST_WIDE_INT n)
++{
++ tree array_ref;
++ gimple new_stmt;
++
++ array_ref = build4 (ARRAY_REF, TREE_TYPE (vect), array,
++ build_int_cst (size_type_node, n),
++ NULL_TREE, NULL_TREE);
++
++ new_stmt = gimple_build_assign (array_ref, vect);
++ vect_finish_stmt_generation (stmt, new_stmt, gsi);
++ mark_symbols_for_renaming (new_stmt);
++}
++
++/* PTR is a pointer to an array of type TYPE. Return a representation
++ of *PTR. The memory reference replaces those in FIRST_DR
++ (and its group). */
++
++static tree
++create_array_ref (tree type, tree ptr, struct data_reference *first_dr)
++{
++ struct ptr_info_def *pi;
++ tree mem_ref, alias_ptr_type;
++
++ alias_ptr_type = reference_alias_ptr_type (DR_REF (first_dr));
++ mem_ref = build2 (MEM_REF, type, ptr, build_int_cst (alias_ptr_type, 0));
++ /* Arrays have the same alignment as their type. */
++ pi = get_ptr_info (ptr);
++ pi->align = TYPE_ALIGN_UNIT (type);
++ pi->misalign = 0;
++ return mem_ref;
++}
++
+ /* Utility functions used by vect_mark_stmts_to_be_vectorized. */
+
+ /* Function vect_mark_relevant.
+@@ -648,7 +724,8 @@
+
+ void
+ vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
+- enum vect_def_type dt, slp_tree slp_node)
++ bool store_lanes_p, enum vect_def_type dt,
++ slp_tree slp_node)
+ {
+ int group_size;
+ unsigned int inside_cost = 0, outside_cost = 0;
+@@ -685,9 +762,11 @@
+ first_dr = STMT_VINFO_DATA_REF (stmt_info);
+ }
+
+- /* Is this an access in a group of stores, which provide strided access?
+- If so, add in the cost of the permutes. */
+- if (group_size > 1)
++ /* We assume that the cost of a single store-lanes instruction is
++ equivalent to the cost of GROUP_SIZE separate stores. If a strided
++ access is instead being provided by a permute-and-store operation,
++ include the cost of the permutes. */
++ if (!store_lanes_p && group_size > 1)
+ {
+ /* Uses a high and low interleave operation for each needed permute. */
+ inside_cost = ncopies * exact_log2(group_size) * group_size
+@@ -763,8 +842,8 @@
+ access scheme chosen. */
+
+ void
+-vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, slp_tree slp_node)
+-
++vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, bool load_lanes_p,
++ slp_tree slp_node)
+ {
+ int group_size;
+ gimple first_stmt;
+@@ -789,9 +868,11 @@
+ first_dr = dr;
+ }
+
+- /* Is this an access in a group of loads providing strided access?
+- If so, add in the cost of the permutes. */
+- if (group_size > 1)
++ /* We assume that the cost of a single load-lanes instruction is
++ equivalent to the cost of GROUP_SIZE separate loads. If a strided
++ access is instead being provided by a load-and-permute operation,
++ include the cost of the permutes. */
++ if (!load_lanes_p && group_size > 1)
+ {
+ /* Uses an even and odd extract operations for each needed permute. */
+ inside_cost = ncopies * exact_log2(group_size) * group_size
+@@ -3329,6 +3410,7 @@
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr = NULL;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
++ tree elem_type;
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ struct loop *loop = NULL;
+ enum machine_mode vec_mode;
+@@ -3344,6 +3426,7 @@
+ int j;
+ gimple next_stmt, first_stmt = NULL;
+ bool strided_store = false;
++ bool store_lanes_p = false;
+ unsigned int group_size, i;
+ VEC(tree,heap) *dr_chain = NULL, *oprnds = NULL, *result_chain = NULL;
+ bool inv_p;
+@@ -3351,6 +3434,7 @@
+ bool slp = (slp_node != NULL);
+ unsigned int vec_num;
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
++ tree aggr_type;
+
+ if (loop_vinfo)
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
+@@ -3404,7 +3488,8 @@
+
+ /* The scalar rhs type needs to be trivially convertible to the vector
+ component type. This should always be the case. */
+- if (!useless_type_conversion_p (TREE_TYPE (vectype), TREE_TYPE (op)))
++ elem_type = TREE_TYPE (vectype);
++ if (!useless_type_conversion_p (elem_type, TREE_TYPE (op)))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "??? operands of different types");
+@@ -3431,9 +3516,14 @@
+ {
+ strided_store = true;
+ first_stmt = DR_GROUP_FIRST_DR (stmt_info);
+- if (!vect_strided_store_supported (vectype)
+- && !PURE_SLP_STMT (stmt_info) && !slp)
+- return false;
++ if (!slp && !PURE_SLP_STMT (stmt_info))
++ {
++ group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
++ if (vect_store_lanes_supported (vectype, group_size))
++ store_lanes_p = true;
++ else if (!vect_strided_store_supported (vectype, group_size))
++ return false;
++ }
+
+ if (first_stmt == stmt)
+ {
+@@ -3459,7 +3549,7 @@
+ if (!vec_stmt) /* transformation not required. */
+ {
+ STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
+- vect_model_store_cost (stmt_info, ncopies, dt, NULL);
++ vect_model_store_cost (stmt_info, ncopies, store_lanes_p, dt, NULL);
+ return true;
+ }
+
+@@ -3514,6 +3604,16 @@
+
+ alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
+ gcc_assert (alignment_support_scheme);
++ /* Targets with store-lane instructions must not require explicit
++ realignment. */
++ gcc_assert (!store_lanes_p
++ || alignment_support_scheme == dr_aligned
++ || alignment_support_scheme == dr_unaligned_supported);
++
++ if (store_lanes_p)
++ aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
++ else
++ aggr_type = vectype;
+
+ /* In case the vectorization factor (VF) is bigger than the number
+ of elements that we can fit in a vectype (nunits), we have to generate
+@@ -3602,9 +3702,9 @@
+ /* We should have catched mismatched types earlier. */
+ gcc_assert (useless_type_conversion_p (vectype,
+ TREE_TYPE (vec_oprnd)));
+- dataref_ptr = vect_create_data_ref_ptr (first_stmt, NULL, NULL_TREE,
+- &dummy, &ptr_incr, false,
+- &inv_p);
++ dataref_ptr = vect_create_data_ref_ptr (first_stmt, aggr_type, NULL,
++ NULL_TREE, &dummy,
++ &ptr_incr, false, &inv_p);
+ gcc_assert (bb_vinfo || !inv_p);
+ }
+ else
+@@ -3625,76 +3725,101 @@
+ VEC_replace(tree, dr_chain, i, vec_oprnd);
+ VEC_replace(tree, oprnds, i, vec_oprnd);
+ }
+- dataref_ptr =
+- bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt, NULL_TREE);
+- }
+-
+- if (strided_store)
+- {
+- result_chain = VEC_alloc (tree, heap, group_size);
+- /* Permute. */
+- if (!vect_permute_store_chain (dr_chain, group_size, stmt, gsi,
+- &result_chain))
+- return false;
+- }
+-
+- next_stmt = first_stmt;
+- for (i = 0; i < vec_num; i++)
+- {
+- struct ptr_info_def *pi;
+-
+- if (i > 0)
+- /* Bump the vector pointer. */
+- dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
+- NULL_TREE);
+-
+- if (slp)
+- vec_oprnd = VEC_index (tree, vec_oprnds, i);
+- else if (strided_store)
+- /* For strided stores vectorized defs are interleaved in
+- vect_permute_store_chain(). */
+- vec_oprnd = VEC_index (tree, result_chain, i);
+-
+- data_ref = build2 (MEM_REF, TREE_TYPE (vec_oprnd), dataref_ptr,
+- build_int_cst (reference_alias_ptr_type
+- (DR_REF (first_dr)), 0));
+- pi = get_ptr_info (dataref_ptr);
+- pi->align = TYPE_ALIGN_UNIT (vectype);
+- if (aligned_access_p (first_dr))
+- pi->misalign = 0;
+- else if (DR_MISALIGNMENT (first_dr) == -1)
+- {
+- TREE_TYPE (data_ref)
+- = build_aligned_type (TREE_TYPE (data_ref),
+- TYPE_ALIGN (TREE_TYPE (vectype)));
+- pi->align = TYPE_ALIGN_UNIT (TREE_TYPE (vectype));
+- pi->misalign = 0;
+- }
+- else
+- {
+- TREE_TYPE (data_ref)
+- = build_aligned_type (TREE_TYPE (data_ref),
+- TYPE_ALIGN (TREE_TYPE (vectype)));
+- pi->misalign = DR_MISALIGNMENT (first_dr);
+- }
+-
+- /* Arguments are ready. Create the new vector stmt. */
+- new_stmt = gimple_build_assign (data_ref, vec_oprnd);
++ dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
++ TYPE_SIZE_UNIT (aggr_type));
++ }
++
++ if (store_lanes_p)
++ {
++ tree vec_array;
++
++ /* Combine all the vectors into an array. */
++ vec_array = create_vector_array (vectype, vec_num);
++ for (i = 0; i < vec_num; i++)
++ {
++ vec_oprnd = VEC_index (tree, dr_chain, i);
++ write_vector_array (stmt, gsi, vec_oprnd, vec_array, i);
++ }
++
++ /* Emit:
++ MEM_REF[...all elements...] = STORE_LANES (VEC_ARRAY). */
++ data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
++ new_stmt = gimple_build_call_internal (IFN_STORE_LANES, 1, vec_array);
++ gimple_call_set_lhs (new_stmt, data_ref);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ mark_symbols_for_renaming (new_stmt);
+-
+- if (slp)
+- continue;
+-
+- if (j == 0)
+- STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
++ }
++ else
++ {
++ new_stmt = NULL;
++ if (strided_store)
++ {
++ result_chain = VEC_alloc (tree, heap, group_size);
++ /* Permute. */
++ vect_permute_store_chain (dr_chain, group_size, stmt, gsi,
++ &result_chain);
++ }
++
++ next_stmt = first_stmt;
++ for (i = 0; i < vec_num; i++)
++ {
++ struct ptr_info_def *pi;
++
++ if (i > 0)
++ /* Bump the vector pointer. */
++ dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
++ stmt, NULL_TREE);
++
++ if (slp)
++ vec_oprnd = VEC_index (tree, vec_oprnds, i);
++ else if (strided_store)
++ /* For strided stores vectorized defs are interleaved in
++ vect_permute_store_chain(). */
++ vec_oprnd = VEC_index (tree, result_chain, i);
++
++ data_ref = build2 (MEM_REF, TREE_TYPE (vec_oprnd), dataref_ptr,
++ build_int_cst (reference_alias_ptr_type
++ (DR_REF (first_dr)), 0));
++ pi = get_ptr_info (dataref_ptr);
++ pi->align = TYPE_ALIGN_UNIT (vectype);
++ if (aligned_access_p (first_dr))
++ pi->misalign = 0;
++ else if (DR_MISALIGNMENT (first_dr) == -1)
++ {
++ TREE_TYPE (data_ref)
++ = build_aligned_type (TREE_TYPE (data_ref),
++ TYPE_ALIGN (elem_type));
++ pi->align = TYPE_ALIGN_UNIT (elem_type);
++ pi->misalign = 0;
++ }
++ else
++ {
++ TREE_TYPE (data_ref)
++ = build_aligned_type (TREE_TYPE (data_ref),
++ TYPE_ALIGN (elem_type));
++ pi->misalign = DR_MISALIGNMENT (first_dr);
++ }
++
++ /* Arguments are ready. Create the new vector stmt. */
++ new_stmt = gimple_build_assign (data_ref, vec_oprnd);
++ vect_finish_stmt_generation (stmt, new_stmt, gsi);
++ mark_symbols_for_renaming (new_stmt);
++
++ if (slp)
++ continue;
++
++ next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
++ if (!next_stmt)
++ break;
++ }
++ }
++ if (!slp)
++ {
++ if (j == 0)
++ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ else
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+-
+ prev_stmt_info = vinfo_for_stmt (new_stmt);
+- next_stmt = DR_GROUP_NEXT_DR (vinfo_for_stmt (next_stmt));
+- if (!next_stmt)
+- break;
+ }
+ }
+
+@@ -3805,6 +3930,7 @@
+ bool nested_in_vect_loop = false;
+ struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
++ tree elem_type;
+ tree new_temp;
+ enum machine_mode mode;
+ gimple new_stmt = NULL;
+@@ -3821,6 +3947,7 @@
+ gimple phi = NULL;
+ VEC(tree,heap) *dr_chain = NULL;
+ bool strided_load = false;
++ bool load_lanes_p = false;
+ gimple first_stmt;
+ tree scalar_type;
+ bool inv_p;
+@@ -3833,6 +3960,7 @@
+ enum tree_code code;
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ int vf;
++ tree aggr_type;
+
+ if (loop_vinfo)
+ {
+@@ -3909,7 +4037,8 @@
+
+ /* The vector component type needs to be trivially convertible to the
+ scalar lhs. This should always be the case. */
+- if (!useless_type_conversion_p (TREE_TYPE (scalar_dest), TREE_TYPE (vectype)))
++ elem_type = TREE_TYPE (vectype);
++ if (!useless_type_conversion_p (TREE_TYPE (scalar_dest), elem_type))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "??? operands of different types");
+@@ -3923,10 +4052,15 @@
+ /* FORNOW */
+ gcc_assert (! nested_in_vect_loop);
+
+- /* Check if interleaving is supported. */
+- if (!vect_strided_load_supported (vectype)
+- && !PURE_SLP_STMT (stmt_info) && !slp)
+- return false;
++ first_stmt = DR_GROUP_FIRST_DR (stmt_info);
++ if (!slp && !PURE_SLP_STMT (stmt_info))
++ {
++ group_size = DR_GROUP_SIZE (vinfo_for_stmt (first_stmt));
++ if (vect_load_lanes_supported (vectype, group_size))
++ load_lanes_p = true;
++ else if (!vect_strided_load_supported (vectype, group_size))
++ return false;
++ }
+ }
+
+ if (negative)
+@@ -3951,12 +4085,12 @@
+ if (!vec_stmt) /* transformation not required. */
+ {
+ STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
+- vect_model_load_cost (stmt_info, ncopies, NULL);
++ vect_model_load_cost (stmt_info, ncopies, load_lanes_p, NULL);
+ return true;
+ }
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+- fprintf (vect_dump, "transform load.");
++ fprintf (vect_dump, "transform load. ncopies = %d", ncopies);
+
+ /** Transform. **/
+
+@@ -3982,8 +4116,6 @@
+ }
+ else
+ vec_num = group_size;
+-
+- dr_chain = VEC_alloc (tree, heap, vec_num);
+ }
+ else
+ {
+@@ -3994,6 +4126,11 @@
+
+ alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
+ gcc_assert (alignment_support_scheme);
++ /* Targets with load-lane instructions must not require explicit
++ realignment. */
++ gcc_assert (!load_lanes_p
++ || alignment_support_scheme == dr_aligned
++ || alignment_support_scheme == dr_unaligned_supported);
+
+ /* In case the vectorization factor (VF) is bigger than the number
+ of elements that we can fit in a vectype (nunits), we have to generate
+@@ -4125,208 +4262,252 @@
+ if (negative)
+ offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1);
+
++ if (load_lanes_p)
++ aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
++ else
++ aggr_type = vectype;
++
+ prev_stmt_info = NULL;
+ for (j = 0; j < ncopies; j++)
+ {
+ /* 1. Create the vector pointer update chain. */
+ if (j == 0)
+- dataref_ptr = vect_create_data_ref_ptr (first_stmt,
++ dataref_ptr = vect_create_data_ref_ptr (first_stmt, aggr_type,
+ at_loop, offset,
+ &dummy, &ptr_incr, false,
+ &inv_p);
+ else
+- dataref_ptr =
+- bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt, NULL_TREE);
+-
+- for (i = 0; i < vec_num; i++)
++ dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
++ TYPE_SIZE_UNIT (aggr_type));
++
++ if (strided_load || slp_perm)
++ dr_chain = VEC_alloc (tree, heap, vec_num);
++
++ if (load_lanes_p)
+ {
+- if (i > 0)
+- dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi, stmt,
+- NULL_TREE);
+-
+- /* 2. Create the vector-load in the loop. */
+- switch (alignment_support_scheme)
+- {
+- case dr_aligned:
+- case dr_unaligned_supported:
+- {
+- struct ptr_info_def *pi;
+- data_ref
+- = build2 (MEM_REF, vectype, dataref_ptr,
+- build_int_cst (reference_alias_ptr_type
+- (DR_REF (first_dr)), 0));
+- pi = get_ptr_info (dataref_ptr);
+- pi->align = TYPE_ALIGN_UNIT (vectype);
+- if (alignment_support_scheme == dr_aligned)
+- {
+- gcc_assert (aligned_access_p (first_dr));
+- pi->misalign = 0;
+- }
+- else if (DR_MISALIGNMENT (first_dr) == -1)
+- {
+- TREE_TYPE (data_ref)
+- = build_aligned_type (TREE_TYPE (data_ref),
+- TYPE_ALIGN (TREE_TYPE (vectype)));
+- pi->align = TYPE_ALIGN_UNIT (TREE_TYPE (vectype));
+- pi->misalign = 0;
+- }
+- else
+- {
+- TREE_TYPE (data_ref)
+- = build_aligned_type (TREE_TYPE (data_ref),
+- TYPE_ALIGN (TREE_TYPE (vectype)));
+- pi->misalign = DR_MISALIGNMENT (first_dr);
+- }
+- break;
+- }
+- case dr_explicit_realign:
+- {
+- tree ptr, bump;
+- tree vs_minus_1 = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
+-
+- if (compute_in_loop)
+- msq = vect_setup_realignment (first_stmt, gsi,
+- &realignment_token,
+- dr_explicit_realign,
+- dataref_ptr, NULL);
+-
+- new_stmt = gimple_build_assign_with_ops
+- (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
+- build_int_cst
+- (TREE_TYPE (dataref_ptr),
+- -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
+- ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
+- gimple_assign_set_lhs (new_stmt, ptr);
+- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+- data_ref
+- = build2 (MEM_REF, vectype, ptr,
+- build_int_cst (reference_alias_ptr_type
+- (DR_REF (first_dr)), 0));
+- vec_dest = vect_create_destination_var (scalar_dest, vectype);
+- new_stmt = gimple_build_assign (vec_dest, data_ref);
+- new_temp = make_ssa_name (vec_dest, new_stmt);
+- gimple_assign_set_lhs (new_stmt, new_temp);
+- gimple_set_vdef (new_stmt, gimple_vdef (stmt));
+- gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+- msq = new_temp;
+-
+- bump = size_binop (MULT_EXPR, vs_minus_1,
+- TYPE_SIZE_UNIT (scalar_type));
+- ptr = bump_vector_ptr (dataref_ptr, NULL, gsi, stmt, bump);
+- new_stmt = gimple_build_assign_with_ops
+- (BIT_AND_EXPR, NULL_TREE, ptr,
+- build_int_cst
+- (TREE_TYPE (ptr),
+- -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
+- ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
+- gimple_assign_set_lhs (new_stmt, ptr);
+- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+- data_ref
+- = build2 (MEM_REF, vectype, ptr,
+- build_int_cst (reference_alias_ptr_type
+- (DR_REF (first_dr)), 0));
+- break;
+- }
+- case dr_explicit_realign_optimized:
+- new_stmt = gimple_build_assign_with_ops
+- (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
+- build_int_cst
+- (TREE_TYPE (dataref_ptr),
+- -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
+- new_temp = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
+- gimple_assign_set_lhs (new_stmt, new_temp);
+- vect_finish_stmt_generation (stmt, new_stmt, gsi);
+- data_ref
+- = build2 (MEM_REF, vectype, new_temp,
+- build_int_cst (reference_alias_ptr_type
+- (DR_REF (first_dr)), 0));
+- break;
+- default:
+- gcc_unreachable ();
+- }
+- vec_dest = vect_create_destination_var (scalar_dest, vectype);
+- new_stmt = gimple_build_assign (vec_dest, data_ref);
+- new_temp = make_ssa_name (vec_dest, new_stmt);
+- gimple_assign_set_lhs (new_stmt, new_temp);
++ tree vec_array;
++
++ vec_array = create_vector_array (vectype, vec_num);
++
++ /* Emit:
++ VEC_ARRAY = LOAD_LANES (MEM_REF[...all elements...]). */
++ data_ref = create_array_ref (aggr_type, dataref_ptr, first_dr);
++ new_stmt = gimple_build_call_internal (IFN_LOAD_LANES, 1, data_ref);
++ gimple_call_set_lhs (new_stmt, vec_array);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ mark_symbols_for_renaming (new_stmt);
+
+- /* 3. Handle explicit realignment if necessary/supported. Create in
+- loop: vec_dest = realign_load (msq, lsq, realignment_token) */
+- if (alignment_support_scheme == dr_explicit_realign_optimized
+- || alignment_support_scheme == dr_explicit_realign)
+- {
+- tree tmp;
+-
+- lsq = gimple_assign_lhs (new_stmt);
+- if (!realignment_token)
+- realignment_token = dataref_ptr;
++ /* Extract each vector into an SSA_NAME. */
++ for (i = 0; i < vec_num; i++)
++ {
++ new_temp = read_vector_array (stmt, gsi, scalar_dest,
++ vec_array, i);
++ VEC_quick_push (tree, dr_chain, new_temp);
++ }
++
++ /* Record the mapping between SSA_NAMEs and statements. */
++ vect_record_strided_load_vectors (stmt, dr_chain);
++ }
++ else
++ {
++ for (i = 0; i < vec_num; i++)
++ {
++ if (i > 0)
++ dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
++ stmt, NULL_TREE);
++
++ /* 2. Create the vector-load in the loop. */
++ switch (alignment_support_scheme)
++ {
++ case dr_aligned:
++ case dr_unaligned_supported:
++ {
++ struct ptr_info_def *pi;
++ data_ref
++ = build2 (MEM_REF, vectype, dataref_ptr,
++ build_int_cst (reference_alias_ptr_type
++ (DR_REF (first_dr)), 0));
++ pi = get_ptr_info (dataref_ptr);
++ pi->align = TYPE_ALIGN_UNIT (vectype);
++ if (alignment_support_scheme == dr_aligned)
++ {
++ gcc_assert (aligned_access_p (first_dr));
++ pi->misalign = 0;
++ }
++ else if (DR_MISALIGNMENT (first_dr) == -1)
++ {
++ TREE_TYPE (data_ref)
++ = build_aligned_type (TREE_TYPE (data_ref),
++ TYPE_ALIGN (elem_type));
++ pi->align = TYPE_ALIGN_UNIT (elem_type);
++ pi->misalign = 0;
++ }
++ else
++ {
++ TREE_TYPE (data_ref)
++ = build_aligned_type (TREE_TYPE (data_ref),
++ TYPE_ALIGN (elem_type));
++ pi->misalign = DR_MISALIGNMENT (first_dr);
++ }
++ break;
++ }
++ case dr_explicit_realign:
++ {
++ tree ptr, bump;
++ tree vs_minus_1
++ = size_int (TYPE_VECTOR_SUBPARTS (vectype) - 1);
++
++ if (compute_in_loop)
++ msq = vect_setup_realignment (first_stmt, gsi,
++ &realignment_token,
++ dr_explicit_realign,
++ dataref_ptr, NULL);
++
++ new_stmt = gimple_build_assign_with_ops
++ (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
++ build_int_cst
++ (TREE_TYPE (dataref_ptr),
++ -(HOST_WIDE_INT)
++ TYPE_ALIGN_UNIT (vectype)));
++ ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
++ gimple_assign_set_lhs (new_stmt, ptr);
++ vect_finish_stmt_generation (stmt, new_stmt, gsi);
++ data_ref
++ = build2 (MEM_REF, vectype, ptr,
++ build_int_cst (reference_alias_ptr_type
++ (DR_REF (first_dr)), 0));
++ vec_dest = vect_create_destination_var (scalar_dest,
++ vectype);
++ new_stmt = gimple_build_assign (vec_dest, data_ref);
++ new_temp = make_ssa_name (vec_dest, new_stmt);
++ gimple_assign_set_lhs (new_stmt, new_temp);
++ gimple_set_vdef (new_stmt, gimple_vdef (stmt));
++ gimple_set_vuse (new_stmt, gimple_vuse (stmt));
++ vect_finish_stmt_generation (stmt, new_stmt, gsi);
++ msq = new_temp;
++
++ bump = size_binop (MULT_EXPR, vs_minus_1,
++ TYPE_SIZE_UNIT (scalar_type));
++ ptr = bump_vector_ptr (dataref_ptr, NULL, gsi, stmt, bump);
++ new_stmt = gimple_build_assign_with_ops
++ (BIT_AND_EXPR, NULL_TREE, ptr,
++ build_int_cst
++ (TREE_TYPE (ptr),
++ -(HOST_WIDE_INT)
++ TYPE_ALIGN_UNIT (vectype)));
++ ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
++ gimple_assign_set_lhs (new_stmt, ptr);
++ vect_finish_stmt_generation (stmt, new_stmt, gsi);
++ data_ref
++ = build2 (MEM_REF, vectype, ptr,
++ build_int_cst (reference_alias_ptr_type
++ (DR_REF (first_dr)), 0));
++ break;
++ }
++ case dr_explicit_realign_optimized:
++ new_stmt = gimple_build_assign_with_ops
++ (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
++ build_int_cst
++ (TREE_TYPE (dataref_ptr),
++ -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
++ new_temp = make_ssa_name (SSA_NAME_VAR (dataref_ptr),
++ new_stmt);
++ gimple_assign_set_lhs (new_stmt, new_temp);
++ vect_finish_stmt_generation (stmt, new_stmt, gsi);
++ data_ref
++ = build2 (MEM_REF, vectype, new_temp,
++ build_int_cst (reference_alias_ptr_type
++ (DR_REF (first_dr)), 0));
++ break;
++ default:
++ gcc_unreachable ();
++ }
+ vec_dest = vect_create_destination_var (scalar_dest, vectype);
+- tmp = build3 (REALIGN_LOAD_EXPR, vectype, msq, lsq,
+- realignment_token);
+- new_stmt = gimple_build_assign (vec_dest, tmp);
++ new_stmt = gimple_build_assign (vec_dest, data_ref);
+ new_temp = make_ssa_name (vec_dest, new_stmt);
+ gimple_assign_set_lhs (new_stmt, new_temp);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+-
+- if (alignment_support_scheme == dr_explicit_realign_optimized)
+- {
+- gcc_assert (phi);
+- if (i == vec_num - 1 && j == ncopies - 1)
+- add_phi_arg (phi, lsq, loop_latch_edge (containing_loop),
+- UNKNOWN_LOCATION);
+- msq = lsq;
+- }
+- }
+-
+- /* 4. Handle invariant-load. */
+- if (inv_p && !bb_vinfo)
+- {
+- gcc_assert (!strided_load);
+- gcc_assert (nested_in_vect_loop_p (loop, stmt));
+- if (j == 0)
+- {
+- int k;
+- tree t = NULL_TREE;
+- tree vec_inv, bitpos, bitsize = TYPE_SIZE (scalar_type);
+-
+- /* CHECKME: bitpos depends on endianess? */
+- bitpos = bitsize_zero_node;
+- vec_inv = build3 (BIT_FIELD_REF, scalar_type, new_temp,
+- bitsize, bitpos);
+- vec_dest =
+- vect_create_destination_var (scalar_dest, NULL_TREE);
+- new_stmt = gimple_build_assign (vec_dest, vec_inv);
+- new_temp = make_ssa_name (vec_dest, new_stmt);
++ mark_symbols_for_renaming (new_stmt);
++
++ /* 3. Handle explicit realignment if necessary/supported.
++ Create in loop:
++ vec_dest = realign_load (msq, lsq, realignment_token) */
++ if (alignment_support_scheme == dr_explicit_realign_optimized
++ || alignment_support_scheme == dr_explicit_realign)
++ {
++ tree tmp;
++
++ lsq = gimple_assign_lhs (new_stmt);
++ if (!realignment_token)
++ realignment_token = dataref_ptr;
++ vec_dest = vect_create_destination_var (scalar_dest, vectype);
++ tmp = build3 (REALIGN_LOAD_EXPR, vectype, msq, lsq,
++ realignment_token);
++ new_stmt = gimple_build_assign (vec_dest, tmp);
++ new_temp = make_ssa_name (vec_dest, new_stmt);
+ gimple_assign_set_lhs (new_stmt, new_temp);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+
+- for (k = nunits - 1; k >= 0; --k)
+- t = tree_cons (NULL_TREE, new_temp, t);
+- /* FIXME: use build_constructor directly. */
+- vec_inv = build_constructor_from_list (vectype, t);
+- new_temp = vect_init_vector (stmt, vec_inv, vectype, gsi);
++ if (alignment_support_scheme == dr_explicit_realign_optimized)
++ {
++ gcc_assert (phi);
++ if (i == vec_num - 1 && j == ncopies - 1)
++ add_phi_arg (phi, lsq,
++ loop_latch_edge (containing_loop),
++ UNKNOWN_LOCATION);
++ msq = lsq;
++ }
++ }
++
++ /* 4. Handle invariant-load. */
++ if (inv_p && !bb_vinfo)
++ {
++ gcc_assert (!strided_load);
++ gcc_assert (nested_in_vect_loop_p (loop, stmt));
++ if (j == 0)
++ {
++ int k;
++ tree t = NULL_TREE;
++ tree vec_inv, bitpos, bitsize = TYPE_SIZE (scalar_type);
++
++ /* CHECKME: bitpos depends on endianess? */
++ bitpos = bitsize_zero_node;
++ vec_inv = build3 (BIT_FIELD_REF, scalar_type, new_temp,
++ bitsize, bitpos);
++ vec_dest = vect_create_destination_var (scalar_dest,
++ NULL_TREE);
++ new_stmt = gimple_build_assign (vec_dest, vec_inv);
++ new_temp = make_ssa_name (vec_dest, new_stmt);
++ gimple_assign_set_lhs (new_stmt, new_temp);
++ vect_finish_stmt_generation (stmt, new_stmt, gsi);
++
++ for (k = nunits - 1; k >= 0; --k)
++ t = tree_cons (NULL_TREE, new_temp, t);
++ /* FIXME: use build_constructor directly. */
++ vec_inv = build_constructor_from_list (vectype, t);
++ new_temp = vect_init_vector (stmt, vec_inv, vectype, gsi);
++ new_stmt = SSA_NAME_DEF_STMT (new_temp);
++ }
++ else
++ gcc_unreachable (); /* FORNOW. */
++ }
++
++ if (negative)
++ {
++ new_temp = reverse_vec_elements (new_temp, stmt, gsi);
+ new_stmt = SSA_NAME_DEF_STMT (new_temp);
+ }
+- else
+- gcc_unreachable (); /* FORNOW. */
+- }
+-
+- if (negative)
+- {
+- new_temp = reverse_vec_elements (new_temp, stmt, gsi);
+- new_stmt = SSA_NAME_DEF_STMT (new_temp);
+- }
+-
+- /* Collect vector loads and later create their permutation in
+- vect_transform_strided_load (). */
+- if (strided_load || slp_perm)
+- VEC_quick_push (tree, dr_chain, new_temp);
+-
+- /* Store vector loads in the corresponding SLP_NODE. */
+- if (slp && !slp_perm)
+- VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
++
++ /* Collect vector loads and later create their permutation in
++ vect_transform_strided_load (). */
++ if (strided_load || slp_perm)
++ VEC_quick_push (tree, dr_chain, new_temp);
++
++ /* Store vector loads in the corresponding SLP_NODE. */
++ if (slp && !slp_perm)
++ VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node),
++ new_stmt);
++ }
+ }
+
+ if (slp && !slp_perm)
+@@ -4345,12 +4526,9 @@
+ {
+ if (strided_load)
+ {
+- if (!vect_transform_strided_load (stmt, dr_chain, group_size, gsi))
+- return false;
+-
++ if (!load_lanes_p)
++ vect_transform_strided_load (stmt, dr_chain, group_size, gsi);
+ *vec_stmt = STMT_VINFO_VEC_STMT (stmt_info);
+- VEC_free (tree, heap, dr_chain);
+- dr_chain = VEC_alloc (tree, heap, group_size);
+ }
+ else
+ {
+@@ -4361,11 +4539,10 @@
+ prev_stmt_info = vinfo_for_stmt (new_stmt);
+ }
+ }
++ if (dr_chain)
++ VEC_free (tree, heap, dr_chain);
+ }
+
+- if (dr_chain)
+- VEC_free (tree, heap, dr_chain);
+-
+ return true;
+ }
+
+@@ -4769,27 +4946,6 @@
+ return false;
+ }
+
+- if (!PURE_SLP_STMT (stmt_info))
+- {
+- /* Groups of strided accesses whose size is not a power of 2 are not
+- vectorizable yet using loop-vectorization. Therefore, if this stmt
+- feeds non-SLP-able stmts (i.e., this stmt has to be both SLPed and
+- loop-based vectorized), the loop cannot be vectorized. */
+- if (STMT_VINFO_STRIDED_ACCESS (stmt_info)
+- && exact_log2 (DR_GROUP_SIZE (vinfo_for_stmt (
+- DR_GROUP_FIRST_DR (stmt_info)))) == -1)
+- {
+- if (vect_print_dump_info (REPORT_DETAILS))
+- {
+- fprintf (vect_dump, "not vectorized: the size of group "
+- "of strided accesses is not a power of 2");
+- print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
+- }
+-
+- return false;
+- }
+- }
+-
+ return true;
+ }
+
+
+=== modified file 'gcc/tree-vectorizer.h'
+--- old/gcc/tree-vectorizer.h 2010-12-23 16:25:52 +0000
++++ new/gcc/tree-vectorizer.h 2011-05-05 15:43:06 +0000
+@@ -788,9 +788,9 @@
+ extern tree vectorizable_function (gimple, tree, tree);
+ extern void vect_model_simple_cost (stmt_vec_info, int, enum vect_def_type *,
+ slp_tree);
+-extern void vect_model_store_cost (stmt_vec_info, int, enum vect_def_type,
+- slp_tree);
+-extern void vect_model_load_cost (stmt_vec_info, int, slp_tree);
++extern void vect_model_store_cost (stmt_vec_info, int, bool,
++ enum vect_def_type, slp_tree);
++extern void vect_model_load_cost (stmt_vec_info, int, bool, slp_tree);
+ extern void vect_finish_stmt_generation (gimple, gimple,
+ gimple_stmt_iterator *);
+ extern bool vect_mark_stmts_to_be_vectorized (loop_vec_info);
+@@ -823,21 +823,22 @@
+ extern bool vect_analyze_data_ref_accesses (loop_vec_info, bb_vec_info);
+ extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
+ extern bool vect_analyze_data_refs (loop_vec_info, bb_vec_info, int *);
+-extern tree vect_create_data_ref_ptr (gimple, struct loop *, tree, tree *,
+- gimple *, bool, bool *);
++extern tree vect_create_data_ref_ptr (gimple, tree, struct loop *, tree,
++ tree *, gimple *, bool, bool *);
+ extern tree bump_vector_ptr (tree, gimple, gimple_stmt_iterator *, gimple, tree);
+ extern tree vect_create_destination_var (tree, tree);
+-extern bool vect_strided_store_supported (tree);
+-extern bool vect_strided_load_supported (tree);
+-extern bool vect_permute_store_chain (VEC(tree,heap) *,unsigned int, gimple,
++extern bool vect_strided_store_supported (tree, unsigned HOST_WIDE_INT);
++extern bool vect_store_lanes_supported (tree, unsigned HOST_WIDE_INT);
++extern bool vect_strided_load_supported (tree, unsigned HOST_WIDE_INT);
++extern bool vect_load_lanes_supported (tree, unsigned HOST_WIDE_INT);
++extern void vect_permute_store_chain (VEC(tree,heap) *,unsigned int, gimple,
+ gimple_stmt_iterator *, VEC(tree,heap) **);
+ extern tree vect_setup_realignment (gimple, gimple_stmt_iterator *, tree *,
+ enum dr_alignment_support, tree,
+ struct loop **);
+-extern bool vect_permute_load_chain (VEC(tree,heap) *,unsigned int, gimple,
+- gimple_stmt_iterator *, VEC(tree,heap) **);
+-extern bool vect_transform_strided_load (gimple, VEC(tree,heap) *, int,
++extern void vect_transform_strided_load (gimple, VEC(tree,heap) *, int,
+ gimple_stmt_iterator *);
++extern void vect_record_strided_load_vectors (gimple, VEC(tree,heap) *);
+ extern int vect_get_place_in_interleaving_chain (gimple, gimple);
+ extern tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
+ extern tree vect_create_addr_base_for_vector_ref (gimple, gimple_seq *,
+
+=== modified file 'gcc/tree.c'
+--- old/gcc/tree.c 2011-05-18 13:29:24 +0000
++++ new/gcc/tree.c 2011-06-02 12:12:00 +0000
+@@ -7321,6 +7321,15 @@
+ return build_array_type_1 (elt_type, index_type, false);
+ }
+
++/* Return a representation of ELT_TYPE[NELTS], using indices of type
++ sizetype. */
++
++tree
++build_array_type_nelts (tree elt_type, unsigned HOST_WIDE_INT nelts)
++{
++ return build_array_type (elt_type, build_index_type (size_int (nelts - 1)));
++}
++
+ /* Recursively examines the array elements of TYPE, until a non-array
+ element type is found. */
+
+
+=== modified file 'gcc/tree.h'
+--- old/gcc/tree.h 2011-03-11 22:38:58 +0000
++++ new/gcc/tree.h 2011-05-05 15:43:06 +0000
+@@ -4192,6 +4192,7 @@
+ extern tree build_index_type (tree);
+ extern tree build_array_type (tree, tree);
+ extern tree build_nonshared_array_type (tree, tree);
++extern tree build_array_type_nelts (tree, unsigned HOST_WIDE_INT);
+ extern tree build_function_type (tree, tree);
+ extern tree build_function_type_list (tree, ...);
+ extern tree build_function_type_skip_args (tree, bitmap);
+
+=== modified file 'gcc/value-prof.c'
+--- old/gcc/value-prof.c 2011-01-29 03:54:56 +0000
++++ new/gcc/value-prof.c 2011-05-05 15:42:22 +0000
+@@ -1242,6 +1242,9 @@
+ if (TREE_CODE (callee) == FUNCTION_DECL)
+ return false;
+
++ if (gimple_call_internal_p (stmt))
++ return false;
++
+ histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INDIR_CALL);
+ if (!histogram)
+ return false;
+@@ -1630,6 +1633,7 @@
+ tree callee;
+
+ if (gimple_code (stmt) != GIMPLE_CALL
++ || gimple_call_internal_p (stmt)
+ || gimple_call_fndecl (stmt) != NULL_TREE)
+ return;
+
+