tree.def (ALIGN_INDIRECT_REF, [...]): New tree-codes.

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
This commit is contained in:
Dorit Naishlos 2004-09-23 14:34:35 +00:00 committed by Dorit Nuzman
parent d31012b7f8
commit 7ccf35ed17
72 changed files with 1399 additions and 168 deletions

View 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.

View 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

View 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)
}
/* 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.

View File

@ -1902,6 +1902,27 @@
"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.
@ -2062,3 +2083,40 @@
"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")])

View 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

View 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,

View 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));

View 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);

View 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)

View 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);

View 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);

View 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)
}
}
/* 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);

View 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);

View 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

View 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, \

View 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);

View 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,

View 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. */

View 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.

View 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-*-* } } } */

View 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"

View 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-*-* } } } */

View File

@ -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" } } */

View 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"

View 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-*-* } } } */

View File

@ -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" } } */

View 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"

View 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"

View 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"

View 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"

View 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;
}

View 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"

View 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"

View 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"

View 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-*-* } } } */

View File

@ -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" } } */

View 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"

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View 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-*-* } } } */

View File

@ -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" } } */

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View 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 *-*-* } } } */

View File

@ -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-*-* } } } */

View File

@ -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" } } */

View 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"

View 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"

View 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-*-* } } } */

View File

@ -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" } } */

View 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"

View 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:

View 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:

View 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

View 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 "/";

View 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)

View 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);

View 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);

View 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. */

View 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;
}

View 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)

View 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);
}
/** (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;
/* 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);
/* 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;
}
*/
/* Handle use. */
op = TREE_OPERAND (stmt, 1);
data_ref = vect_create_data_ref (stmt, bsi);
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;
}
*/
/* 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);
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;
}
/* <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,

View 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

View 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. */

View 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

View 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) \