+2008-09-22 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/37482
+ * tree-vectorizer.h (struct _slp_instance): Add new field.
+ (SLP_INSTANCE_FIRST_LOAD_STMT): New.
+ (get_earlier_stmt): New function.
+ * tree-vect-analyze.c (vect_find_first_load_in_slp_instance): New
+ function.
+ (vect_analyze_slp_instance): Set SLP_INSTANCE_FIRST_LOAD_STMT.
+ * tree-vect-transform.c (vect_finish_stmt_generation): Remove the
+ asserts that GSI points to the scalar statement being vectorized.
+ Set new statement location according to GSI.
+ (vect_schedule_slp_instance): Use GSI of
+ SLP_INSTANCE_FIRST_LOAD_STMT when vectorizing loads.
+
2008-09-21 Jan Hubicka <jh@suse.cz>
* ipa-cp.c (ipcp_estimate_growth): Check recursive calls.
+2008-09-22 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/37482
+ * gcc.dg/vect/pr37482.c: New test.
+
2008-09-22 Hans-Peter Nilsson <hp@axis.com>
PR middle-end/37170
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+void SexiALI_Convert(void *vdest, void *vsrc, unsigned int frames)
+{
+ unsigned int x;
+ short *src = vsrc;
+ unsigned char *dest = vdest;
+ for(x=0;x<256;x++)
+ {
+ int tmp;
+ tmp = *src;
+ src++;
+ tmp += *src;
+ src++;
+ *dest++ = tmp;
+ *dest++ = tmp;
+ }
+}
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
return false;
}
+
+/* Find the first load in the loop that belongs to INSTANCE.
+ When loads are in several SLP nodes, there can be a case in which the first
+ load does not appear in the first SLP node to be transformed, causing
+ incorrect order of statements. Since we generate all the loads together,
+ they must be inserted before the first load of the SLP instance and not
+ before the first load of the first node of the instance. */
+static gimple
+vect_find_first_load_in_slp_instance (slp_instance instance)
+{
+ int i, j;
+ slp_tree load_node;
+ gimple first_load = NULL, load;
+
+ for (i = 0;
+ VEC_iterate (slp_tree, SLP_INSTANCE_LOADS (instance), i, load_node);
+ i++)
+ for (j = 0;
+ VEC_iterate (gimple, SLP_TREE_SCALAR_STMTS (load_node), j, load);
+ j++)
+ first_load = get_earlier_stmt (load, first_load);
+
+ return first_load;
+}
+
+
/* Analyze an SLP instance starting from a group of strided stores. Call
vect_build_slp_tree to build a tree of packed stmts if possible.
Return FALSE if it's impossible to SLP any stmt in the loop. */
SLP_INSTANCE_OUTSIDE_OF_LOOP_COST (new_instance) = outside_cost;
SLP_INSTANCE_INSIDE_OF_LOOP_COST (new_instance) = inside_cost;
SLP_INSTANCE_LOADS (new_instance) = loads;
+ SLP_INSTANCE_FIRST_LOAD_STMT (new_instance) = NULL;
SLP_INSTANCE_LOAD_PERMUTATION (new_instance) = load_permutation;
if (VEC_length (slp_tree, loads))
{
vect_free_slp_instance (new_instance);
return false;
}
+
+ SLP_INSTANCE_FIRST_LOAD_STMT (new_instance)
+ = vect_find_first_load_in_slp_instance (new_instance);
}
else
VEC_free (int, heap, SLP_INSTANCE_LOAD_PERMUTATION (new_instance));
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- gcc_assert (stmt == gsi_stmt (*gsi));
gcc_assert (gimple_code (stmt) != GIMPLE_LABEL);
gsi_insert_before (gsi, vec_stmt, GSI_SAME_STMT);
print_gimple_stmt (vect_dump, vec_stmt, 0, TDF_SLIM);
}
- /* Make sure gsi points to the stmt that is being vectorized. */
- gcc_assert (stmt == gsi_stmt (*gsi));
-
- gimple_set_location (vec_stmt, gimple_location (stmt));
+ gimple_set_location (vec_stmt, gimple_location (gsi_stmt (*gsi)));
}
static bool
vect_schedule_slp_instance (slp_tree node, slp_instance instance,
- unsigned int vectorization_factor)
+ unsigned int vectorization_factor)
{
gimple stmt;
bool strided_store, is_store;
stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (node), 0);
stmt_info = vinfo_for_stmt (stmt);
+
/* VECTYPE is the type of the destination. */
vectype = get_vectype_for_scalar_type (TREE_TYPE (gimple_assign_lhs (stmt)));
nunits = (unsigned int) TYPE_VECTOR_SUBPARTS (vectype);
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- si = gsi_for_stmt (stmt);
+ /* Loads should be inserted before the first load. */
+ if (SLP_INSTANCE_FIRST_LOAD_STMT (instance)
+ && STMT_VINFO_STRIDED_ACCESS (stmt_info)
+ && !REFERENCE_CLASS_P (gimple_get_lhs (stmt)))
+ si = gsi_for_stmt (SLP_INSTANCE_FIRST_LOAD_STMT (instance));
+ else
+ si = gsi_for_stmt (stmt);
+
is_store = vect_transform_stmt (stmt, &si, &strided_store, node, instance);
if (is_store)
{
{
/* Schedule the tree of INSTANCE. */
is_store = vect_schedule_slp_instance (SLP_INSTANCE_TREE (instance),
- instance,
- LOOP_VINFO_VECT_FACTOR (loop_vinfo));
+ instance, LOOP_VINFO_VECT_FACTOR (loop_vinfo));
if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS)
|| vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
/* The group of nodes that contain loads of this SLP instance. */
VEC (slp_tree, heap) *loads;
+
+ /* The first scalar load of the instance. The created vector loads will be
+ inserted before this statement. */
+ gimple first_load;
} *slp_instance;
DEF_VEC_P(slp_instance);
#define SLP_INSTANCE_INSIDE_OF_LOOP_COST(S) (S)->cost.inside_of_loop
#define SLP_INSTANCE_LOAD_PERMUTATION(S) (S)->load_permutation
#define SLP_INSTANCE_LOADS(S) (S)->loads
+#define SLP_INSTANCE_FIRST_LOAD_STMT(S) (S)->first_load
#define SLP_TREE_LEFT(S) (S)->left
#define SLP_TREE_RIGHT(S) (S)->right
VEC_replace (vec_void_p, stmt_vec_info_vec, uid - 1, (vec_void_p) info);
}
+static inline gimple
+get_earlier_stmt (gimple stmt1, gimple stmt2)
+{
+ unsigned int uid1, uid2;
+
+ if (stmt1 == NULL)
+ return stmt2;
+
+ if (stmt2 == NULL)
+ return stmt1;
+
+ uid1 = gimple_uid (stmt1);
+ uid2 = gimple_uid (stmt2);
+
+ if (uid1 == 0 || uid2 == 0)
+ return NULL;
+
+ gcc_assert (uid1 <= VEC_length (vec_void_p, stmt_vec_info_vec));
+ gcc_assert (uid2 <= VEC_length (vec_void_p, stmt_vec_info_vec));
+
+ if (uid1 < uid2)
+ return stmt1;
+ else
+ return stmt2;
+}
+
static inline bool
is_pattern_stmt_p (stmt_vec_info stmt_info)
{