Commit 52639a61 by Richard Biener Committed by Richard Biener

re PR tree-optimization/66917 (ARM: NEON: memcpy compiles to vst1 with incorrect alignment)

2015-08-03  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/66917
	* tree-vectorizer.h (struct dataref_aux): Add base_element_aligned
	field.
	(DR_VECT_AUX): New macro.
	(set_dr_misalignment): Adjust.
	(dr_misalignment): Likewise.
	* tree-vect-data-refs.c (vect_compute_data_ref_alignment):
	Compute whether the base is at least element aligned.
	* tree-vect-stmts.c (ensure_base_align): Adjust.
	(vectorizable_store): If the base is not element aligned
	preserve alignment of the original access if misalignment is unknown.
	(vectorizable_load): Likewise.

From-SVN: r226487
parent 94b8fdcc
2015-08-03 Richard Biener <rguenther@suse.de>
PR tree-optimization/66917
* tree-vectorizer.h (struct dataref_aux): Add base_element_aligned
field.
(DR_VECT_AUX): New macro.
(set_dr_misalignment): Adjust.
(dr_misalignment): Likewise.
* tree-vect-data-refs.c (vect_compute_data_ref_alignment):
Compute whether the base is at least element aligned.
* tree-vect-stmts.c (ensure_base_align): Adjust.
(vectorizable_store): If the base is not element aligned
preserve alignment of the original access if misalignment is unknown.
(vectorizable_load): Likewise.
2015-08-02 Martin Sebor <msebor@redhat.com> 2015-08-02 Martin Sebor <msebor@redhat.com>
* c-family/c.opt (-Wframe-address): New warning option. * c-family/c.opt (-Wframe-address): New warning option.
......
...@@ -622,7 +622,6 @@ vect_compute_data_ref_alignment (struct data_reference *dr) ...@@ -622,7 +622,6 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
tree ref = DR_REF (dr); tree ref = DR_REF (dr);
tree vectype; tree vectype;
tree base, base_addr; tree base, base_addr;
bool base_aligned;
tree misalign = NULL_TREE; tree misalign = NULL_TREE;
tree aligned_to; tree aligned_to;
unsigned HOST_WIDE_INT alignment; unsigned HOST_WIDE_INT alignment;
...@@ -698,6 +697,19 @@ vect_compute_data_ref_alignment (struct data_reference *dr) ...@@ -698,6 +697,19 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
} }
} }
/* To look at alignment of the base we have to preserve an inner MEM_REF
as that carries alignment information of the actual access. */
base = ref;
while (handled_component_p (base))
base = TREE_OPERAND (base, 0);
if (TREE_CODE (base) == MEM_REF)
base = build2 (MEM_REF, TREE_TYPE (base), base_addr,
build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)), 0));
unsigned int base_alignment = get_object_alignment (base);
if (base_alignment >= TYPE_ALIGN (TREE_TYPE (vectype)))
DR_VECT_AUX (dr)->base_element_aligned = true;
alignment = TYPE_ALIGN_UNIT (vectype); alignment = TYPE_ALIGN_UNIT (vectype);
if ((compare_tree_int (aligned_to, alignment) < 0) if ((compare_tree_int (aligned_to, alignment) < 0)
...@@ -713,21 +725,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr) ...@@ -713,21 +725,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
return true; return true;
} }
/* To look at alignment of the base we have to preserve an inner MEM_REF if (base_alignment < TYPE_ALIGN (vectype))
as that carries alignment information of the actual access. */
base = ref;
while (handled_component_p (base))
base = TREE_OPERAND (base, 0);
if (TREE_CODE (base) == MEM_REF)
base = build2 (MEM_REF, TREE_TYPE (base), base_addr,
build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)), 0));
if (get_object_alignment (base) >= TYPE_ALIGN (vectype))
base_aligned = true;
else
base_aligned = false;
if (!base_aligned)
{ {
/* Strip an inner MEM_REF to a bare decl if possible. */ /* Strip an inner MEM_REF to a bare decl if possible. */
if (TREE_CODE (base) == MEM_REF if (TREE_CODE (base) == MEM_REF
...@@ -757,8 +755,9 @@ vect_compute_data_ref_alignment (struct data_reference *dr) ...@@ -757,8 +755,9 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
dump_printf (MSG_NOTE, "\n"); dump_printf (MSG_NOTE, "\n");
} }
((dataref_aux *)dr->aux)->base_decl = base; DR_VECT_AUX (dr)->base_decl = base;
((dataref_aux *)dr->aux)->base_misaligned = true; DR_VECT_AUX (dr)->base_misaligned = true;
DR_VECT_AUX (dr)->base_element_aligned = true;
} }
/* If this is a backward running DR then first access in the larger /* If this is a backward running DR then first access in the larger
......
...@@ -5056,10 +5056,10 @@ ensure_base_align (stmt_vec_info stmt_info, struct data_reference *dr) ...@@ -5056,10 +5056,10 @@ ensure_base_align (stmt_vec_info stmt_info, struct data_reference *dr)
if (!dr->aux) if (!dr->aux)
return; return;
if (((dataref_aux *)dr->aux)->base_misaligned) if (DR_VECT_AUX (dr)->base_misaligned)
{ {
tree vectype = STMT_VINFO_VECTYPE (stmt_info); tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree base_decl = ((dataref_aux *)dr->aux)->base_decl; tree base_decl = DR_VECT_AUX (dr)->base_decl;
if (decl_in_symtab_p (base_decl)) if (decl_in_symtab_p (base_decl))
symtab_node::get (base_decl)->increase_alignment (TYPE_ALIGN (vectype)); symtab_node::get (base_decl)->increase_alignment (TYPE_ALIGN (vectype));
...@@ -5068,7 +5068,7 @@ ensure_base_align (stmt_vec_info stmt_info, struct data_reference *dr) ...@@ -5068,7 +5068,7 @@ ensure_base_align (stmt_vec_info stmt_info, struct data_reference *dr)
DECL_ALIGN (base_decl) = TYPE_ALIGN (vectype); DECL_ALIGN (base_decl) = TYPE_ALIGN (vectype);
DECL_USER_ALIGN (base_decl) = 1; DECL_USER_ALIGN (base_decl) = 1;
} }
((dataref_aux *)dr->aux)->base_misaligned = false; DR_VECT_AUX (dr)->base_misaligned = false;
} }
} }
...@@ -5739,11 +5739,15 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -5739,11 +5739,15 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
misalign = 0; misalign = 0;
else if (DR_MISALIGNMENT (first_dr) == -1) else if (DR_MISALIGNMENT (first_dr) == -1)
{ {
if (DR_VECT_AUX (first_dr)->base_element_aligned)
align = TYPE_ALIGN_UNIT (elem_type);
else
align = get_object_alignment (DR_REF (first_dr))
/ BITS_PER_UNIT;
misalign = 0;
TREE_TYPE (data_ref) TREE_TYPE (data_ref)
= build_aligned_type (TREE_TYPE (data_ref), = build_aligned_type (TREE_TYPE (data_ref),
TYPE_ALIGN (elem_type)); align * BITS_PER_UNIT);
align = TYPE_ALIGN_UNIT (elem_type);
misalign = 0;
} }
else else
{ {
...@@ -6824,11 +6828,15 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -6824,11 +6828,15 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
} }
else if (DR_MISALIGNMENT (first_dr) == -1) else if (DR_MISALIGNMENT (first_dr) == -1)
{ {
if (DR_VECT_AUX (first_dr)->base_element_aligned)
align = TYPE_ALIGN_UNIT (elem_type);
else
align = (get_object_alignment (DR_REF (first_dr))
/ BITS_PER_UNIT);
misalign = 0;
TREE_TYPE (data_ref) TREE_TYPE (data_ref)
= build_aligned_type (TREE_TYPE (data_ref), = build_aligned_type (TREE_TYPE (data_ref),
TYPE_ALIGN (elem_type)); align * BITS_PER_UNIT);
align = TYPE_ALIGN_UNIT (elem_type);
misalign = 0;
} }
else else
{ {
......
...@@ -707,11 +707,16 @@ typedef struct _stmt_vec_info { ...@@ -707,11 +707,16 @@ typedef struct _stmt_vec_info {
#define STMT_SLP_TYPE(S) (S)->slp_type #define STMT_SLP_TYPE(S) (S)->slp_type
struct dataref_aux { struct dataref_aux {
tree base_decl;
bool base_misaligned;
int misalignment; int misalignment;
/* If true the alignment of base_decl needs to be increased. */
bool base_misaligned;
/* If true we know the base is at least vector element alignment aligned. */
bool base_element_aligned;
tree base_decl;
}; };
#define DR_VECT_AUX(dr) ((dataref_aux *)(dr)->aux)
#define VECT_MAX_COST 1000 #define VECT_MAX_COST 1000
/* The maximum number of intermediate steps required in multi-step type /* The maximum number of intermediate steps required in multi-step type
...@@ -910,14 +915,13 @@ destroy_cost_data (void *data) ...@@ -910,14 +915,13 @@ destroy_cost_data (void *data)
targetm.vectorize.destroy_cost_data (data); targetm.vectorize.destroy_cost_data (data);
} }
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
/* Info on data references alignment. */ /* Info on data references alignment. */
/*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/
inline void inline void
set_dr_misalignment (struct data_reference *dr, int val) set_dr_misalignment (struct data_reference *dr, int val)
{ {
dataref_aux *data_aux = (dataref_aux *) dr->aux; dataref_aux *data_aux = DR_VECT_AUX (dr);
if (!data_aux) if (!data_aux)
{ {
...@@ -931,8 +935,7 @@ set_dr_misalignment (struct data_reference *dr, int val) ...@@ -931,8 +935,7 @@ set_dr_misalignment (struct data_reference *dr, int val)
inline int inline int
dr_misalignment (struct data_reference *dr) dr_misalignment (struct data_reference *dr)
{ {
gcc_assert (dr->aux); return DR_VECT_AUX (dr)->misalignment;
return ((dataref_aux *) dr->aux)->misalignment;
} }
/* Reflects actual alignment of first access in the vectorized loop, /* Reflects actual alignment of first access in the vectorized loop,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment