[PATCH] Fix a -ftree-vectorize ICE (PR tree-optimization/33017)

Jakub Jelinek jakub@redhat.com
Mon Sep 3 19:34:00 GMT 2007


Hi!

The attached testcase ICEs on i?86-linux with -O2 -ftree-vectorize.
The problem is that DR_OFFSET (dr) in this case is fairly complex
(involves pure function call) and tree-vect-transform.c
doesn't call mark_symbols_for_renaming on the statements
force_gimple_operand creates.  I have started writing a patch to do
so (second attachment), but it only covers a small part of the
force_gimple_operand calls (though enough to fix the ICE).

Then it occured to me that I don't see how having a const or pure
function call inside of DR_OFFSET etc. can be really helpful for
optimizations, the only effect it IMHO has is that optimizations
that use tree-data-ref.c might duplicate that const/pure call
and then other optimizations need to clean that up again.
So, the first attachment just stops in split_constant_offset
when it sees a call - the LHS will be IMHO better than the RHS.
This has been regtested on x86_64-linux, ok for trunk?

	Jakub
-------------- next part --------------
2007-09-03  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/33017
	* tree-data-ref.c (split_constant_offset) <case SSA_NAME>: Don't
	recurse for pure or const function calls.

	* gcc.dg/pr33017.c: New test.

--- gcc/tree-data-ref.c.jj	2007-08-23 23:37:41.000000000 +0200
+++ gcc/tree-data-ref.c	2007-09-03 20:21:37.000000000 +0200
@@ -574,7 +574,8 @@ split_constant_offset (tree exp, tree *v
 
 	    if (!TREE_SIDE_EFFECTS (def_stmt_rhs) 
 		&& EXPR_P (def_stmt_rhs)
-		&& !REFERENCE_CLASS_P (def_stmt_rhs))
+		&& !REFERENCE_CLASS_P (def_stmt_rhs)
+		&& !get_call_expr_in (def_stmt_rhs))
 	      {
 		split_constant_offset (def_stmt_rhs, &var0, &off0);
 		var0 = fold_convert (type, var0);
--- gcc/testsuite/gcc.dg/pr33017.c.jj	2007-09-03 20:34:13.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr33017.c	2007-09-03 20:33:37.000000000 +0200
@@ -0,0 +1,30 @@
+/* PR tree-optimization/33017 */
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+extern __SIZE_TYPE__ strlen (const char *);
+extern void abort (void);
+
+char *
+__attribute__((noinline))
+foo (const char *string)
+{
+  int len;
+  static char var[0x104];
+  int off;
+  len = strlen (string);
+  for (off = 0; off < 64; off++)
+    var[len + off + 2] = 0x57;
+  return var;
+}
+
+int
+main (void)
+{
+  char *p = foo ("abcd");
+  int i;
+  for (i = 0; i < 0x104; i++)
+    if (p[i] != ((i >= 6 && i < 70) ? 0x57 : 0))
+      abort ();
+  return 0;
+}
-------------- next part --------------
--- gcc/tree-vectorizer.c.jj	2007-08-27 10:15:33.000000000 +0200
+++ gcc/tree-vectorizer.c	2007-09-03 19:31:46.000000000 +0200
@@ -955,9 +955,6 @@ slpeel_can_duplicate_loop_p (const struc
   tree orig_cond = get_loop_exit_condition (loop);
   block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src);
 
-  if (need_ssa_update_p ())
-    return false;
-
   if (loop->inner
       /* All loops have an outer scope; the only case loop->outer is NULL is for
          the function itself.  */
--- gcc/tree-vect-analyze.c.jj	2007-08-20 09:49:24.000000000 +0200
+++ gcc/tree-vect-analyze.c	2007-09-03 19:32:37.000000000 +0200
@@ -551,7 +551,8 @@ vect_analyze_operations (loop_vec_info l
                      "not vectorized: can't create epilog loop 1.");
           return false;
         }
-      if (!slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
+      if (need_ssa_update_p ()
+	  || !slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
         {
           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
             fprintf (vect_dump,
@@ -1774,7 +1775,8 @@ vect_enhance_data_refs_alignment (loop_v
      will require peeling for loop-bound, which in turn requires that we
      know how to adjust the loop ivs after the loop.  */
   if (vect_versioning_for_alias_required
-       || !vect_can_advance_ivs_p (loop_vinfo)
+      || !vect_can_advance_ivs_p (loop_vinfo)
+      || need_ssa_update_p ()
       || !slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
     do_peeling = false;
 
--- gcc/tree-vect-transform.c.jj	2007-08-20 09:49:24.000000000 +0200
+++ gcc/tree-vect-transform.c	2007-09-03 18:58:19.000000000 +0200
@@ -765,6 +765,7 @@ vect_create_addr_base_for_vector_ref (tr
   tree init = unshare_expr (DR_INIT (dr));
   tree vect_ptr_type, addr_expr2;
   tree step = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
+  tree new_stmts = NULL_TREE;
 
   gcc_assert (loop);
   if (loop != containing_loop)
@@ -785,7 +786,7 @@ vect_create_addr_base_for_vector_ref (tr
   add_referenced_var (data_ref_base_var);
   data_ref_base = force_gimple_operand (data_ref_base, &new_base_stmt,
 					true, data_ref_base_var);
-  append_to_statement_list_force(new_base_stmt, new_stmt_list);
+  append_to_statement_list_force (new_base_stmt, &new_stmts);
 
   /* Create base_offset */
   base_offset = size_binop (PLUS_EXPR, base_offset, init);
@@ -793,7 +794,7 @@ vect_create_addr_base_for_vector_ref (tr
   dest = create_tmp_var (TREE_TYPE (base_offset), "base_off");
   add_referenced_var (dest);
   base_offset = force_gimple_operand (base_offset, &new_stmt, true, dest); 
-  append_to_statement_list_force (new_stmt, new_stmt_list);
+  append_to_statement_list_force (new_stmt, &new_stmts);
 
   if (offset)
     {
@@ -804,7 +805,7 @@ vect_create_addr_base_for_vector_ref (tr
       base_offset = fold_build2 (PLUS_EXPR, TREE_TYPE (base_offset),
 				 base_offset, offset);
       base_offset = force_gimple_operand (base_offset, &new_stmt, false, tmp);
-      append_to_statement_list_force (new_stmt, new_stmt_list);
+      append_to_statement_list_force (new_stmt, &new_stmts);
     }
   
   /* base + base_offset */
@@ -822,7 +823,15 @@ vect_create_addr_base_for_vector_ref (tr
                                      get_name (base_name));
   add_referenced_var (addr_expr2);
   vec_stmt = force_gimple_operand (vec_stmt, &new_stmt, false, addr_expr2);
-  append_to_statement_list_force (new_stmt, new_stmt_list);
+  append_to_statement_list_force (new_stmt, &new_stmts);
+
+  if (new_stmts)
+    {
+      tree_stmt_iterator tsi;
+      for (tsi = tsi_start (new_stmts); !tsi_end_p (tsi); tsi_next (&tsi))
+	mark_symbols_for_renaming (tsi_stmt (tsi));
+      append_to_statement_list_force (new_stmts, new_stmt_list);
+    }
 
   if (vect_print_dump_info (REPORT_DETAILS))
     {


More information about the Gcc-patches mailing list