]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree.def (ALIGN_INDIRECT_REF, [...]): New tree-codes.
authorDorit Naishlos <dorit@il.ibm.com>
Thu, 23 Sep 2004 14:34:35 +0000 (14:34 +0000)
committerDorit Nuzman <dorit@gcc.gnu.org>
Thu, 23 Sep 2004 14:34:35 +0000 (14:34 +0000)
2004-09-23  Dorit Naishlos <dorit@il.ibm.com>

        * tree.def (ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF):
        New tree-codes.
        * tree.h (REF_ORIGINAL): Consider ALIGN_INDIRECT_REF and
        MISALIGNED_INDIRECT_REF.
        * alias.c (get_alias_set, nonoverlapping_memrefs_p): Likewise.
        * emit-rtl.c (mem_expr_equal_p, set_mem_attributes_minus_bitpos):
        Likewise.
        * expr.c (safe_from_p, expand_expr_real_1, rewrite_address_base)
        (find_interesting_uses_address): Likewise.
        * fold-const.c (non_lvalue, operand_equal_p): Likewise.
        (build_fold_addr_expr_with_type): Likewise.
        * gimplify.c (gimplify_addr_expr, gimplify_expr): Likewise.
        * print-rtl.c (print_mem_expr): Likewise.
        * tree-dump.c (dequeue_and_dump): Likewise.
        * tree-eh.c (tree_could_trap_p): Likewise.
        * tree-gimple.c (is_gimple_addressable, get_base_address): Likewise.
        * tree-pretty-print.c (op_prio, op_symbol, dump_generic_node): Likewise.
        * tree-ssa-alias.c (find_ptr_dereference, ptr_is_dereferenced_by):
        Likewise.
        * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
        * tree-ssa-dom.c (record_equivalences_from_stmt): Likewise.
        * tree-ssa-loop-im.c (for_each_index, is_call_clobbered_ref): Likewise.
        * tree-ssa-loop-ivopts.c (find_interesting_uses_address): Likewise.
        (add_address_candidates, rewrite_address_base): Likewise.
        * tree-ssa-operands.c (get_expr_operands, get_indirect_ref_operands):
        Likewise.
        * tree.c (staticp, build1_stat): Likewise.

        * tree.def (REALIGN_LOAD_EXPR, REALIGN_STORE_EXPR): New tree-codes.
        * tree-pretty-print.c (dump_generic_node): Consider REALIGN_LOAD_EXPR.
        * tree-ssa-operands.c (get_expr_operands): Likewise.
        * expr.c (expand_expr_real_1): Likewise.

        * optabs.h (vec_realign_store_optab, vec_realign_load_optab): New
        optabs.
        (OTI_vec_realign_store, OTI_vec_realign_load): New optab_index values
        for the new optabs.
        (expand_ternary_op): New function.
        * genopinit.c (optabs): Handle the new optabs.
        * optabs.c (optab_for_tree_code): Add cases for the new tree-codes.
        (init_optabs): Initialize vec_realign_load_optab.
        (expand_ternary_op): New functions.

        * target-def.h (TARGET_VECTORIZE): New member for struct gcc_target.
        (TARGET_VECTORIZE_MISALIGNED_MEM_OK): New member for targetm.vectorize.
        (TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD): Likewise.
        (TARGET_VECTORIZE_BUILTIN_MASK_FOR_STORE): Likewise.
        * target.h (struct vectorize): New member for struct gcc_target.
        (misaligned_mem_ok): New member for targetm.vectorize.
        (builtin_mask_for_load): Likewise.
        (builtin_mask_for_store): Likewise.
        * targethooks.c (default_vect_misaligned_mem_ok): New function.
        * targethooks.h (default_vect_misaligned_mem_ok): New function.

        * config/rs6000/altivec.md (build_vector_mask_for_load): New
        define_expand.
        (vec_realign_load_v4si, vec_realign_load_v4sf, vec_realign_load_v8hi)
        (vec_realign_load_v16qi): New define_insn.
        * config/rs6000/rs6000.h (ALTIVEC_BUILTIN_MASK_FOR_LOAD):
        (ALTIVEC_BUILTIN_MASK_FOR_STORE): New target builtins.
        * config/rs6000/rs6000.c (altivec_builtin_mask_for_load):
        (altivec_builtin_mask_for_store): New variables.
        (rs6000_builtin_mask_for_load): New function. Implements
        TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD.
        (rs6000_builtin_mask_for_store): New function. Implements
        TARGET_VECTORIZE_BUILTIN_MASK_FOR_STORE.
        (rs6000_expand_builtin): Expand the target builtins
        builtin_mask_for_load and builtin_mask_for_store.
        (altivec_init_builtins): Initialize the new target builtins.
        * config/i386/i386.c (ix86_misaligned_mem_ok): New function.
        Implements the target hook TARGET_VECTORIZE_MISALIGNED_MEM_OK.

        * tree-vectorizer.c (vect_create_data_ref): Renamed to
        vect_create_data_ref_ptr. Returns a pointer instead of an array-ref.
        (vect_create_addr_base_for_vector_ref): Additional argument (offset).
        (vectorizable_store): Call vect_create_data_ref_ptr with additional
        arguments, and create an indirect_ref with its return value data_ref.
        Check aligned_access_p.
        (vectorizable_load): Handle misaligned loads, using software-pipelined
        scheme with REALIGN_LOAD_EXPR and ALIGN_INDIRECT_REF if
        vec_realign_load_optab is supported, or using a scheme without
        software-pipelining with MISALIGNED_INDIRECT_REF if the target hook
        misaligned_mem_ok is supported.

        (vect_finish_stmt_generation): Typo.
        (vect_enhance_data_refs_alignment): Rename loop_vinfo to loop_info.
        (vect_analyze_data_refs_alignment): Don't fail vectorization in the
        presence of misaligned loads.
        (vect_analyze_data_ref_access): Add check for constant init.
        (vect_get_symbl_and_dr): Remove duplicate line.
        * tree-vectorizer.h (DR_MISALIGNMENT): Add comment.

From-SVN: r87948

72 files changed:
gcc/ChangeLog
gcc/alias.c
gcc/config/i386/i386.c
gcc/config/rs6000/altivec.md
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/emit-rtl.c
gcc/expr.c
gcc/fold-const.c
gcc/genopinit.c
gcc/gimplify.c
gcc/optabs.c
gcc/optabs.h
gcc/print-rtl.c
gcc/target-def.h
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-13.c
gcc/testsuite/gcc.dg/vect/vect-26.c
gcc/testsuite/gcc.dg/vect/vect-27.c
gcc/testsuite/gcc.dg/vect/vect-27a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-28.c
gcc/testsuite/gcc.dg/vect/vect-29.c
gcc/testsuite/gcc.dg/vect/vect-29a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-40.c
gcc/testsuite/gcc.dg/vect/vect-41.c
gcc/testsuite/gcc.dg/vect/vect-42.c
gcc/testsuite/gcc.dg/vect/vect-43.c
gcc/testsuite/gcc.dg/vect/vect-44.c
gcc/testsuite/gcc.dg/vect/vect-45.c
gcc/testsuite/gcc.dg/vect/vect-46.c
gcc/testsuite/gcc.dg/vect/vect-47.c
gcc/testsuite/gcc.dg/vect/vect-48.c
gcc/testsuite/gcc.dg/vect/vect-48a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-49.c
gcc/testsuite/gcc.dg/vect/vect-50.c
gcc/testsuite/gcc.dg/vect/vect-51.c
gcc/testsuite/gcc.dg/vect/vect-52.c
gcc/testsuite/gcc.dg/vect/vect-53.c
gcc/testsuite/gcc.dg/vect/vect-54.c
gcc/testsuite/gcc.dg/vect/vect-55.c
gcc/testsuite/gcc.dg/vect/vect-56.c
gcc/testsuite/gcc.dg/vect/vect-56a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-57.c
gcc/testsuite/gcc.dg/vect/vect-58.c
gcc/testsuite/gcc.dg/vect/vect-59.c
gcc/testsuite/gcc.dg/vect/vect-60.c
gcc/testsuite/gcc.dg/vect/vect-61.c
gcc/testsuite/gcc.dg/vect/vect-72.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-72a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-75.c
gcc/testsuite/gcc.dg/vect/vect-76.c
gcc/testsuite/gcc.dg/vect/vect-77.c
gcc/testsuite/gcc.dg/vect/vect-77a.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-78.c
gcc/tree-dump.c
gcc/tree-eh.c
gcc/tree-gimple.c
gcc/tree-pretty-print.c
gcc/tree-ssa-alias.c
gcc/tree-ssa-dce.c
gcc/tree-ssa-dom.c
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-operands.c
gcc/tree-vectorizer.c
gcc/tree-vectorizer.h
gcc/tree.c
gcc/tree.def
gcc/tree.h

index aa7bb17cea7c0064b061adeb8d54e36a260afbd0..65f8c94af6c6568a31c1929321b15b6520255644 100644 (file)
@@ -1,3 +1,97 @@
+2004-09-23  Dorit Naishlos <dorit@il.ibm.com>
+
+        * tree.def (ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF):
+        New tree-codes.
+        * tree.h (REF_ORIGINAL): Consider ALIGN_INDIRECT_REF and
+        MISALIGNED_INDIRECT_REF.
+        * alias.c (get_alias_set, nonoverlapping_memrefs_p): Likewise.
+        * emit-rtl.c (mem_expr_equal_p, set_mem_attributes_minus_bitpos):
+        Likewise.
+        * expr.c (safe_from_p, expand_expr_real_1, rewrite_address_base)
+        (find_interesting_uses_address): Likewise.
+        * fold-const.c (non_lvalue, operand_equal_p): Likewise.
+        (build_fold_addr_expr_with_type): Likewise.
+        * gimplify.c (gimplify_addr_expr, gimplify_expr): Likewise.
+        * print-rtl.c (print_mem_expr): Likewise.
+        * tree-dump.c (dequeue_and_dump): Likewise.
+        * tree-eh.c (tree_could_trap_p): Likewise.
+        * tree-gimple.c (is_gimple_addressable, get_base_address): Likewise.
+        * tree-pretty-print.c (op_prio, op_symbol, dump_generic_node): Likewise.
+        * tree-ssa-alias.c (find_ptr_dereference, ptr_is_dereferenced_by):
+        Likewise.
+        * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
+        * tree-ssa-dom.c (record_equivalences_from_stmt): Likewise.
+        * tree-ssa-loop-im.c (for_each_index, is_call_clobbered_ref): Likewise.
+        * tree-ssa-loop-ivopts.c (find_interesting_uses_address): Likewise.
+        (add_address_candidates, rewrite_address_base): Likewise.
+        * tree-ssa-operands.c (get_expr_operands, get_indirect_ref_operands):
+        Likewise.
+        * tree.c (staticp, build1_stat): Likewise.
+
+        * tree.def (REALIGN_LOAD_EXPR, REALIGN_STORE_EXPR): New tree-codes.
+        * tree-pretty-print.c (dump_generic_node): Consider REALIGN_LOAD_EXPR.
+        * tree-ssa-operands.c (get_expr_operands): Likewise.
+        * expr.c (expand_expr_real_1): Likewise.
+
+        * optabs.h (vec_realign_store_optab, vec_realign_load_optab): New
+        optabs.
+        (OTI_vec_realign_store, OTI_vec_realign_load): New optab_index values
+        for the new optabs.
+        (expand_ternary_op): New function.
+        * genopinit.c (optabs): Handle the new optabs.
+        * optabs.c (optab_for_tree_code): Add cases for the new tree-codes.
+        (init_optabs): Initialize vec_realign_load_optab.
+        (expand_ternary_op): New functions.
+
+        * target-def.h (TARGET_VECTORIZE): New member for struct gcc_target.
+        (TARGET_VECTORIZE_MISALIGNED_MEM_OK): New member for targetm.vectorize.
+        (TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD): Likewise.
+        (TARGET_VECTORIZE_BUILTIN_MASK_FOR_STORE): Likewise.
+        * target.h (struct vectorize): New member for struct gcc_target.
+        (misaligned_mem_ok): New member for targetm.vectorize.
+        (builtin_mask_for_load): Likewise.
+        (builtin_mask_for_store): Likewise.
+        * targethooks.c (default_vect_misaligned_mem_ok): New function.
+        * targethooks.h (default_vect_misaligned_mem_ok): New function.
+
+        * config/rs6000/altivec.md (build_vector_mask_for_load): New
+        define_expand.
+        (vec_realign_load_v4si, vec_realign_load_v4sf, vec_realign_load_v8hi)
+        (vec_realign_load_v16qi): New define_insn.
+        * config/rs6000/rs6000.h (ALTIVEC_BUILTIN_MASK_FOR_LOAD):
+        (ALTIVEC_BUILTIN_MASK_FOR_STORE): New target builtins.
+        * config/rs6000/rs6000.c (altivec_builtin_mask_for_load):
+        (altivec_builtin_mask_for_store): New variables.
+        (rs6000_builtin_mask_for_load): New function. Implements
+        TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD.
+        (rs6000_builtin_mask_for_store): New function. Implements
+        TARGET_VECTORIZE_BUILTIN_MASK_FOR_STORE.
+        (rs6000_expand_builtin): Expand the target builtins
+        builtin_mask_for_load and builtin_mask_for_store.
+        (altivec_init_builtins): Initialize the new target builtins.
+        * config/i386/i386.c (ix86_misaligned_mem_ok): New function.
+        Implements the target hook TARGET_VECTORIZE_MISALIGNED_MEM_OK.
+
+        * tree-vectorizer.c (vect_create_data_ref): Renamed to
+        vect_create_data_ref_ptr. Returns a pointer instead of an array-ref.
+        (vect_create_addr_base_for_vector_ref): Additional argument (offset).
+        (vectorizable_store): Call vect_create_data_ref_ptr with additional
+        arguments, and create an indirect_ref with its return value data_ref.
+        Check aligned_access_p.
+        (vectorizable_load): Handle misaligned loads, using software-pipelined
+        scheme with REALIGN_LOAD_EXPR and ALIGN_INDIRECT_REF if
+        vec_realign_load_optab is supported, or using a scheme without
+        software-pipelining with MISALIGNED_INDIRECT_REF if the target hook
+        misaligned_mem_ok is supported.
+
+        (vect_finish_stmt_generation): Typo.
+        (vect_enhance_data_refs_alignment): Rename loop_vinfo to loop_info.
+        (vect_analyze_data_refs_alignment): Don't fail vectorization in the
+        presence of misaligned loads.
+        (vect_analyze_data_ref_access): Add check for constant init.
+        (vect_get_symbl_and_dr): Remove duplicate line.
+        * tree-vectorizer.h (DR_MISALIGNMENT): Add comment.
+
 2004-09-23  Kazu Hirata  <kazu@cs.umass.edu>
 
        * builtins.c: Fix a comment typo.
