https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98176

--- Comment #7 from Hongyu Wang <wwwhhhyyy333 at gmail dot com> ---
(In reply to Richard Biener from comment #5)
> Yes.
> 
> For a LIM testcase an example with a memcpy might be more practically
> relevant.
> 
> For refactoring I'd start with classifying the unanalyzable refs as
> separate ref ID, marking it with another bit like ref_unanalyzed in
> in_mem_ref and asserting there's a single access of such refs.
> The mem_refs_may_alias_p code then needs to use stmt-based alias
> queries instead of refs_may_alias_p_1 using accesses_in_loop[0]->stmt.
> 
> And code testing for UNANALYZABLE_MEM_ID now needs to look at the
> ref_unanalyzed flag to not consider those refs for transforms.
> 
> Note this may blow up the memory requirements for testcases with lots
> of "unanalyzable" refs.
> 
> The nonpure-call code is more difficult to improve, even sincos can not
> return
> when the access to s or c traps.  Analyzing the arguments might help here.
> If you disregard that detail I think all ECF_LEAF|ECF_NOTHROW functions
> return normally.

Thanks for the suggestion, I did some refactor accordingly and this case could
be vectorized. 

diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 92e5a8dd774..3e3e81bc36f 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -119,6 +119,8 @@ public:
                                   (its index in memory_accesses.refs_list)  */
   unsigned ref_canonical : 1;   /* Whether mem.ref was canonicalized.  */
   unsigned ref_decomposed : 1;  /* Whether the ref was hashed from mem.  */
+  unsigned ref_unanalyzed : 1; /* Whether the ref was unanalyzed memory.  */
+
   hashval_t hash;              /* Its hash value.  */

   /* The memory access itself and associated caching of alias-oracle
@@ -260,7 +262,14 @@ static bool refs_independent_p (im_mem_ref *, im_mem_ref
*, bool = true);
 #define UNANALYZABLE_MEM_ID 0

 /* Whether the reference was analyzable.  */
-#define MEM_ANALYZABLE(REF) ((REF)->id != UNANALYZABLE_MEM_ID)
+#define MEM_ANALYZABLE(REF) ((REF)->id != UNANALYZABLE_MEM_ID          \
+                            && !(REF)->ref_unanalyzed)
+
+#define REF_ID_UNANALYZABLE(id)                                               
\
+  (id == UNANALYZABLE_MEM_ID                                           \
+   || ((memory_accesses.refs_list[id])                                 \
+       && (memory_accesses.refs_list[id]->ref_unanalyzed)) \
+   )

 static struct lim_aux_data *
 init_lim_data (gimple *stmt)
@@ -829,7 +838,8 @@ set_profitable_level (gimple *stmt)
   set_level (stmt, gimple_bb (stmt)->loop_father, get_lim_data
(stmt)->max_loop);
 }

-/* Returns true if STMT is a call that has side effects.  */
+/* Returns true if STMT is a call that has side effects, or it is
+   not a function call with ECF_LEAF | ECF_NOTHROW.  */

 static bool
 nonpure_call_p (gimple *stmt)
@@ -837,6 +847,11 @@ nonpure_call_p (gimple *stmt)
   if (gimple_code (stmt) != GIMPLE_CALL)
     return false;

+  /* Simplified here, better to analyze call parameter.  */
+  int flags = gimple_call_flags (stmt);
+  if (flags & (ECF_LEAF | ECF_NOTHROW))
+    return false;
+
   return gimple_has_side_effects (stmt);
 }

@@ -1377,6 +1392,7 @@ mem_ref_alloc (ao_ref *mem, unsigned hash, unsigned id)
   ref->id = id;
   ref->ref_canonical = false;
   ref->ref_decomposed = false;
+  ref->ref_unanalyzed = false;
   ref->hash = hash;
   ref->stored = NULL;
   ref->loaded = NULL;
@@ -1461,9 +1477,13 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt)
   mem = simple_mem_ref_in_stmt (stmt, &is_stored);
   if (!mem)
     {
-      /* We use the shared mem_ref for all unanalyzable refs.  */
-      id = UNANALYZABLE_MEM_ID;
-      ref = memory_accesses.refs_list[id];
+      /* Mark unanaylzable refs with different id and skip analysis. */
+      id = memory_accesses.refs_list.length ();
+      ref = mem_ref_alloc (NULL, 0, id);
+      ref->ref_unanalyzed = true;
+      memory_accesses.refs_list.safe_push (ref);
+      record_mem_ref_loc (ref, stmt, NULL);
+
       if (dump_file && (dump_flags & TDF_DETAILS))
        {
          fprintf (dump_file, "Unanalyzed memory reference %u: ", id);
@@ -1576,7 +1596,7 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt)
       mark_ref_stored (ref, loop);
     }
   /* A not simple memory op is also a read when it is a write.  */
-  if (!is_stored || id == UNANALYZABLE_MEM_ID)
+  if (!is_stored || REF_ID_UNANALYZABLE (id))
     {
       bitmap_set_bit (&memory_accesses.refs_loaded_in_loop[loop->num],
ref->id);
       mark_ref_loaded (ref, loop);
@@ -1701,6 +1721,31 @@ mem_refs_may_alias_p (im_mem_ref *mem1, im_mem_ref
*mem2,
   poly_widest_int size1, size2;
   aff_tree off1, off2;

+  /* For refs marked as unanalyzed, use stmt_based alias analysis
+     and returns false when one mem_ref used by this unanalyzed stmt*/
+  if (mem1->ref_unanalyzed
+      || mem2->ref_unanalyzed)
+    {
+      if (mem1->ref_unanalyzed
+         && !mem2->ref_unanalyzed)
+       {
+         gcc_assert (mem1->accesses_in_loop.length() == 1);
+         gimple *stmt = mem1->accesses_in_loop[0].stmt;
+         if (ref_maybe_used_by_stmt_p (stmt, &mem2->mem, tbaa_p))
+           return true;
+       }
+      else if(!mem1->ref_unanalyzed)
+       {
+         gcc_assert (mem2->accesses_in_loop.length() == 1);
+         gimple *stmt = mem2->accesses_in_loop[0].stmt;
+         if (ref_maybe_used_by_stmt_p (stmt, &mem1->mem, tbaa_p))
+           return true;
+       }
+      else
+       return true;
+      return false;
+    }
+
   /* Perform basic offset and type-based disambiguation.  */
   if (!refs_may_alias_p_1 (&mem1->mem, &mem2->mem, tbaa_p))
     return false;
@@ -2423,7 +2468,7 @@ sm_seq_valid_bb (class loop *loop, basic_block bb, tree
vdef,
        }
       lim_aux_data *data = get_lim_data (def);
       gcc_assert (data);
-      if (data->ref == UNANALYZABLE_MEM_ID)
+      if (REF_ID_UNANALYZABLE (data->ref) )
        return -1;
       /* One of the stores we want to apply SM to and we've not yet seen.  */
       else if (bitmap_clear_bit (refs_not_in_seq, data->ref))
-- 

Does it looks correct? 

And this includes too many unanalyzed ids when I tried to compile a big
program... Is there any possibility to avoid the memory usage?

Reply via email to