This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Problems with a patch to improve dependence analysis
- From: "Sjodin, Jan" <Jan dot Sjodin at amd dot com>
- To: "GCC Patches" <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 13 Jul 2007 16:04:55 -0500
- Subject: Problems with a patch to improve dependence analysis
I am working on a patch to make the dependence analysis slightly more
powerful to enable the vectorizer. I would be happy to get some input on
what could be wrong. The case I'm trying to get to work is the
following:
int foo (int A[N][N])
{
int i,j;
/* vectorizable */
for (i = 1; i < N; i++)
for (j = 0; j < N; j++)
A[i][j] = A[i-1][j] + A[i][j];
return 0;
}
Currently this does not get vectorized because internally A[i-1][j] is
represented as (A+k)[i][j]. The dependence analysis determines that A
and (A+k) are not the same base object and gives up. The function
split_constant_offset is doing some work to eliminate this problem but
it does not follow ssa edges, the constant in this case is in a
different statemt. Below is a fix for this:
Index: trunk/gcc/tree-data-ref.c
===================================================================
--- trunk/gcc/tree-data-ref.c (revision 126419)
+++ trunk/gcc/tree-data-ref.c (working copy)
@@ -566,6 +566,25 @@ split_constant_offset (tree exp, tree *v
return;
}
+ case SSA_NAME:
+ {
+ tree def_stmt = SSA_NAME_DEF_STMT (exp);
+ if (TREE_CODE (def_stmt) == GIMPLE_MODIFY_STMT)
+ {
+ tree def_stmt_rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+ if (!TREE_SIDE_EFFECTS (def_stmt_rhs)
+ && EXPR_P (def_stmt_rhs))
+ {
+ split_constant_offset (def_stmt_rhs, &var0, &off0);
+ var0 = fold_convert (type, var0);
+ *var = var0;
+ *off = off0;
+ return;
+ }
+ }
+ break;
+ }
+
default:
break;
}
This worked for the most part (non-bootstrap, make check), but there are
errors during bootstrap:
-----------------------------------------------------------------------
_r4.c: In function 'matmul_r4':
/home/jsjodin/Work/Project/GCC/Latest/trunk/libgfortran/generated/matm
ul
_r4.c:87: error: expected an SSA_NAME object
/home/jsjodin/Work/Project/GCC/Latest/trunk/libgfortran/generated/matm
ul
_r4.c:87: error: in statement
# VUSE <SMT.37> { SMT.37 }
D.5431_402 = retarray_45(D)->data;
----------------------------------------------------------------------
Since split_constant_offset now can create large expressions any direct
uses of the result to generate code will not be valid (GIMPLE). The
result of split_constant_offset is used for computing three properties
in data_ref:
DR_BASE_OBJECT -- only used internally by the dependence analysis
DR_BASE_ADDRESS -- used in tree-vect-transform.c to generate code
(triggers the error)
DR_OFFSET -- used in tree-vect-transform.c to generate code
There are no other uses to my knowledge.
The idea to fix this was to use force_gimple_operand, but doing that
does not change anything the same error still occurs. We have verified
that DR_BASE_ADDRESS is the problem (added a flag to enable/disable the
SSA_NAME case in split_constant_offset). Unless the fix below is buggy
(the temporaries "batmp" get generated and used in other examples) I
don't know what could be the cause of the errors. Does anyone have an
idea why?
Below is the code change for tree-vect-transform.c
Index: trunk/gcc/tree-vect-transform.c
===================================================================
--- trunk/gcc/tree-vect-transform.c (revision 126419)
+++ trunk/gcc/tree-vect-transform.c (working copy)
@@ -651,21 +651,32 @@ vect_create_addr_base_for_vector_ref (tr {
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
- tree data_ref_base = unshare_expr (DR_BASE_ADDRESS (dr));
- tree base_name = build_fold_indirect_ref (data_ref_base);
+ tree data_ref_base_expr = unshare_expr (DR_BASE_ADDRESS (dr)); tree
+ base_name = build_fold_indirect_ref (data_ref_base_expr); tree
+ data_ref_base_var; tree data_ref_base; tree new_base_stmt;
tree vec_stmt;
tree addr_base, addr_expr;
tree dest, new_stmt;
tree base_offset = unshare_expr (DR_OFFSET (dr));
tree init = unshare_expr (DR_INIT (dr));
tree vect_ptr_type, addr_expr2;
+
+
+ /* Create data_ref_base */
+ data_ref_base_var = create_tmp_var (TREE_TYPE (data_ref_base_expr),
+ "batmp");
+ add_referenced_var (data_ref_base_var);
+ data_ref_base = force_gimple_operand (data_ref_base_expr,
&new_base_stmt,
+ true, data_ref_base_var);
+ append_to_statement_list_force(new_base_stmt, new_stmt_list);
/* Create base_offset */
base_offset = size_binop (PLUS_EXPR, base_offset, init);
base_offset = fold_convert (sizetype, base_offset);
dest = create_tmp_var (TREE_TYPE (base_offset), "base_off");
add_referenced_var (dest);
- base_offset = force_gimple_operand (base_offset, &new_stmt, false,
dest);
+ base_offset = force_gimple_operand (base_offset, &new_stmt, true,
+ dest);
append_to_statement_list_force (new_stmt, new_stmt_list);
if (offset)