index b937cb13cb84572bcd85d9e1035b7f799429b0ed..e096cbf6bc3d5b654975e636e7906d5eec45c66d 100644 (file)
@@ -450,7 +450,9 @@ get_alias_set (tree t)
        }
 
       /* Check for accesses through restrict-qualified pointers.  */
-      if (TREE_CODE (inner) == INDIRECT_REF)
+      if (TREE_CODE (inner) == INDIRECT_REF
+         || TREE_CODE (inner) == ALIGN_INDIRECT_REF
+         || TREE_CODE (inner) == MISALIGNED_INDIRECT_REF)
        {
          tree decl = find_base_decl (TREE_OPERAND (inner, 0));
 
@@ -2006,7 +2008,9 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
       moffsetx = adjust_offset_for_component_ref (exprx, moffsetx);
       exprx = t;
     }
-  else if (TREE_CODE (exprx) == INDIRECT_REF)
+  else if (TREE_CODE (exprx) == INDIRECT_REF
+          || TREE_CODE (exprx) == ALIGN_INDIRECT_REF
+          || TREE_CODE (exprx) == MISALIGNED_INDIRECT_REF)
     {
       exprx = TREE_OPERAND (exprx, 0);
       if (flag_argument_noalias < 2
@@ -2023,7 +2027,9 @@ nonoverlapping_memrefs_p (rtx x, rtx y)
       moffsety = adjust_offset_for_component_ref (expry, moffsety);
       expry = t;
     }
-  else if (TREE_CODE (expry) == INDIRECT_REF)
+  else if (TREE_CODE (expry) == INDIRECT_REF
+           || TREE_CODE (expry) == ALIGN_INDIRECT_REF
+           || TREE_CODE (expry) == MISALIGNED_INDIRECT_REF)
     {
       expry = TREE_OPERAND (expry, 0);
       if (flag_argument_noalias < 2
index 09db92e79714df7557023122ecbebb79d95a7795..de8411eb6635ec951cd78f3f6d060f76e86e772b 100644 (file)
@@ -868,6 +868,7 @@ static void ix86_expand_strlensi_unroll_1 (rtx, rtx, rtx);
 static int ix86_issue_rate (void);
 static int ix86_adjust_cost (rtx, rtx, rtx, int);
 static int ia32_multipass_dfa_lookahead (void);
+static bool ix86_misaligned_mem_ok (enum machine_mode);
 static void ix86_init_mmx_sse_builtins (void);
 static rtx x86_this_parameter (tree);
 static void x86_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
@@ -1014,6 +1015,9 @@ static void init_ext_80387_constants (void);
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
   ia32_multipass_dfa_lookahead
 
+#undef TARGET_VECTORIZE_MISALIGNED_MEM_OK
+#define TARGET_VECTORIZE_MISALIGNED_MEM_OK ix86_misaligned_mem_ok
+
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL ix86_function_ok_for_sibcall
 
@@ -11616,6 +11620,17 @@ ia32_multipass_dfa_lookahead (void)
 }
 
 \f
+/* Implement the target hook targetm.vectorize.misaligned_mem_ok.  */
+
+static bool
+ix86_misaligned_mem_ok (enum machine_mode mode)
+{
+  if (TARGET_MMX && VALID_MMX_REG_MODE (mode))
+    return true;
+  else
+    return false;
+}
+
 /* Compute the alignment given to a constant that is being placed in memory.
    EXP is the constant and ALIGN is the alignment that the object would
    ordinarily have.
index ff58d8e3fa88a79e4af82cd170255f4219408e59..0eb29b1ea37b9c9eb6fb8acb63e4f7d23fd607c4 100644 (file)
   "lvsr %0,%y1"
   [(set_attr "type" "vecload")])
 
+(define_expand "build_vector_mask_for_load"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+       (unspec:V16QI [(match_operand 1 "memory_operand" "m")] 195))]
+  "TARGET_ALTIVEC"
+  "
+{ 
+  rtx addr;
+  rtx temp;
+
+  if (GET_CODE (operands[1]) != MEM)
+    abort ();
+
+  addr = XEXP (operands[1], 0);
+  temp = gen_reg_rtx (GET_MODE (addr));
+  emit_insn (gen_rtx_SET (VOIDmode, temp, 
+                         gen_rtx_NEG (GET_MODE (addr), addr)));
+  emit_insn (gen_altivec_lvsr (operands[0], 
+                              gen_rtx_MEM (GET_MODE (operands[1]), temp)));
+  DONE;
+}")
+
 ;; Parallel some of the LVE* and STV*'s with unspecs because some have
 ;; identical rtl but different instructions-- and gcc gets confused.
 
   "vspltisb %2,0\;vsubsws %3,%2,%1\;vmaxsw %0,%1,%3"
   [(set_attr "type" "vecsimple")
    (set_attr "length" "12")])
+
+(define_insn "vec_realign_load_v4si"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")
+                      (match_operand:V16QI 3 "register_operand" "v")] 215))]
+  "TARGET_ALTIVEC"
+  "vperm %0,%1,%2,%3"
+  [(set_attr "type" "vecperm")])
+
+(define_insn "vec_realign_load_v4sf"
+  [(set (match_operand:V4SF 0 "register_operand" "=v")
+        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")
+                      (match_operand:V16QI 3 "register_operand" "v")] 216))]
+  "TARGET_ALTIVEC"
+  "vperm %0,%1,%2,%3"
+  [(set_attr "type" "vecperm")])
+
+(define_insn "vec_realign_load_v8hi"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")
+                      (match_operand:V16QI 3 "register_operand" "v")] 217))]
+  "TARGET_ALTIVEC"
+  "vperm %0,%1,%2,%3"
+  [(set_attr "type" "vecperm")])
+
+(define_insn "vec_realign_load_v16qi"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                      (match_operand:V16QI 2 "register_operand" "v")
+                      (match_operand:V16QI 3 "register_operand" "v")] 218))]
+  "TARGET_ALTIVEC"
+  "vperm %0,%1,%2,%3"
+  [(set_attr "type" "vecperm")])
+
index eba4a0672fb638e8de883241ccee8917d173a110..7f448ee0c4b8e07aa481955e28174b39cb58a6ab 100644 (file)
@@ -143,6 +143,11 @@ enum rs6000_dependence_cost rs6000_sched_costly_dep;
 const char *rs6000_sched_insert_nops_str;
 enum rs6000_nop_insertion rs6000_sched_insert_nops;
 
+/* Support targetm.vectorize.builtin_mask_for_load.  */
+tree altivec_builtin_mask_for_load;
+/* Support targetm.vectorize.builtin_mask_for_store.  */
+tree altivec_builtin_mask_for_store;
+
 /* Size of long double */
 const char *rs6000_long_double_size_string;
 int rs6000_long_double_type_size;
@@ -681,6 +686,8 @@ static int redefine_groups (FILE *, int, rtx, rtx);
 static int pad_groups (FILE *, int, rtx, rtx);
 static void rs6000_sched_finish (FILE *, int);
 static int rs6000_use_sched_lookahead (void);
+static tree rs6000_builtin_mask_for_load (void);
+static tree rs6000_builtin_mask_for_store (void);
 
 static void rs6000_init_builtins (void);
 static rtx rs6000_expand_unop_builtin (enum insn_code, tree, rtx);
@@ -905,6 +912,12 @@ static const char alt_reg_names[][8] =
 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD rs6000_use_sched_lookahead
 
+#undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
+#define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD rs6000_builtin_mask_for_load
+
+#undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_STORE
+#define TARGET_VECTORIZE_BUILTIN_MASK_FOR_STORE rs6000_builtin_mask_for_store
+
 #undef TARGET_INIT_BUILTINS
 #define TARGET_INIT_BUILTINS rs6000_init_builtins
 
@@ -1536,6 +1549,26 @@ rs6000_override_options (const char *default_cpu)
       }
 }
 
+/* Implement targetm.vectorize.builtin_mask_for_load.  */
+static tree
+rs6000_builtin_mask_for_load (void)
+{
+  if (TARGET_ALTIVEC)
+    return altivec_builtin_mask_for_load;
+  else
+    return 0;
+}
+
+/* Implement targetm.vectorize.builtin_mask_for_store.  */
+static tree
+rs6000_builtin_mask_for_store (void)
+{
+  if (TARGET_ALTIVEC)
+    return altivec_builtin_mask_for_store;
+  else
+    return 0;
+}
+
 /* Handle generic options of the form -mfoo=yes/no.
    NAME is the option name.
    VALUE is the option value.
@@ -7202,6 +7235,48 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
   rtx ret;
   bool success;
 
+  if (fcode == ALTIVEC_BUILTIN_MASK_FOR_LOAD
+      || fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE)
+    {
+      int icode = (int) CODE_FOR_altivec_lvsr;
+      enum machine_mode tmode = insn_data[icode].operand[0].mode;
+      enum machine_mode mode = insn_data[icode].operand[1].mode;
+      tree arg;
+      rtx op, addr, pat;
+
+      if (!TARGET_ALTIVEC)
+       abort ();
+
+      arg = TREE_VALUE (arglist);
+      if (TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
+       abort ();
+      op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL);
+      addr = memory_address (mode, op);
+      if (fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE)
+       op = addr;
+      else
+       {
+         /* For the load case need to negate the address.  */
+         op = gen_reg_rtx (GET_MODE (addr));
+         emit_insn (gen_rtx_SET (VOIDmode, op,
+                        gen_rtx_NEG (GET_MODE (addr), addr)));
+        }
+      op = gen_rtx_MEM (mode, op);
+
+      if (target == 0
+         || GET_MODE (target) != tmode
+         || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+       target = gen_reg_rtx (tmode);
+
+      /*pat = gen_altivec_lvsr (target, op);*/
+      pat = GEN_FCN (icode) (target, op);
+      if (!pat)
+       return 0;
+      emit_insn (pat);
+
+      return target;
+    }
+
   if (TARGET_ALTIVEC)
     {
       ret = altivec_expand_builtin (exp, target, &success);
@@ -7691,6 +7766,9 @@ altivec_init_builtins (void)
     = build_function_type_list (integer_type_node,
                                pcchar_type_node, NULL_TREE);
 
+  tree id;
+  tree decl;
+
   def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4sf", v4sf_ftype_pcfloat,
               ALTIVEC_BUILTIN_LD_INTERNAL_4sf);
   def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4sf", void_ftype_pfloat_v4sf,
@@ -7792,6 +7870,24 @@ altivec_init_builtins (void)
 
       def_builtin (d->mask, d->name, type, d->code);
     }
+
+  /* Initialize target builtin that implements 
+     targetm.vectorize.builtin_mask_for_load.  */
+  id = get_identifier ("__builtin_altivec_mask_for_load");
+  decl = build_decl (FUNCTION_DECL, id, v16qi_ftype_long_pcvoid);
+  DECL_BUILT_IN_CLASS (decl) = BUILT_IN_MD;
+  DECL_FUNCTION_CODE (decl) = ALTIVEC_BUILTIN_MASK_FOR_LOAD;
+  /* Record the decl. Will be used by rs6000_builtin_mask_for_load.  */
+  altivec_builtin_mask_for_load = decl;
+
+  /* Initialize target builtin that implements 
+     targetm.vectorize.builtin_mask_for_store.  */
+  id = get_identifier ("__builtin_altivec_mask_for_store");
+  decl = build_decl (FUNCTION_DECL, id, v16qi_ftype_long_pcvoid);
+  DECL_BUILT_IN_CLASS (decl) = BUILT_IN_MD;
+  DECL_FUNCTION_CODE (decl) = ALTIVEC_BUILTIN_MASK_FOR_STORE;
+  /* Record the decl. Will be used by rs6000_builtin_mask_for_store.  */
+  altivec_builtin_mask_for_store = decl;
 }
 
 static void
index 801d54fd93f7ef0b512f717a63148fb1d75859e3..399f2e22d607c9cb23c67d990a185634c8b25853 100644 (file)
@@ -2822,6 +2822,8 @@ enum rs6000_builtins
   ALTIVEC_BUILTIN_ABS_V8HI,
   ALTIVEC_BUILTIN_ABS_V16QI,
   ALTIVEC_BUILTIN_COMPILETIME_ERROR,
+  ALTIVEC_BUILTIN_MASK_FOR_LOAD,
+  ALTIVEC_BUILTIN_MASK_FOR_STORE,
 
   /* SPE builtins.  */
   SPE_BUILTIN_EVADDW,
index ce597b086e62fcd02c17d607376a4caf32d0f41c..2572b8564103c62263f073260b3917ca7b620e1f 100644 (file)
@@ -1485,7 +1485,9 @@ mem_expr_equal_p (tree expr1, tree expr2)
       && mem_expr_equal_p (TREE_OPERAND (expr1, 1), /* field decl */
                           TREE_OPERAND (expr2, 1));
   
-  if (TREE_CODE (expr1) == INDIRECT_REF)
+  if (TREE_CODE (expr1) == INDIRECT_REF
+      || TREE_CODE (expr1) == ALIGN_INDIRECT_REF
+      || TREE_CODE (expr1) == MISALIGNED_INDIRECT_REF)
     return mem_expr_equal_p (TREE_OPERAND (expr1, 0),
                             TREE_OPERAND (expr2, 0));
 
@@ -1546,8 +1548,19 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
 
   /* We can set the alignment from the type if we are making an object,
      this is an INDIRECT_REF, or if TYPE_ALIGN_OK.  */
-  if (objectp || TREE_CODE (t) == INDIRECT_REF || TYPE_ALIGN_OK (type))
+  if (objectp || TREE_CODE (t) == INDIRECT_REF 
+      || TREE_CODE (t) == ALIGN_INDIRECT_REF 
+      || TYPE_ALIGN_OK (type))
     align = MAX (align, TYPE_ALIGN (type));
+  else 
+    if (TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+      {
+       if (integer_zerop (TREE_OPERAND (t, 1)))
+         /* We don't know anything about the alignment.  */
+         align = BITS_PER_UNIT;
+       else
+         align = tree_low_cst (TREE_OPERAND (t, 1), 1);
+      }
 
   /* If the size is known, we can set that.  */
   if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
@@ -1672,7 +1685,9 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
                 the size we got from the type?  */
            }
          else if (flag_argument_noalias > 1
-                  && TREE_CODE (t2) == INDIRECT_REF
+                  && (TREE_CODE (t2) == INDIRECT_REF 
+                      || TREE_CODE (t2) == ALIGN_INDIRECT_REF
+                      || TREE_CODE (t2) == MISALIGNED_INDIRECT_REF)    
                   && TREE_CODE (TREE_OPERAND (t2, 0)) == PARM_DECL)
            {
              expr = t2;
@@ -1683,7 +1698,9 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
       /* If this is a Fortran indirect argument reference, record the
         parameter decl.  */
       else if (flag_argument_noalias > 1
-              && TREE_CODE (t) == INDIRECT_REF
+              && (TREE_CODE (t) == INDIRECT_REF
+                  || TREE_CODE (t) == ALIGN_INDIRECT_REF
+                  || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
               && TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL)
        {
          expr = t;
@@ -1701,6 +1718,14 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
        size = plus_constant (size, apply_bitpos / BITS_PER_UNIT);
     }
 
+  if (TREE_CODE (t) == ALIGN_INDIRECT_REF)
+    {
+      /* Force EXPR and OFFSE to NULL, since we don't know exactly what
+        we're overlapping.  */
+      offset = NULL;
+      expr = NULL;
+    }
+
   /* Now set the attributes we computed above.  */
   MEM_ATTRS (ref)
     = get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref));
index da8304a970867c1438d239be15d25fe4d3dfae61..96cab626f7b74b6b859befbb8cc2b5515e4b6e1b 100644 (file)
@@ -5829,6 +5829,8 @@ safe_from_p (rtx x, tree exp, int top_p)
            }
          break;
 
+       case MISALIGNED_INDIRECT_REF:
+       case ALIGN_INDIRECT_REF:
        case INDIRECT_REF:
          if (MEM_P (x)
              && alias_sets_conflict_p (MEM_ALIAS_SET (x),
@@ -6745,11 +6747,17 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          return target;
        }
 
+    case MISALIGNED_INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
       {
        tree exp1 = TREE_OPERAND (exp, 0);
        tree orig;
 
+       if (code == MISALIGNED_INDIRECT_REF
+           && !targetm.vectorize.misaligned_mem_ok (mode))
+         abort ();
+
        if (modifier != EXPAND_WRITE)
          {
            tree t;
@@ -6761,6 +6769,14 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
        op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
        op0 = memory_address (mode, op0);
+
+       if (code == ALIGN_INDIRECT_REF)
+         {
+           int align = TYPE_ALIGN_UNIT (type);
+           op0 = gen_rtx_AND (Pmode, op0, GEN_INT (-align));
+           op0 = memory_address (mode, op0);
+         }
+
        temp = gen_rtx_MEM (mode, op0);
 
        orig = REF_ORIGINAL (exp);
@@ -8203,6 +8219,24 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return expand_expr_real (TREE_OPERAND (exp, 0), original_target, tmode,
                               modifier, alt_rtl);
 
+    case REALIGN_LOAD_EXPR:
+      {
+        tree oprnd0 = TREE_OPERAND (exp, 0); 
+        tree oprnd1 = TREE_OPERAND (exp, 1);
+        tree oprnd2 = TREE_OPERAND (exp, 2);
+        rtx op2;
+
+        this_optab = optab_for_tree_code (code, type);
+        expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, 0);
+        op2 = expand_expr (oprnd2, NULL_RTX, VOIDmode, 0);
+        temp = expand_ternary_op (mode, this_optab, op0, op1, op2, 
+                                 target, unsignedp);
+        if (temp == 0)
+          abort ();
+        return temp;
+      }
+
+
     default:
       return lang_hooks.expand_expr (exp, original_target, tmode,
                                     modifier, alt_rtl);
index c762fada3fe34e850063b90d121683bbe6e6dcd0..7049f4f94757b0fd14f8201626f60370c60844c8 100644 (file)
@@ -1990,6 +1990,8 @@ non_lvalue (tree x)
 
   case COMPONENT_REF:
   case INDIRECT_REF:
+  case ALIGN_INDIRECT_REF:
+  case MISALIGNED_INDIRECT_REF:
   case ARRAY_REF:
   case ARRAY_RANGE_REF:
   case BIT_FIELD_REF:
@@ -2466,6 +2468,8 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case INDIRECT_REF:
+       case ALIGN_INDIRECT_REF:
+       case MISALIGNED_INDIRECT_REF:
        case REALPART_EXPR:
        case IMAGPART_EXPR:
          return operand_equal_p (TREE_OPERAND (arg0, 0),
@@ -10478,7 +10482,9 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
   if (TREE_CODE (t) == WITH_SIZE_EXPR)
     t = TREE_OPERAND (t, 0);
 
-  if (TREE_CODE (t) == INDIRECT_REF)
+  /* Note: doesn't apply to ALIGN_INDIRECT_REF */
+  if (TREE_CODE (t) == INDIRECT_REF
+      || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
     {
       t = TREE_OPERAND (t, 0);
       if (TREE_TYPE (t) != ptrtype)
index 273a5fbb5a0b5e94163010545e8d37a8aab63e56..0d39f67ef75ad2bddb753a93d983d31e8c9f8704 100644 (file)
@@ -169,7 +169,9 @@ static const char * const optabs[] =
   "cmpmem_optab[$A] = CODE_FOR_$(cmpmem$a$)",
   "vec_set_optab->handlers[$A].insn_code = CODE_FOR_$(vec_set$a$)",
   "vec_extract_optab->handlers[$A].insn_code = CODE_FOR_$(vec_extract$a$)",
-  "vec_init_optab->handlers[$A].insn_code = CODE_FOR_$(vec_init$a$)" };
+  "vec_init_optab->handlers[$A].insn_code = CODE_FOR_$(vec_init$a$)",
+  "vec_realign_store_optab->handlers[$A].insn_code = CODE_FOR_$(vec_realign_store_$a$)",
+  "vec_realign_load_optab->handlers[$A].insn_code = CODE_FOR_$(vec_realign_load_$a$)" };
 
 static void gen_insn (rtx);
 
index 1bf14a738a36950ec9505890cd4cc835dbc50014..27744bcb6893452f0f52b6f3e0cb626daa00fcb1 100644 (file)
@@ -3052,6 +3052,7 @@ gimplify_addr_expr (tree *expr_p, tree *pre_p, tree *post_p)
   switch (TREE_CODE (op0))
     {
     case INDIRECT_REF:
+    case MISALIGNED_INDIRECT_REF:
     do_indirect_ref:
       /* Check if we are dealing with an expression of the form '&*ptr'.
         While the front end folds away '&*ptr' into 'ptr', these
@@ -3642,6 +3643,8 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          recalculate_side_effects (*expr_p);
          break;
 
+       case ALIGN_INDIRECT_REF:
+       case MISALIGNED_INDIRECT_REF:
        case INDIRECT_REF:
          ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
                               is_gimple_reg, fb_rvalue);
index 0b75a81cd7f548d93086bca0e014ec1a700599c7..abb69700a04a3f121f5da8dacfac0a0b5133fa84 100644 (file)
@@ -286,6 +286,12 @@ optab_for_tree_code (enum tree_code code, tree type)
     case MIN_EXPR:
       return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
 
+    case REALIGN_STORE_EXPR:
+      return vec_realign_store_optab;
+
+    case REALIGN_LOAD_EXPR:
+      return vec_realign_load_optab;
+
     default:
       break;
     }
@@ -313,6 +319,88 @@ optab_for_tree_code (enum tree_code code, tree type)
     }
 }
 \f
+
+/* Generate code to perform an operation specified by TERNARY_OPTAB
+   on operands OP0, OP1 and OP2, with result having machine-mode MODE.
+
+   UNSIGNEDP is for the case where we have to widen the operands
+   to perform the operation.  It says to use zero-extension.
+
+   If TARGET is nonzero, the value
+   is generated there, if it is convenient to do so.
+   In all cases an rtx is returned for the locus of the value;
+   this may or may not be TARGET.  */
+
+rtx
+expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0, 
+                  rtx op1, rtx op2, rtx target, int unsignedp) 
+{
+  int icode = (int) ternary_optab->handlers[(int) mode].insn_code;
+  enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+  enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+  enum machine_mode mode2 = insn_data[icode].operand[3].mode;
+  rtx temp;
+  rtx pat;
+  rtx xop0 = op0, xop1 = op1, xop2 = op2;
+
+  if (ternary_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
+    abort ();
+
+  if (!target
+      || ! (*insn_data[icode].operand[0].predicate) (target, mode))
+    temp = gen_reg_rtx (mode);
+  else
+    temp = target;
+
+  /* In case the insn wants input operands in modes different from
+     those of the actual operands, convert the operands.  It would
+     seem that we don't need to convert CONST_INTs, but we do, so
+     that they're properly zero-extended, sign-extended or truncated
+     for their mode.  */
+
+  if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
+    xop0 = convert_modes (mode0,
+                          GET_MODE (op0) != VOIDmode
+                          ? GET_MODE (op0) 
+                          : mode,
+                          xop0, unsignedp);
+
+  if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
+    xop1 = convert_modes (mode1,
+                          GET_MODE (op1) != VOIDmode
+                          ? GET_MODE (op1)
+                          : mode,
+                          xop1, unsignedp);
+
+  if (GET_MODE (op2) != mode2 && mode2 != VOIDmode)
+    xop2 = convert_modes (mode2,
+                          GET_MODE (op2) != VOIDmode
+                          ? GET_MODE (op2)
+                          : mode,
+                          xop2, unsignedp);
+
+  /* Now, if insn's predicates don't allow our operands, put them into
+     pseudo regs.  */
+  
+  if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0)
+      && mode0 != VOIDmode) 
+    xop0 = copy_to_mode_reg (mode0, xop0);
+  
+  if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1)
+      && mode1 != VOIDmode)
+    xop1 = copy_to_mode_reg (mode1, xop1);
+    
+  if (! (*insn_data[icode].operand[3].predicate) (xop2, mode2)
+      && mode2 != VOIDmode)
+    xop2 = copy_to_mode_reg (mode2, xop2);
+    
+  pat = GEN_FCN (icode) (temp, xop0, xop1, xop2);
+    
+  emit_insn (pat);
+  return temp; 
+}
+
+
 /* Like expand_binop, but return a constant rtx if the result can be
    calculated at compile time.  The arguments and return value are
    otherwise the same as for expand_binop.  */
@@ -4657,6 +4745,8 @@ init_optabs (void)
   vec_extract_optab = init_optab (UNKNOWN);
   vec_set_optab = init_optab (UNKNOWN);
   vec_init_optab = init_optab (UNKNOWN);
+  vec_realign_load_optab = init_optab (UNKNOWN);
+
   /* Conversions.  */
   sext_optab = init_convert_optab (SIGN_EXTEND);
   zext_optab = init_convert_optab (ZERO_EXTEND);
index b5632c770fe9adf9caa3cd73d81f4ce64a50dd95..8e895f203c5b48562a0e4caf21d90b5192630f55 100644 (file)
@@ -228,6 +228,10 @@ enum optab_index
   OTI_vec_extract,
   /* Initialize vector operand.  */
   OTI_vec_init,
+  /* Extract specified elements from vectors, for vector store.  */
+  OTI_vec_realign_store,
+  /* Extract specified elements from vectors, for vector load.  */
+  OTI_vec_realign_load,
 
   OTI_MAX
 };
@@ -330,6 +334,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
 #define vec_set_optab (optab_table[OTI_vec_set])
 #define vec_extract_optab (optab_table[OTI_vec_extract])
 #define vec_init_optab (optab_table[OTI_vec_init])
+#define vec_realign_store_optab (optab_table[OTI_vec_realign_store])
+#define vec_realign_load_optab (optab_table[OTI_vec_realign_load])
 
 /* Conversion optabs have their own table and indexes.  */
 enum convert_optab_index
@@ -405,6 +411,10 @@ extern enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
 
 /* Define functions given in optabs.c.  */
 
+extern rtx expand_ternary_op (enum machine_mode mode, optab ternary_optab, 
+                             rtx op0, rtx op1, rtx op2, rtx target, 
+                             int unsignedp);
+
 /* Expand a binary operation given optab and rtx operands.  */
 extern rtx expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
                         enum optab_methods);
index b4b2ca36fb5191acd84e742fc2c4bc3978447905..32ef01c88442b8cffa2ab81a0b264e260be52f41 100644 (file)
@@ -102,6 +102,18 @@ print_mem_expr (FILE *outfile, tree expr)
       print_mem_expr (outfile, TREE_OPERAND (expr, 0));
       fputs (")", outfile);
     }
+  else if (TREE_CODE (expr) == ALIGN_INDIRECT_REF)
+    {
+      fputs (" (A*", outfile);
+      print_mem_expr (outfile, TREE_OPERAND (expr, 0));
+      fputs (")", outfile);
+    }
+  else if (TREE_CODE (expr) == MISALIGNED_INDIRECT_REF)
+    {
+      fputs (" (M*", outfile);
+      print_mem_expr (outfile, TREE_OPERAND (expr, 0));
+      fputs (")", outfile);
+    }
   else if (TREE_CODE (expr) == RESULT_DECL)
     fputs (" <result>", outfile);
   else
index a77c3be82b1f97f7ee1a041cc5a089521d9fa805..61adf14325a1350969b2755069fbe0710da170aa 100644 (file)
@@ -273,6 +273,17 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    TARGET_SCHED_DFA_NEW_CYCLE,                                 \
    TARGET_SCHED_IS_COSTLY_DEPENDENCE}
 
+#ifndef TARGET_VECTORIZE_MISALIGNED_MEM_OK
+#define TARGET_VECTORIZE_MISALIGNED_MEM_OK default_vect_misaligned_mem_ok
+#endif
+#define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD 0
+#define TARGET_VECTORIZE_BUILTIN_MASK_FOR_STORE 0
+
+#define TARGET_VECTORIZE                                                \
+  {TARGET_VECTORIZE_MISALIGNED_MEM_OK,                                  \
+   TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD,                             \
+   TARGET_VECTORIZE_BUILTIN_MASK_FOR_STORE}
+
 /* In except.c */
 #define TARGET_EH_RETURN_FILTER_MODE  default_eh_return_filter_mode
 
@@ -466,6 +477,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 {                                              \
   TARGET_ASM_OUT,                              \
   TARGET_SCHED,                                        \
+  TARGET_VECTORIZE,                            \
   TARGET_EH_RETURN_FILTER_MODE,                        \
   TARGET_MERGE_DECL_ATTRIBUTES,                        \
   TARGET_MERGE_TYPE_ATTRIBUTES,                        \
index 6824c13562e8d42e442135a65ae134687dd9bbdb..9f766ae18dd2ec27753d05136cdca8a34f6d25c0 100644 (file)
@@ -282,6 +282,23 @@ struct gcc_target
     bool (* is_costly_dependence) (rtx, rtx, rtx, int, int);
   } sched;
 
+  /* Functions relating to vectorization.  */
+  struct vectorize
+  {
+    /* The following member value is a pointer to a function called
+       by the vectorizer, and when expanding a MISALIGNED_INDIREC_REF
+       expression.  If the hook returns true (false) then a move* pattern
+       to/from memory can (cannot) be generated for this mode even if the
+       memory location is unaligned.  */
+    bool (* misaligned_mem_ok) (enum machine_mode);
+
+    /* The following member values are pointers to functions called
+       by the vectorizer, and return the decl of the target builtin
+       function.  */
+    tree (* builtin_mask_for_load) (void);
+    tree (* builtin_mask_for_store) (void);
+  } vectorize;
+
   /* Return machine mode for filter value.  */
   enum machine_mode (* eh_return_filter_mode) (void);
 
index c71707524441dec16fda57065d7fd8a36ecd4602..48690a130cf886ce1ba197fa67a4d7b89f1e9f43 100644 (file)
@@ -268,6 +268,12 @@ default_scalar_mode_supported_p (enum machine_mode mode)
     }
 }
 
+bool
+default_vect_misaligned_mem_ok (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return !STRICT_ALIGNMENT;
+}
+
 bool
 hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false (
        CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
index 4ff0ea36af8d01c3d8e9a3af273a12b42869a412..024a0808e0bc8e05a3b6b492db21616fbee417dc 100644 (file)
@@ -47,6 +47,8 @@ extern void default_unwind_emit (FILE *, rtx);
 
 extern bool default_scalar_mode_supported_p (enum machine_mode);
 
+extern bool default_vect_misaligned_mem_ok (enum machine_mode);
+
 /* These are here, and not in hooks.[ch], because not all users of
    hooks.h include tm.h, and thus we don't have CUMULATIVE_ARGS.  */
 
index fbd76080aec75ce0db97d449e219cb232e1e4044..536ccf5cef8f6a3a6dab9299b9c482e475ca3d18 100644 (file)
@@ -1,3 +1,38 @@
+2004-09-23  Dorit Naishlos <dorit@il.ibm.com>
+
+        * gcc.dg/vect/vect-27.c: Now vectorized on altivec.
+        * gcc.dg/vect/vect-29.c: Now vectorized on altivec.
+        * gcc.dg/vect/vect-48.c: Now vectorized on altivec.
+        * gcc.dg/vect/vect-56.c: Now vectorized on altivec.
+        * gcc.dg/vect/vect-72.c: New test for altivec and sse2.
+        * gcc.dg/vect/vect-77.c: Now vectorized on altivec.
+
+        * gcc.dg/vect/vect-27a.c: New test for altivec and mmx.
+        * gcc.dg/vect/vect-29a.c: New test for altivec and mmx.
+        * gcc.dg/vect/vect-48a.c: New test for altivec and mmx.
+        * gcc.dg/vect/vect-56a.c: New test for altivec and mmx.
+        * gcc.dg/vect/vect-72a.c: New test for altivec and mmx.
+        * gcc.dg/vect/vect-77a.c: New test for altivec and mmx.
+
+        * gcc.dg/vect/vect-13.c: Change to run test instead of compile.
+
+        * gcc.dg/vect/vect-44.c: Check additional cases.
+        * gcc.dg/vect/vect-48.c: Check additional cases.
+
+        * gcc.dg/vect/vect-26.c: Use sse2 instead of sse.
+        * gcc.dg/vect/vect-27.c: Use sse2 instead of sse.
+        * gcc.dg/vect/vect-28.c: Use sse2 instead of sse.
+        * gcc.dg/vect/vect-29.c: Use sse2 instead of sse.
+        * gcc.dg/vect/vect-4?.c: Use sse2 instead of sse.
+        * gcc.dg/vect/vect-75.c: Use sse2 instead of sse.
+        * gcc.dg/vect/vect-76.c: Use sse2 instead of sse.
+        * gcc.dg/vect/vect-77.c: Use sse2 instead of sse.
+        * gcc.dg/vect/vect-78.c: Use sse2 instead of sse.
+
+        * gcc.dg/vect/vect-5?.c: Use sse2 instead of sse. Add return 0.
+        * gcc.dg/vect/vect-60.c: Use sse2 instead of sse. Add return 0.
+        * gcc.dg/vect/vect-61.c: Use sse2 instead of sse. Add return 0.
+
 2004-09-23  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
 
        * gcc.dg/tree-ssa/loop-6.c: New test.
index 21385b40ef846c9be9c14deb6063992391624338..052abe12d182389462de1225bc950f0c178635a2 100644 (file)
@@ -1,25 +1,41 @@
-/* { dg-do compile { target powerpc*-*-* i?86-*-* x86_64-*-* } } */
+/* { dg-do run { target powerpc*-*-* i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
+#include <stdarg.h>
+#include "tree-vect.h"
 
 #define N 16
 
 int a[N];
 int results[N] = {0,1,2,3,0,0,0,0,0,0,0,0,12,13,14,15};
 
-int main ()
+int main1()
 {
   int i;
   int b[N] = {0,1,2,3,-4,-5,-6,-7,-8,-9,-10,-11,12,13,14,15};
 
-  /* Not vectorizable yet (condition in loop).  */
+  /* Max pattern.  */
   for (i = 0; i < N; i++)
     {
       a[i] = (b[i] >= 0 ? b[i] : 0);
     }
 
+  /* Check results  */
+  for (i = 0; i < N; i++)
+    {
+      if (a[i] != results[i])
+       abort ();
+    }
+
   return 0;
 }
 
+int main (void)
+{
+  check_vect ();
+
+  return main1 ();
+}
+
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail i?86-*-* x86_64-*-* } } } */
index bfeb76ece69336e0013955ac23928f480596756b..fd21beddb782792ea7e83cd162a27a0760cc9120 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
index 35e8f418f5fa48446b3b7494d775c77c4828762e..d2e8c9445599fa0f7ee209ef4c44f2f95d850291 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -43,5 +43,5 @@ int main (void)
   return main1 ();
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail i?86-*-* x86_64-*-* } } } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/vect-27a.c b/gcc/testsuite/gcc.dg/vect/vect-27a.c
new file mode 100644 (file)
index 0000000..9dd7549
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -mmmx" { target i?86-*-* x86_64-*-* } } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 128
+
+/* unaligned load.  */
+
+int main1 ()
+{
+  int i;
+  int ia[N];
+  int ib[N+1];
+
+  for (i=0; i < N; i++)
+    {
+      ib[i] = i;
+    }
+
+  for (i = 1; i <= N; i++)
+    {
+      ia[i-1] = ib[i];
+    }
+
+  /* check results:  */
+  for (i = 1; i <= N; i++)
+    {
+      if (ia[i-1] != ib[i])
+        abort ();
+    }
+
+  return 0;
+}
+
+int main (void)
+{ 
+  check_vect ();
+  
+  return main1 ();
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+
index b10cf136e1710b31a33f9d485d95e07f9d5416b3..cb8d7cb0c76592d546bc1e632b0b908fc573a9ed 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
index 80754f5fea55b5224f0a518e7f0668128ea25c75..c0383c7c8a63e08916b9a9ab56fac1470157b6ac 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -46,5 +46,5 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail i?86-*-* x86_64-*-* } } } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/vect-29a.c b/gcc/testsuite/gcc.dg/vect/vect-29a.c
new file mode 100644 (file)
index 0000000..13cd5c9
--- /dev/null
@@ -0,0 +1,50 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -mmmx" { target i?86-*-* x86_64-*-* } } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 128
+#define OFF 3
+
+/* unaligned load.  */
+
+int main1 (int off)
+{
+  int i;
+  int ia[N];
+  int ib[N+OFF];
+
+  for (i = 0; i < N+OFF; i++)
+    {
+      ib[i] = i;
+    }
+
+  for (i = 0; i < N; i++)
+    {
+      ia[i] = ib[i+off];
+    }
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    {
+      if (ia[i] != ib[i+off])
+        abort ();
+    }
+
+  return 0;
+}
+
+int main (void)
+{ 
+  check_vect ();
+  
+  main1 (0); /* aligned */
+  main1 (OFF); /* unaligned */
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+
index e3dd2778adbadf2d2349df659640bedc96d13221..2507575ba13c5d98e4d2bf196e2b85d4df48794e 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
index 0f9cae4ee8fe5d7e6b7b4a64d2eeb7a20beb220c..f54258fab3cc387816944dd35997c3e861956e68 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
index 7f79d42de49c636b6dd9d76c96be93cc8172a6f2..9d40a37113aa109e307e200a9e204daa1de8c9ad 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
index 370b5dd8bb77fcb94ef0413b34d4de7d615b225f..eedef268bd517e4cfa697d60e384d76fe89e752c 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
index 4068ab1d577a369f3d5605e908e0c4db1bebc605..8aab2fe07e136c0249cdd9fa121837c6e9cad526 100644 (file)
@@ -1,13 +1,14 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
 
 #define N 256
 
+typedef float afloat __attribute__ ((__aligned__(16)));
 
 void bar (float *pa, float *pb, float *pc) 
 {
@@ -42,13 +43,17 @@ main1 (float * __restrict__ pa, float * __restrict__ pb, float * __restrict__ pc
 int main (void)
 {
   int i;
-  float a[N];
-  float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
-  float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+  afloat a[N+4];
+  afloat b[N+4] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60,63,66,69};
+  afloat c[N+4] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
 
   check_vect ();
 
   main1 (a,b,c);
+  main1 (&a[1],b,c);
+  main1 (a,&b[1],c);
+  main1 (&a[1],&b[1],&c[1]);
+
   return 0;
 }
 
index c0b0029e12f479cbfd95463a76636821b9ecb5fd..bc5d5c843cb199b2e54cfe3fd9c494fcf7417058 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
index 1fb08a7eab500feda2eb51a1bd307c9ec71558b9..7710c039d50bfddf62b96edbc23913883e5416da 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
index e1e1d38e6b63de6a8f4f52498558b9ae99325d26..ccbcccf880de7ccec7a6ea46488e8336faff51d4 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
index c7485be3a0b06916acd10519adf43bc50f201f40..3dfdb9579376505ba7be679ad891190f4fcb6826 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -43,14 +43,16 @@ main1 (afloat * __restrict__ pa, float * __restrict__ pb, float * __restrict__ p
 int main (void)
 {
   int i;
-  float a[N];
-  float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
-  float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+  afloat a[N];
+  afloat b[N+1] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60};
+  afloat c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
 
   check_vect ();
 
   main1 (a,b,c);
+  main1 (a,&b[1],c);
+
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail i?86-*-* x86_64-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-48a.c b/gcc/testsuite/gcc.dg/vect/vect-48a.c
new file mode 100644 (file)
index 0000000..0422edc
--- /dev/null
@@ -0,0 +1,58 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -mmmx" { target i?86-*-* x86_64-*-* } } */
+  
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 256
+
+typedef short ashort __attribute__ ((__aligned__(16)));
+
+void bar (short *pa, short *pb, short *pc) 
+{
+  int i;
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    {
+      if (pa[i] != (pb[i] + pc[i]))
+       abort ();
+    }
+
+  return;
+}
+
+
+int
+main1 (ashort * __restrict__ pa, short * __restrict__ pb, short * __restrict__ pc)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    {
+      pa[i] = pb[i] + pc[i];
+    }
+
+  bar (pa,pb,pc);
+
+  return 0;
+}
+
+int main (void)
+{
+  int i;
+  ashort a[N];
+  ashort b[N+1] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60};
+  ashort c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+
+  check_vect ();
+
+  main1 (a,b,c);
+  main1 (a,&b[1],c);
+
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
index 8d8b212a66f824ae3b7924c99a61a9621f77f8aa..6a2669956a73df989d2af4aaddf6da2638cb37d5 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
index cd7cf5d4996673b89ed0c85de4c90c160bcec2df..3b952a3a6c11237c8674e9d4a7341bd29dd59236 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -49,6 +49,7 @@ int main (void)
   check_vect ();
 
   main1 (N,a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 65c0f40275455cad40a53581690141ab4441b05c..7804a4c8e8f17c246d117fcd110022c2dc442b8c 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -49,6 +49,7 @@ int main (void)
   check_vect ();
 
   main1 (N,a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 32a584b2a0b03a58ea85ef5df418ea030413f093..60d9b79629600883af326334b26c978aa5327b69 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -51,6 +51,7 @@ int main (void)
 
   main1 (N,a,&b[1],c);
   main1 (N,a,&b[1],&c[1]);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 4b99304caf3419cd6d33e41163ec667c619f88bf..e8f17472be0f3c8928dd66a1aa5e5cd782699b47 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
   
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -51,6 +51,7 @@ int main (void)
 
   main1 (N,a,&b[1],c);
   main1 (N,a,&b[1],&c[1]);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 5ab9e026f423ecc20a12d26ac86f85c81080e843..172feae8d67797cee6c91b667aef018a9023246c 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -50,6 +50,7 @@ int main (void)
   check_vect ();
 
   main1 (a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 2257a2312f338dd4994d51155af419f69195d105..e5c4ba2dbc2a0b7006cef27483c8cdaf46003ba8 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -50,6 +50,7 @@ int main (void)
   check_vect ();
 
   main1 (a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 0e20137bebd5112268ce7ef2823efd800f8a54ac..9170e49cd2fc2a12a1c27c3b70e49199feef06e8 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -50,6 +50,7 @@ int main (void)
   check_vect ();
 
   main1 (a,b,c);
+  return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail i?86-*-* x86_64-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-56a.c b/gcc/testsuite/gcc.dg/vect/vect-56a.c
new file mode 100644 (file)
index 0000000..5d8ed11
--- /dev/null
@@ -0,0 +1,56 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -mmmx" { target i?86-*-* x86_64-*-* } } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 256
+
+typedef short ashort __attribute__ ((__aligned__(16)));
+
+void bar (ashort *pa, ashort *pb, ashort *pc)
+{
+  int i;
+
+  /* check results:  */
+  for (i = 0; i < N/2; i++)
+    {
+      if (pa[i] != (pb[i+1] + pc[i+1]))
+       abort ();
+    }
+
+  return;
+}
+
+
+int
+main1 (ashort * __restrict__ pa, ashort * __restrict__ pb, ashort * __restrict__ pc)
+{
+  int i;
+
+  for (i = 0; i < N/2; i++)
+    {
+      pa[i] = pb[i+1] + pc[i+1];
+    }
+
+  bar (pa,pb,pc);
+
+  return 0;
+}
+
+int main (void)
+{
+  int i;
+  ashort a[N];
+  ashort b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+  ashort c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+
+  check_vect ();
+
+  main1 (a,b,c);
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
index 0e675d7755c9d85c8eb0abcd8fb2641ef58a6a62..ce2e74089a4617c464f1a028a6cfd35a19efb7cf 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -50,6 +50,7 @@ int main (void)
   check_vect ();
 
   main1 (a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 57c27795f1cc51a5d9b3ea726457b281de3e2627..c080c909d1b094a533373cf8c3685086e1ec0f1c 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -51,6 +51,7 @@ int main (void)
   check_vect ();
 
   main1 (n,a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 3dfbe19e988438a758e110b5a667a7137930576d..4bdd7b401a00d8a82618197ea09374f896d4cec6 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -51,6 +51,7 @@ int main (void)
   check_vect ();
 
   main1 (n,a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 276b7e222fb393b6e55574329ccfcb219d1c33d5..e19d36e8fef7767787be69ad297ddc498ee22bd7 100644 (file)
@@ -1,7 +1,8 @@
+
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -51,6 +52,7 @@ int main (void)
   check_vect ();
 
   main1 (n,a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
index 257ef388fc5a81985e14ce0aa00e7c3c228c8b4b..6df22a61c40569e365f5563bc5f8edb987645288 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -51,6 +51,7 @@ int main (void)
   check_vect ();
 
   main1 (n,a,b,c);
+  return 0;
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-72.c b/gcc/testsuite/gcc.dg/vect/vect-72.c
new file mode 100644 (file)
index 0000000..1a2ad07
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 128
+
+/* unaligned load.  */
+
+int main1 ()
+{
+  int i;
+  char ia[N];
+  char ib[N+1];
+
+  for (i=0; i < N+1; i++)
+    {
+      ib[i] = i;
+    }
+
+  for (i = 1; i < N+1; i++)
+    {
+      ia[i-1] = ib[i];
+    }
+
+  /* check results:  */
+  for (i = 1; i <= N; i++)
+    {
+      if (ia[i-1] != ib[i])
+        abort ();
+    }
+
+  return 0;
+}
+
+int main (void)
+{ 
+  check_vect ();
+  
+  return main1 ();
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail i?86-*-* x86_64-*-* } } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-72a.c b/gcc/testsuite/gcc.dg/vect/vect-72a.c
new file mode 100644 (file)
index 0000000..71fda70
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -mmmx" { target i?86-*-* x86_64-*-* } } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 128
+
+/* unaligned load.  */
+
+int main1 ()
+{
+  int i;
+  char ia[N];
+  char ib[N+1];
+
+  for (i=0; i < N+1; i++)
+    {
+      ib[i] = i;
+    }
+
+  for (i = 1; i < N+1; i++)
+    {
+      ia[i-1] = ib[i];
+    }
+
+  /* check results:  */
+  for (i = 1; i <= N; i++)
+    {
+      if (ia[i-1] != ib[i])
+        abort ();
+    }
+
+  return 0;
+}
+
+int main (void)
+{ 
+  check_vect ();
+  
+  return main1 ();
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+
index 5fcb3abad86b8473b0df0adcf4fbfe30316fcfa3..f5fee582d2dc6a244e90a00cd285ba4ca6b1df19 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
index 11b87e325a823ff778324e16365735c9e77c7650..17d6ff7b52f3b7e897cb196af6d81d4da56f226c 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
index c5dacc5a8811da3fc7b6ae61b674702d9c7eeefb..9f5697d60352ed6b52d5bbe83f84c7881555bd78 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
@@ -43,5 +43,5 @@ int main (void)
 }
 
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail i?86-*-* x86_64-*-* } } } */
 
diff --git a/gcc/testsuite/gcc.dg/vect/vect-77a.c b/gcc/testsuite/gcc.dg/vect/vect-77a.c
new file mode 100644 (file)
index 0000000..afa0c49
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do run { target powerpc*-*-* } } */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -mmmx" { target i?86-*-* x86_64-*-* } } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 8
+#define OFF 8
+
+typedef int aint __attribute__ ((__aligned__(16)));
+
+aint ib[N+OFF] = {0, 1, 3, 5, 7, 11, 13, 17, 0, 2, 6, 10, 14, 22, 26, 34};
+
+int main1 (aint *ib, int off)
+{
+  int i;
+  int ia[N];
+
+  for (i = 0; i < N; i++)
+    {
+      ia[i] = ib[i+off];
+    }
+
+
+  /* check results:  */
+  for (i = 0; i < N; i++)
+    {
+     if (ia[i] != ib[i+off])
+        abort ();
+    }
+
+  return 0;
+}
+
+int main (void)
+{
+  check_vect ();
+
+  main1 (ib, 8);
+  return 0;
+}
+
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+
index 6a4eb8c4dc745c15995601c026510dbe0311ecfe..75ad3c2984380e773629d1cc4bd125214066d7e6 100644 (file)
@@ -1,7 +1,7 @@
 /* { dg-do run { target powerpc*-*-* } } */
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -maltivec" { target powerpc*-*-* } } */
-/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse" { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-stats -msse2" { target i?86-*-* x86_64-*-* } } */
 
 #include <stdarg.h>
 #include "tree-vect.h"
index d8d370fc3040ab7087cf2ff301f0e6e9412a748f..fed3bfc4a099d6c22b5bad3e006002505074e45b 100644 (file)
@@ -527,6 +527,8 @@ dequeue_and_dump (dump_info_p di)
     case TRUTH_NOT_EXPR:
     case ADDR_EXPR:
     case INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
+    case MISALIGNED_INDIRECT_REF:
     case CLEANUP_POINT_EXPR:
     case SAVE_EXPR:
     case REALPART_EXPR:
index b7bc7c3221bc451db248a43a6b14d441d9bcffd2..b7ed2edc38797f9605bbeb6cde4c32ce41a2ab5d 100644 (file)
@@ -1767,6 +1767,8 @@ tree_could_trap_p (tree expr)
       return !in_array_bounds_p (expr);
 
     case INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
+    case MISALIGNED_INDIRECT_REF:
       return !TREE_THIS_NOTRAP (expr);
 
     case ASM_EXPR:
index d9fe0205b3ca022a06f7c461cb1de8aa23e6f21f..fe707d5fc542861f2e6d01303372d634cff07167 100644 (file)
@@ -323,7 +323,9 @@ is_gimple_addressable (tree t)
   return (is_gimple_id (t) || handled_component_p (t)
          || TREE_CODE (t) == REALPART_EXPR
          || TREE_CODE (t) == IMAGPART_EXPR
-         || TREE_CODE (t) == INDIRECT_REF);
+         || TREE_CODE (t) == INDIRECT_REF
+         || TREE_CODE (t) == ALIGN_INDIRECT_REF
+         || TREE_CODE (t) == MISALIGNED_INDIRECT_REF);
 }
 
 /* Return true if T is function invariant.  Or rather a restricted
@@ -563,6 +565,8 @@ get_base_address (tree t)
   if (SSA_VAR_P (t)
       || TREE_CODE (t) == STRING_CST
       || TREE_CODE (t) == CONSTRUCTOR
+      || TREE_CODE (t) == MISALIGNED_INDIRECT_REF
+      || TREE_CODE (t) == ALIGN_INDIRECT_REF
       || TREE_CODE (t) == INDIRECT_REF)
     return t;
   else
index 71196fbe78345fd6a6ad8740d68abc6afaf0fea7..0bb2072f71443c03a8803b33394da1105734e804 100644 (file)
@@ -1018,6 +1018,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
     case ADDR_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
+    case ALIGN_INDIRECT_REF:
+    case MISALIGNED_INDIRECT_REF:
     case INDIRECT_REF:
       if (TREE_CODE (node) == ADDR_EXPR
          && (TREE_CODE (TREE_OPERAND (node, 0)) == STRING_CST
@@ -1034,6 +1036,13 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
        }
       else
        dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+
+      if (TREE_CODE (node) == MISALIGNED_INDIRECT_REF)
+        {
+          pp_string (buffer, "{misalignment: ");
+          dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+          pp_character (buffer, '}');
+        }
       break;
 
     case POSTDECREMENT_EXPR:
@@ -1451,6 +1460,16 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       is_stmt = false;
       break;
 
+    case REALIGN_LOAD_EXPR:
+      pp_string (buffer, "REALIGN_LOAD <");
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_string (buffer, ", ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+      pp_string (buffer, ", ");
+      dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
+      pp_string (buffer, ">");
+      break;
+      
     default:
       NIY;
     }
@@ -1710,6 +1729,8 @@ op_prio (tree op)
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
     case NEGATE_EXPR:
+    case ALIGN_INDIRECT_REF:
+    case MISALIGNED_INDIRECT_REF:
     case INDIRECT_REF:
     case ADDR_EXPR:
     case FLOAT_EXPR:
@@ -1838,6 +1859,12 @@ op_symbol (tree op)
     case INDIRECT_REF:
       return "*";
 
+    case ALIGN_INDIRECT_REF:
+      return "A*";
+
+    case MISALIGNED_INDIRECT_REF:
+      return "M*";
+
     case TRUNC_DIV_EXPR:
     case RDIV_EXPR:
       return "/";
index 3d99d94e92ee4187c5e02b770fa1346015e34d73..b0cdddce9682ab754c117f98c849255f9cc7d1bc 100644 (file)
@@ -495,14 +495,16 @@ collect_points_to_info_for (struct alias_info *ai, tree ptr)
 
 
 /* Helper for ptr_is_dereferenced_by.  Called by walk_tree to look for
-   INDIRECT_REF nodes for the pointer passed in DATA.  */
+   (ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA.  */
 
 static tree
 find_ptr_dereference (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
 {
   tree ptr = (tree) data;
 
-  if (TREE_CODE (*tp) == INDIRECT_REF
+  if ((TREE_CODE (*tp) == INDIRECT_REF
+       || TREE_CODE (*tp) == ALIGN_INDIRECT_REF
+       || TREE_CODE (*tp) == MISALIGNED_INDIRECT_REF)
       && TREE_OPERAND (*tp, 0) == ptr)
     return *tp;
 
@@ -510,8 +512,9 @@ find_ptr_dereference (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
 }
 
 
-/* Return true if STMT contains INDIRECT_REF <PTR>.  *IS_STORE is set
-   to 'true' if the dereference is on the LHS of an assignment.  */
+/* Return true if STMT contains (ALIGN/MISALIGNED_)INDIRECT_REF <PTR>.  
+   *IS_STORE is set to 'true' if the dereference is on the LHS of an 
+   assignment.  */
 
 static bool
 ptr_is_dereferenced_by (tree ptr, tree stmt, bool *is_store)
index 80357dcfc277bed1bad58cc6fefcf31f0d4e7149..937a301f523750a4f3fe06db28b581c297546235 100644 (file)
@@ -418,7 +418,9 @@ mark_stmt_if_obviously_necessary (tree stmt, bool aggressive)
          if (is_global_var (lhs))
            mark_stmt_necessary (stmt, true);
        }
-      else if (TREE_CODE (lhs) == INDIRECT_REF)
+      else if (TREE_CODE (lhs) == INDIRECT_REF
+              || TREE_CODE (lhs) == ALIGN_INDIRECT_REF
+              || TREE_CODE (lhs) == MISALIGNED_INDIRECT_REF)
        {
          tree ptr = TREE_OPERAND (lhs, 0);
          struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
index 057e72af6daf485bfcb73ae9e63c22fe8dc28f58..aed07e25f3b4a025c355a28658733ced12e502d6 100644 (file)
@@ -2414,7 +2414,9 @@ record_equivalences_from_stmt (tree stmt,
          t = TREE_OPERAND (t, 0);
 
        /* Now see if this is a pointer dereference.  */
-       if (TREE_CODE (t) == INDIRECT_REF)
+       if (TREE_CODE (t) == INDIRECT_REF
+           || TREE_CODE (t) == ALIGN_INDIRECT_REF
+           || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
           {
            tree op = TREE_OPERAND (t, 0);
 
index de8649173d00111d4abc38efb6c0e5b7aab8b93a..4aafc815b84f19b7e12b2bba46a704bd0e91f562 100644 (file)
@@ -137,6 +137,8 @@ for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
        case SSA_NAME:
          return cbck (*addr_p, addr_p, data);
 
+       case MISALIGNED_INDIRECT_REF:
+       case ALIGN_INDIRECT_REF:
        case INDIRECT_REF:
          nxt = &TREE_OPERAND (*addr_p, 0);
          return cbck (*addr_p, nxt, data);
@@ -1101,7 +1103,9 @@ is_call_clobbered_ref (tree ref)
   if (DECL_P (base))
     return is_call_clobbered (base);
 
-  if (TREE_CODE (base) == INDIRECT_REF)
+  if (TREE_CODE (base) == INDIRECT_REF
+      || TREE_CODE (base) == ALIGN_INDIRECT_REF
+      || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
     {
       /* Check whether the alias tags associated with the pointer
         are call clobbered.  */
index 078e8a36cf9f7f9286d5da1c6d077c0ad2dc08b9..08a962d09325337845198aec2a98f202433520bc 100644 (file)
@@ -1269,7 +1269,9 @@ find_interesting_uses_address (struct ivopts_data *data, tree stmt, tree *op_p)
       || zero_p (step))
     goto fail;
 
-  if (TREE_CODE (base) == INDIRECT_REF)
+  if (TREE_CODE (base) == INDIRECT_REF
+      || TREE_CODE (base) == ALIGN_INDIRECT_REF
+      || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
     base = TREE_OPERAND (base, 0);
   else
     base = build_addr (base);
@@ -1699,7 +1701,9 @@ add_address_candidates (struct ivopts_data *data,
 
       if (base != TREE_OPERAND (iv->base, 0))
        { 
-         if (TREE_CODE (base) == INDIRECT_REF)
+         if (TREE_CODE (base) == INDIRECT_REF
+             || TREE_CODE (base) == ALIGN_INDIRECT_REF
+             || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
            base = TREE_OPERAND (base, 0);
          else
            base = build_addr (base);
@@ -3826,13 +3830,16 @@ unshare_and_remove_ssa_names (tree ref)
 static void
 rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with)
 {
-  tree var = get_base_address (*op), new_var, new_name, copy, name;
+  tree bvar, var, new_var, new_name, copy, name;
   tree orig;
 
+  var = bvar = get_base_address (*op);
+
   if (!var || TREE_CODE (with) != SSA_NAME)
     goto do_rewrite;
-
-  if (TREE_CODE (var) == INDIRECT_REF)
+  if (TREE_CODE (var) == INDIRECT_REF
+      || TREE_CODE (var) == ALIGN_INDIRECT_REF
+      || TREE_CODE (var) == MISALIGNED_INDIRECT_REF)
     var = TREE_OPERAND (var, 0);
   if (TREE_CODE (var) == SSA_NAME)
     {
@@ -3869,12 +3876,20 @@ rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with)
 do_rewrite:
 
   orig = NULL_TREE;
-  if (TREE_CODE (*op) == INDIRECT_REF)
+  if (TREE_CODE (*op) == INDIRECT_REF
+      || TREE_CODE (*op) == ALIGN_INDIRECT_REF
+      || TREE_CODE (*op) == MISALIGNED_INDIRECT_REF)
     orig = REF_ORIGINAL (*op);
   if (!orig)
     orig = unshare_and_remove_ssa_names (*op);
 
-  *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
+  if (TREE_CODE (bvar) == ALIGN_INDIRECT_REF)
+    *op = build1 (ALIGN_INDIRECT_REF, TREE_TYPE (*op), with);
+  else if (TREE_CODE (bvar) == MISALIGNED_INDIRECT_REF)
+    *op = build2 (MISALIGNED_INDIRECT_REF, TREE_TYPE (*op), with, TREE_OPERAND (*op, 1));
+  else
+    *op = build1 (INDIRECT_REF, TREE_TYPE (*op), with);
+
   /* Record the original reference, for purposes of alias analysis.  */
   REF_ORIGINAL (*op) = orig;
 }
index 8c0516998bca3db4c32731d13743f206255ee1eb..55e6f8a14465f42cda1a7dc69fd8617955925104 100644 (file)
@@ -1009,6 +1009,11 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case MISALIGNED_INDIRECT_REF:
+      get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
+      /* fall through */
+
+    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
       get_indirect_ref_operands (stmt, expr, flags);
       return;
@@ -1162,6 +1167,14 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
        return;
       }
 
+    case REALIGN_LOAD_EXPR:
+      {
+       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
+        get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
+        get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags);
+        return;
+      }
+
     case BLOCK:
     case FUNCTION_DECL:
     case EXC_PTR_EXPR:
@@ -1274,7 +1287,8 @@ get_asm_expr_operands (tree stmt)
       }
 }
 
-/* A subroutine of get_expr_operands to handle INDIRECT_REF.  */
+/* A subroutine of get_expr_operands to handle INDIRECT_REF,
+   ALIGN_INDIRECT_REF and MISALIGNED_INDIRECT_REF.  */
 
 static void
 get_indirect_ref_operands (tree stmt, tree expr, int flags)
index 33f68ad56d4c4e06a226866a0c4f8f7becb6e42d..b158278d0fd3618f56e7d495b5a3ffaccc7e1e49 100644 (file)
@@ -179,7 +179,8 @@ static bool vect_compute_data_ref_alignment
 static bool vect_analyze_data_ref_access (struct data_reference *);
 static bool vect_get_first_index (tree, tree *);
 static bool vect_can_force_dr_alignment_p (tree, unsigned int);
-static struct data_reference * vect_analyze_pointer_ref_access (tree, tree, bool);
+static struct data_reference * vect_analyze_pointer_ref_access 
+  (tree, tree, bool);
 static tree vect_get_base_and_bit_offset
   (struct data_reference *, tree, tree, loop_vec_info, tree *, bool*);
 static struct data_reference * vect_analyze_pointer_ref_access
@@ -193,9 +194,11 @@ static tree vect_get_symbl_and_dr
 
 /* Utility functions for the code transformation.  */
 static tree vect_create_destination_var (tree, tree);
-static tree vect_create_data_ref (tree, block_stmt_iterator *);
-static tree vect_create_index_for_vector_ref (struct loop *, block_stmt_iterator *);
-static tree vect_create_addr_base_for_vector_ref (tree, tree *);
+static tree vect_create_data_ref_ptr 
+  (tree, block_stmt_iterator *, tree, tree *, bool); 
+static tree vect_create_index_for_vector_ref 
+  (struct loop *, block_stmt_iterator *);
+static tree vect_create_addr_base_for_vector_ref (tree, tree *, tree);
 static tree get_vectype_for_scalar_type (tree);
 static tree vect_get_new_vect_var (tree, enum vect_var_kind, const char *);
 static tree vect_get_vec_def_for_operand (tree, tree);
@@ -702,8 +705,8 @@ vect_create_index_for_vector_ref (struct loop *loop, block_stmt_iterator *bsi)
 
    Input:
    STMT: The statement containing the data reference.
-   NEW_STMT_LIST: Must be initialized to NULL_TREE or a
-   statement list.
+   NEW_STMT_LIST: Must be initialized to NULL_TREE or a statement list.
+   OFFSET: Optional. If supplied, it is be added to the initial address.
 
    Output:
    1. Return an SSA_NAME whose value is the address of the memory location of the
@@ -715,7 +718,8 @@ vect_create_index_for_vector_ref (struct loop *loop, block_stmt_iterator *bsi)
 
 static tree
 vect_create_addr_base_for_vector_ref (tree stmt,
-                                      tree *new_stmt_list)
+                                      tree *new_stmt_list,
+                                     tree offset)
 {
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
   struct loop *loop = STMT_VINFO_LOOP (stmt_info);
@@ -776,7 +780,8 @@ vect_create_addr_base_for_vector_ref (tree stmt,
 
       dest = create_tmp_var (TREE_TYPE (data_ref_base), "dataref");
       add_referenced_tmp_var (dest);
-      data_ref_base  = force_gimple_operand (data_ref_base, &new_stmt, false, dest);  
+      data_ref_base = 
+       force_gimple_operand (data_ref_base, &new_stmt, false, dest);  
       append_to_statement_list_force (new_stmt, new_stmt_list);
 
       vec_stmt = fold_convert (scalar_array_ptr_type, data_ref_base);
@@ -794,6 +799,17 @@ vect_create_addr_base_for_vector_ref (tree stmt,
   init_val = force_gimple_operand (init_oval, &new_stmt, false, dest);  
   append_to_statement_list_force (new_stmt, new_stmt_list);
 
+  if (offset)
+    {
+      tree tmp = create_tmp_var (TREE_TYPE (init_val), "offset");
+      add_referenced_tmp_var (tmp);
+      vec_stmt = build2 (PLUS_EXPR, TREE_TYPE (init_val), init_val, offset);
+      vec_stmt = build2 (MODIFY_EXPR, TREE_TYPE (init_val), tmp, vec_stmt);
+      init_val = make_ssa_name (tmp, vec_stmt);
+      TREE_OPERAND (vec_stmt, 0) = init_val;
+      append_to_statement_list_force (vec_stmt, new_stmt_list);
+    }
+
   array_ref = build4 (ARRAY_REF, scalar_type, array_base, init_val, 
                      NULL_TREE, NULL_TREE);
   addr_base = build_fold_addr_expr (array_ref);
@@ -806,6 +822,7 @@ vect_create_addr_base_for_vector_ref (tree stmt,
   new_temp = make_ssa_name (addr_expr, vec_stmt);
   TREE_OPERAND (vec_stmt, 0) = new_temp;
   append_to_statement_list_force (vec_stmt, new_stmt_list);
+
   return new_temp;
 }
 
@@ -856,31 +873,56 @@ vect_align_data_ref (tree stmt)
 }
 
 
-/* Function vect_create_data_ref.
+/* Function vect_create_data_ref_ptr.
 
    Create a memory reference expression for vector access, to be used in a
-   vector load/store stmt.
+   vector load/store stmt. The reference is based on a new pointer to vector
+   type (vp).
 
    Input:
-   STMT: a stmt that references memory. expected to be of the form
-        MODIFY_EXPR <name, data-ref> or MODIFY_EXPR <data-ref, name>.
-   BSI: block_stmt_iterator where new stmts can be added.
+   1. STMT: a stmt that references memory. Expected to be of the form
+         MODIFY_EXPR <name, data-ref> or MODIFY_EXPR <data-ref, name>.
+   2. BSI: block_stmt_iterator where new stmts can be added.
+   3. 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
+        pointing to the initial address.
 
    Output:
-   1. Declare a new ptr to vector_type, and have it point to the array base.
-      For example, for vector of type V8HI:
-      v8hi *p0;
-      p0 = (v8hi *)&a;
-   2. Create a data-reference based on the new vector pointer p0, and using
-      a new index variable 'idx'. Return the expression '(*p0)[idx]'.
+   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;
+
+      if OFFSET is not supplied:
+         initial_address = &a[init];
+      if OFFSET is supplied:
+         initial_address = &a[init + OFFSET];
+
+      Return the initial_address in INITIAL_ADDRESS.
+
+   2. Create a data-reference in the loop based on the new vector pointer vp,
+      and using a new index variable 'idx' as follows:
+
+      vp' = vp + update
+
+      where if ONLY_INIT is true:
+         update = zero
+      and otherwise
+         update = idx + vector_type_size
+
+      Return the pointer vp'.
+
 
    FORNOW: handle only aligned and consecutive accesses.  */
 
 static tree
-vect_create_data_ref (tree stmt, block_stmt_iterator *bsi)
+vect_create_data_ref_ptr (tree stmt, block_stmt_iterator *bsi, tree offset,
+                          tree *initial_address, bool only_init)
 {
-  tree base_name, data_ref_base, data_ref_base_type;
-  tree array_type;
+  tree base_name;
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
   struct loop *loop = STMT_VINFO_LOOP (stmt_info);
@@ -897,55 +939,44 @@ vect_create_data_ref (tree stmt, block_stmt_iterator *bsi)
   tree vec_stmt;
   tree new_stmt_list = NULL_TREE;
   tree idx;
-  tree new_base;
-  tree data_ref;
-  edge pe;
+  edge pe = loop_preheader_edge (loop);
   basic_block new_bb;
-
-  /* FORNOW: make sure the data reference is aligned.  */
-  vect_align_data_ref (stmt);
+  tree vect_ptr_init;
+  tree vectype_size;
+  tree ptr_update;
+  tree data_ref_ptr;
 
   base_name = unshare_expr (DR_BASE_NAME (dr));
-  data_ref_base = STMT_VINFO_VECT_DR_BASE (stmt_info);
-  data_ref_base_type = TREE_TYPE (data_ref_base);
-
-  array_type = build_array_type (vectype, 0);
-  TYPE_ALIGN (array_type) = TYPE_ALIGN (data_ref_base_type);
-  vect_ptr_type = build_pointer_type (array_type);
-
   if (vect_debug_details (NULL))
     {
+      tree data_ref_base = base_name;
       fprintf (dump_file, "create array_ref of type: ");
       print_generic_expr (dump_file, vectype, TDF_SLIM);
-    }
-
-  /* Create: vectype *p;  */
-  vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var, 
-                                   get_name (base_name));
-  add_referenced_tmp_var (vect_ptr);
-
-  if (vect_debug_details (NULL))
-    {
       if (TREE_CODE (data_ref_base) == VAR_DECL)
-       fprintf (dump_file, "vectorizing a one dimensional array ref: ");
+        fprintf (dump_file, "vectorizing a one dimensional array ref: ");
       else if (TREE_CODE (data_ref_base) == ARRAY_REF)
-       fprintf (dump_file, "vectorizing a multidimensional array ref: ");
+        fprintf (dump_file, "vectorizing a multidimensional array ref: ");
       else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
-       fprintf (dump_file, "vectorizing a record based array ref: ");
+        fprintf (dump_file, "vectorizing a record based array ref: ");
       else if (TREE_CODE (data_ref_base) == SSA_NAME)
-       fprintf (dump_file, "vectorizing a pointer ref: ");
-      else if (TREE_CODE (data_ref_base) == ADDR_EXPR
-              || TREE_CODE (data_ref_base) == PLUS_EXPR
-              || TREE_CODE (data_ref_base) == MINUS_EXPR)
-       fprintf (dump_file, "vectorizing an address expr: ");
+        fprintf (dump_file, "vectorizing a pointer ref: ");
       print_generic_expr (dump_file, base_name, TDF_SLIM);
     }
 
-  /* Handle aliasing:  */
+  /** (1) Create the new vector-pointer variable:  **/
+
+  vect_ptr_type = build_pointer_type (vectype);
+  vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
+                                    get_name (base_name));
+  add_referenced_tmp_var (vect_ptr);
+  
+  
+  /** (2) Handle aliasing information of the new vector-pointer:  **/
+  
   tag = STMT_VINFO_MEMTAG (stmt_info);
   gcc_assert (tag);
   get_var_ann (vect_ptr)->type_mem_tag = tag;
-
+  
   /* Mark for renaming all aliased variables
      (i.e, the may-aliases of the type-mem-tag).  */
   nvuses = NUM_VUSES (vuses);
@@ -969,36 +1000,56 @@ vect_create_data_ref (tree stmt, block_stmt_iterator *bsi)
       if (TREE_CODE (def) == SSA_NAME)
         bitmap_set_bit (vars_to_rename, var_ann (SSA_NAME_VAR (def))->uid);
     }
-  
-  pe = loop_preheader_edge (loop);
 
-  /* Create: (&(base[init_val]) */
-  new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list);
 
-  pe = loop_preheader_edge (loop); 
-  new_bb = bsi_insert_on_edge_immediate (pe, new_stmt_list); 
-  gcc_assert (!new_bb); 
+  /** (3) Calculate the initial address the vector-pointer, and set
+          the vector-pointer to point to it before the loop:  **/
+
+  /* Create: (&(base[init_val+offset]) in the loop preheader.  */
+  new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list,
+                                                   offset);
+  pe = loop_preheader_edge (loop);
+  new_bb = bsi_insert_on_edge_immediate (pe, new_stmt_list);
+  gcc_assert (!new_bb);
+  *initial_address = new_temp;
 
-  /* p = (vectype_array *) addr_base  */
+  /* Create: p = (vectype *) initial_base  */
   vec_stmt = fold_convert (vect_ptr_type, new_temp);
   vec_stmt = build2 (MODIFY_EXPR, void_type_node, vect_ptr, vec_stmt);
   new_temp = make_ssa_name (vect_ptr, vec_stmt);
   TREE_OPERAND (vec_stmt, 0) = new_temp;
-  new_bb = bsi_insert_on_edge_immediate (pe, vec_stmt); 
-  gcc_assert (!new_bb); 
+  new_bb = bsi_insert_on_edge_immediate (pe, vec_stmt);
+  gcc_assert (!new_bb);
+  vect_ptr_init = TREE_OPERAND (vec_stmt, 0);
+
+
+  /** (4) Handle the updating of the vector-pointer inside the loop: **/
+
+  if (only_init) /* No update in loop is required.  */
+    return vect_ptr_init;
 
-  /*** create data ref: '(*p)[idx]' ***/
   idx = vect_create_index_for_vector_ref (loop, bsi);
-  new_base = build_fold_indirect_ref (new_temp);
-  data_ref = build4 (ARRAY_REF, vectype, new_base, idx, NULL_TREE, NULL_TREE);
 
-  if (vect_debug_details (NULL))
-    {
-      fprintf (dump_file, "created new data-ref: ");
-      print_generic_expr (dump_file, data_ref, TDF_SLIM);
-    }
+  /* Create: update = idx * vectype_size  */
+  ptr_update = create_tmp_var (integer_type_node, "update");
+  add_referenced_tmp_var (ptr_update);
+  vectype_size = build_int_cst (integer_type_node,
+                                GET_MODE_SIZE (TYPE_MODE (vectype)));
+  vec_stmt = build2 (MULT_EXPR, integer_type_node, idx, vectype_size);
+  vec_stmt = build2 (MODIFY_EXPR, void_type_node, ptr_update, vec_stmt);
+  new_temp = make_ssa_name (ptr_update, vec_stmt);
+  TREE_OPERAND (vec_stmt, 0) = new_temp;
+  bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
 
-  return data_ref;
+  /* Create: data_ref_ptr = vect_ptr_init + update  */
+  vec_stmt = build2 (PLUS_EXPR, vect_ptr_type, vect_ptr_init, new_temp);
+  vec_stmt = build2 (MODIFY_EXPR, void_type_node, vect_ptr, vec_stmt);
+  new_temp = make_ssa_name (vect_ptr, vec_stmt);
+  TREE_OPERAND (vec_stmt, 0) = new_temp;
+  bsi_insert_before (bsi, vec_stmt, BSI_SAME_STMT);
+  data_ref_ptr = TREE_OPERAND (vec_stmt, 0);
+
+  return data_ref_ptr;
 }
 
 
@@ -1220,8 +1271,8 @@ vect_finish_stmt_generation (tree stmt, tree vec_stmt, block_stmt_iterator *bsi)
 
   /* Make sure bsi points to the stmt that is being vectorized.  */
 
-  /* Assumption: any stmts created for the vectorization of smtmt S are
-     inserted before S. BSI may point to S or some new stmt before it.  */
+  /* Assumption: any stmts created for the vectorization of stmt S were
+     inserted before S. BSI is expected to point to S or some new stmt before S.  */
 
   while (stmt != bsi_stmt (*bsi) && !bsi_end_p (*bsi))
     bsi_next (bsi);
@@ -1424,6 +1475,7 @@ vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   struct loop *loop = STMT_VINFO_LOOP (stmt_info);
   enum machine_mode vec_mode;
+  tree dummy;
 
   /* Is vectorizable store? */
 
@@ -1452,6 +1504,9 @@ vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
   if (!STMT_VINFO_DATA_REF (stmt_info))
     return false;
 
+  if (!aligned_access_p (STMT_VINFO_DATA_REF (stmt_info)))
+    return false;
+
   if (!vec_stmt) /* transformation not required.  */
     {
       STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
@@ -1467,7 +1522,10 @@ vectorizable_store (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
   vec_oprnd1 = vect_get_vec_def_for_operand (op, stmt);
 
   /* Handle def.  */
-  data_ref = vect_create_data_ref (stmt, bsi);
+  /* FORNOW: make sure the data reference is aligned.  */
+  vect_align_data_ref (stmt);
+  data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, &dummy, false);
+  data_ref = build_fold_indirect_ref (data_ref);
 
   /* Arguments are ready. create the new vector stmt.  */
   *vec_stmt = build2 (MODIFY_EXPR, vectype, data_ref, vec_oprnd1);
@@ -1493,9 +1551,17 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
   tree data_ref = NULL;
   tree op;
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+  struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   tree new_temp;
-  enum machine_mode vec_mode;
+  int mode;
+  tree init_addr;
+  tree new_stmt;
+  tree dummy;
+  basic_block new_bb;
+  struct loop *loop = STMT_VINFO_LOOP (stmt_info);
+  edge pe = loop_preheader_edge (loop);
+  bool software_pipeline_loads_p = false;
 
   /* Is vectorizable load? */
 
@@ -1513,11 +1579,31 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
   if (!STMT_VINFO_DATA_REF (stmt_info))
     return false;
 
-  vec_mode = TYPE_MODE (vectype);
+  mode = (int) TYPE_MODE (vectype);
+
   /* FORNOW. In some cases can vectorize even if data-type not supported
-     (e.g. - data copies).  */
-  if (mov_optab->handlers[(int)vec_mode].insn_code == CODE_FOR_nothing)
-    return false;
+    (e.g. - data copies).  */
+  if (mov_optab->handlers[mode].insn_code == CODE_FOR_nothing)
+    {
+      if (vect_debug_details (loop))
+       fprintf (dump_file, "Aligned load, but unsupported type.");
+      return false;
+    }
+
+  if (!aligned_access_p (dr))
+    {
+      if (vec_realign_load_optab->handlers[mode].insn_code != CODE_FOR_nothing
+         && (!targetm.vectorize.builtin_mask_for_load
+             || targetm.vectorize.builtin_mask_for_load ()))
+       software_pipeline_loads_p = true;
+      else if (!targetm.vectorize.misaligned_mem_ok (mode))
+       {
+         /* Possibly unaligned access, and can't sofware pipeline the loads  */
+         if (vect_debug_details (loop))
+           fprintf (dump_file, "Arbitrary load not supported.");
+         return false;
+       }
+    }
 
   if (!vec_stmt) /* transformation not required.  */
     {
@@ -1530,19 +1616,130 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt)
   if (vect_debug_details (NULL))
     fprintf (dump_file, "transform load.");
 
-  /* Handle def.  */
-  vec_dest = vect_create_destination_var (scalar_dest, vectype);
+  if (!software_pipeline_loads_p)
+    {
+      /* Create:
+         p = initial_addr;
+         indx = 0;
+         loop {
+           vec_dest = *(p);
+           indx = indx + 1;
+         }
+      */
+
+      vec_dest = vect_create_destination_var (scalar_dest, vectype);
+      data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, &dummy, false);
+      if (aligned_access_p (dr))
+        data_ref = build_fold_indirect_ref (data_ref);
+      else
+       {
+         int mis = DR_MISALIGNMENT (dr);
+         tree tmis = (mis == -1 ?
+                      integer_zero_node : 
+                      build_int_cst (integer_type_node, mis));
+         tmis = int_const_binop (MULT_EXPR, tmis, 
+                       build_int_cst (integer_type_node, BITS_PER_UNIT), 1);
+         data_ref = build2 (MISALIGNED_INDIRECT_REF, vectype, data_ref, tmis);
+       }
+      new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
+      new_temp = make_ssa_name (vec_dest, new_stmt);
+      TREE_OPERAND (new_stmt, 0) = new_temp;
+      vect_finish_stmt_generation (stmt, new_stmt, bsi);
+    }
+  else /* software-pipeline the loads  */
+    {
+      /* Create:
+        p1 = initial_addr;
+        msq_init = *(floor(p1))
+        p2 = initial_addr + VS - 1;
+        magic = have_builtin ? builtin_result : initial_address;
+        indx = 0;
+        loop {
+          p2' = p2 + indx * vectype_size
+          lsq = *(floor(p2'))
+          vec_dest = realign_load (msq, lsq, magic)
+          indx = indx + 1;
+          msq = lsq;
+        }
+      */
+
+      tree offset;
+      tree magic;
+      tree phi_stmt;
+      tree msq_init;
+      tree msq, lsq;
+      tree dataref_ptr;
+      tree params;
+
+      /* <1> Create msq_init = *(floor(p1)) in the loop preheader  */
+      vec_dest = vect_create_destination_var (scalar_dest, vectype);
+      data_ref = vect_create_data_ref_ptr (stmt, bsi, NULL_TREE, 
+                                          &init_addr, true);
+      data_ref = build1 (ALIGN_INDIRECT_REF, vectype, data_ref);
+      new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
+      new_temp = make_ssa_name (vec_dest, new_stmt);
+      TREE_OPERAND (new_stmt, 0) = new_temp;
+      new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
+      gcc_assert (!new_bb);
+      msq_init = TREE_OPERAND (new_stmt, 0);
+
+
+      /* <2> Create lsq = *(floor(p2')) in the loop  */ 
+      offset = build_int_cst (integer_type_node, 
+                             GET_MODE_NUNITS (TYPE_MODE (vectype)));
+      offset = int_const_binop (MINUS_EXPR, offset, integer_one_node, 1);
+      vec_dest = vect_create_destination_var (scalar_dest, vectype);
+      dataref_ptr = vect_create_data_ref_ptr (stmt, bsi, offset, &dummy, false);
+      data_ref = build1 (ALIGN_INDIRECT_REF, vectype, dataref_ptr);
+      new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
+      new_temp = make_ssa_name (vec_dest, new_stmt);
+      TREE_OPERAND (new_stmt, 0) = new_temp;
+      vect_finish_stmt_generation (stmt, new_stmt, bsi);
+      lsq = TREE_OPERAND (new_stmt, 0);
+
+
+      /* <3> */
+      if (targetm.vectorize.builtin_mask_for_load)
+       {
+         /* Create permutation mask, if required, in loop preheader.  */
+         tree builtin_decl;
+         params = build_tree_list (NULL_TREE, init_addr);
+         vec_dest = vect_create_destination_var (scalar_dest, vectype);
+         builtin_decl = targetm.vectorize.builtin_mask_for_load ();
+         new_stmt = build_function_call_expr (builtin_decl, params);
+         new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, new_stmt);
+         new_temp = make_ssa_name (vec_dest, new_stmt);
+         TREE_OPERAND (new_stmt, 0) = new_temp;
+         new_bb = bsi_insert_on_edge_immediate (pe, new_stmt);
+         gcc_assert (!new_bb);
+         magic = TREE_OPERAND (new_stmt, 0);
+       }
+      else
+       {
+         /* Use current address instead of init_addr for reduced reg pressure.  */
+         magic = dataref_ptr;
+       }
 
-  /* Handle use.  */
-  op = TREE_OPERAND (stmt, 1);
-  data_ref = vect_create_data_ref (stmt, bsi);
 
-  /* Arguments are ready. create the new vector stmt.  */
-  *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, data_ref);
-  new_temp = make_ssa_name (vec_dest, *vec_stmt);
-  TREE_OPERAND (*vec_stmt, 0) = new_temp;
-  vect_finish_stmt_generation (stmt, *vec_stmt, bsi);
+      /* <4> Create msq = phi <msq_init, lsq> in loop  */ 
+      vec_dest = vect_create_destination_var (scalar_dest, vectype);
+      msq = make_ssa_name (vec_dest, NULL_TREE);
+      phi_stmt = create_phi_node (msq, loop->header); /* CHECKME */
+      SSA_NAME_DEF_STMT (msq) = phi_stmt;
+      add_phi_arg (&phi_stmt, msq_init, loop_preheader_edge (loop));
+      add_phi_arg (&phi_stmt, lsq, loop_latch_edge (loop));
+
 
+      /* <5> Create <vec_dest = realign_load (msq, lsq, magic)> in loop  */
+      vec_dest = vect_create_destination_var (scalar_dest, vectype);
+      new_stmt = build3 (REALIGN_LOAD_EXPR, vectype, msq, lsq, magic);
+      new_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, new_stmt);
+      new_temp = make_ssa_name (vec_dest, new_stmt); 
+      TREE_OPERAND (new_stmt, 0) = new_temp;
+      vect_finish_stmt_generation (stmt, new_stmt, bsi);
+    }
+
+  *vec_stmt = new_stmt;
   return true;
 }
 
@@ -2726,7 +2923,7 @@ vect_compute_data_refs_alignment (loop_vec_info loop_vinfo)
    FOR NOW: No transformation is actually performed. TODO.  */
 
 static void
-vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo ATTRIBUTE_UNUSED)
+vect_enhance_data_refs_alignment (loop_vec_info loop_info ATTRIBUTE_UNUSED)
 {
   /*
      This pass will require a cost model to guide it whether to apply peeling 
@@ -2824,7 +3021,8 @@ static bool
 vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
 {
   varray_type loop_write_datarefs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
-  varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
+  /*varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);*/
+
   unsigned int i;
 
   if (vect_debug_details (NULL))
@@ -2864,6 +3062,11 @@ vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
        }
     }
 
+  /* The vectorizer now supports misaligned loads, so we don't fail anymore
+     in the presence of a misaligned read dataref.  For some targets however
+     it may be preferable not to vectorize in such a case as misaligned
+     accesses are very costly.  This should be considered in the future.  */
+/*
   for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_datarefs); i++)
     {
       struct data_reference *dr = VARRAY_GENERIC_PTR (loop_read_datarefs, i);
@@ -2875,6 +3078,7 @@ vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
          return false;
        }
     }
+*/
 
   return true;
 }
@@ -3158,7 +3362,6 @@ vect_get_symbl_and_dr (tree memref, tree stmt, bool is_read,
 
     case ARRAY_REF:
       offset = size_zero_node;
-      array_base = TREE_OPERAND (memref, 0);
 
       /* Store the array base in the stmt info. 
         For one dimensional array ref a[i], the base is a,
index 405ecb24df2dd3f0477a7cdaf02ed4156de2e262..37c57067914d73416ff97588f5c9e23467ebbe28 100644 (file)
@@ -119,6 +119,7 @@ vinfo_for_stmt (tree stmt)
 /* Info on data references alignment.                              */
 /*-----------------------------------------------------------------*/
 
+/* The misalignment of the memory access in bytes.  */
 #define DR_MISALIGNMENT(DR)   (DR)->aux
 
 static inline bool
index 98ab92411f51e82c7f3eab0292d7651126b0c88a..a0cb800470fd7d441fb315d110a2246c06da6920 100644 (file)
@@ -1493,6 +1493,8 @@ staticp (tree arg)
     case BIT_FIELD_REF:
       return NULL;
 
+    case MISALIGNED_INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
       return TREE_CONSTANT (TREE_OPERAND (arg, 0)) ? arg : NULL;
 
@@ -2412,6 +2414,8 @@ build1_stat (enum tree_code code, tree type, tree node MEM_STAT_DECL)
       TREE_READONLY (t) = 0;
       break;
 
+    case MISALIGNED_INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
     case INDIRECT_REF:
       /* Whether a dereference is readonly has nothing to do with whether
         its operand is readonly.  */
index fa58abafad7e9179a23993ee37174194f8357bac..4c1f9861f9ddf4788d8e422546bc428aa3548af2 100644 (file)
@@ -366,6 +366,17 @@ DEFTREECODE (BIT_FIELD_REF, "bit_field_ref", tcc_reference, 3)
 /* C unary `*' or Pascal `^'.  One operand, an expression for a pointer.  */
 DEFTREECODE (INDIRECT_REF, "indirect_ref", tcc_reference, 1)
 
+/* Like above, but aligns the referenced address (i.e, if the address
+   in P is not aligned on TYPE_ALIGN boundary, then &(*P) != P).  */
+DEFTREECODE (ALIGN_INDIRECT_REF, "align_indirect_ref", tcc_reference, 1)
+
+/* Same as INDIRECT_REF, but also specifies the alignment of the referenced
+   address:
+   Operand 0 is the referenced address (a pointer);
+   Operand 1 is an INTEGER_CST which represents the alignment of the address,
+   or 0 if the alignment is unknown.  */
+DEFTREECODE (MISALIGNED_INDIRECT_REF, "misaligned_indirect_ref", tcc_reference, 2)
+
 /* Array indexing.
    Operand 0 is the array; operand 1 is a (single) array index.
    Operand 2, if present, is a copy of TYPE_MIN_VALUE of the index.
@@ -886,6 +897,28 @@ DEFTREECODE (TREE_BINFO, "tree_binfo", tcc_exceptional, 0)
    Operand 1 is the size of the type in the expression.  */
 DEFTREECODE (WITH_SIZE_EXPR, "with_size_expr", tcc_expression, 2)
 
+/* Extract elements from two input vectors Operand 0 and Operand 1
+   size VS, according to the offset OFF defined by Operand 2 as
+   follows:
+   If OFF > 0, the last VS - OFF elements of vector OP0 are concatenated to
+   the first OFF elements of the vector OP1.
+   If OFF == 0, then the returned vector is OP1.
+   On different targets OFF may take different forms; It can be an address, in 
+   which case its low log2(VS)-1 bits define the offset, or it can be a mask 
+   generated by the builtin targetm.vectorize.mask_for_load_builtin_decl.  */
+DEFTREECODE (REALIGN_LOAD_EXPR, "realign_load", tcc_expression, 3)
+
+/* Extract elements from two input vectors Operand 0 and Operand 1
+   size VS, according to the offset OFF defined by Operand 2 as
+   follows:
+   If OFF > 0, the last OFF elements of vector OP0 are concatenated to
+   the first VS - OFF elements of the vector OP1.
+   If OFF == 0, then the returned vector is OP0.
+   On different targets OFF may take different forms; It can be an address, in 
+   which case its low log2(VS)-1 bits define the offset, or it can be a mask 
+   generated by the builtin targetm.vectorize.mask_for_store_builtin_decl.  */
+DEFTREECODE (REALIGN_STORE_EXPR, "realign_store", tcc_expression, 3)
+
 /*
 Local variables:
 mode:c
index db2a4fb5fc49315fed9a0a0b3dc03474b229df77..a913d74c589af5a87a24c3a64664312d9db3096c 100644 (file)
@@ -390,7 +390,7 @@ struct tree_common GTY(())
           ..._TYPE
 
        TREE_THIS_NOTRAP in
-          INDIRECT_REF, ARRAY_REF, ARRAY_RANGE_REF
+          (ALIGN/MISALIGNED_)INDIRECT_REF, ARRAY_REF, ARRAY_RANGE_REF
 
    deprecated_flag:
 
@@ -901,7 +901,8 @@ extern void tree_operand_check_failed (int, enum tree_code,
 /* Nonzero means this node will not trap.  In an INDIRECT_REF, means
    accessing the memory pointed to won't generate a trap.  However,
    this only applies to an object when used appropriately: it doesn't
-   mean that writing a READONLY mem won't trap.
+   mean that writing a READONLY mem won't trap. Similarly for
+   ALIGN_INDIRECT_REF and MISALIGNED_INDIRECT_REF.
 
    In ARRAY_REF and ARRAY_RANGE_REF means that we know that the index
    (or slice of the array) always belongs to the range of the array.
@@ -1145,8 +1146,9 @@ struct tree_vec GTY(())
 #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
 #define TREE_COMPLEXITY(NODE) (EXPR_CHECK (NODE)->exp.complexity)
 
-/* In INDIRECT_REF.  */
-#define REF_ORIGINAL(NODE) TREE_CHAIN (TREE_CHECK (NODE, INDIRECT_REF))
+/* In INDIRECT_REF, ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF.  */
+#define REF_ORIGINAL(NODE) TREE_CHAIN (TREE_CHECK3 (NODE,      \
+       INDIRECT_REF, ALIGN_INDIRECT_REF, MISALIGNED_INDIRECT_REF))
 
 /* In a LABELED_BLOCK_EXPR node.  */
 #define LABELED_BLOCK_LABEL(NODE) \