This fixes the slowness of RTL expansion in PR60291 which is caused
by excessive collisions in mem-attr sharing.  The issue here is
that sharing attempts happens across functions and we have a _lot_
of functions in this testcase referencing the same lexically
equivalent memory, for example MEM[(StgWord *)_5 + -64B].  That
means those get the same hash value.  But they don't compare
equal because an SSA name _5 from function A is of course not equal
to one from function B.

The following fixes that by not doing mem-attr sharing across functions
by clearing the mem-attrs hashtable in rest_of_clean_state.

Another fix may be to do what the comment in iterative_hash_expr
says for SSA names:

    case SSA_NAME:
      /* We can just compare by pointer.  */
      return iterative_hash_host_wide_int (SSA_NAME_VERSION (t), val);

(probably blame me for changing that to hashing the SSA version).  But
I'm not sure that doesn't uncover issues with various hashtables and
walking them, generating code dependent on the order.  It's IMHO just not
expected that you compare function-local expressions from different
functions.

The other thing would be to discard mem-attr sharing alltogether,
but that doesn't seem appropriate at this stage (but it would
also simplify quite some code).  With only one function in RTL
at a time that shouldn't be too bad (see several suggestions
along that line, even with statistics).

Bootstrap / regtest running on x86_64-unknown-linux-gnu, ok for
trunk and 4.8 branch?

Thanks,
Richard.

2014-02-21  Richard Biener  <rguent...@suse.de>

        PR middle-end/60291
        * rtl.h (clear_mem_attrs_htab): Declare.
        * emit-rtl.c (clear_mem_attrs_htab): New function.
        * final.c (rest_of_clean_state): Call clear_mem_attrs_htab
        to avoid sharing mem-attrs between functions.

Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h   (revision 207960)
--- gcc/rtl.h   (working copy)
*************** extern int in_sequence_p (void);
*** 2546,2551 ****
--- 2546,2552 ----
  extern void init_emit (void);
  extern void init_emit_regs (void);
  extern void init_emit_once (void);
+ extern void clear_mem_attrs_htab (void);
  extern void push_topmost_sequence (void);
  extern void pop_topmost_sequence (void);
  extern void set_new_first_and_last_insn (rtx, rtx);
Index: gcc/emit-rtl.c
===================================================================
*** gcc/emit-rtl.c      (revision 207960)
--- gcc/emit-rtl.c      (working copy)
*************** init_emit_once (void)
*** 5913,5918 ****
--- 5913,5926 ----
    simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
    cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
  }
+ 
+ /* Clear the mem-attrs sharing hash table.  */
+ 
+ void
+ clear_mem_attrs_htab (void)
+ {
+   htab_empty (mem_attrs_htab);
+ }
  
  /* Produce exact duplicate of insn INSN after AFTER.
     Care updating of libcall regions if present.  */
Index: gcc/final.c
===================================================================
*** gcc/final.c (revision 207960)
--- gcc/final.c (working copy)
*************** rest_of_clean_state (void)
*** 4678,4683 ****
--- 4678,4686 ----
  
    init_recog_no_volatile ();
  
+   /* Reset mem-attrs sharing.  */
+   clear_mem_attrs_htab ();
+ 
    /* We're done with this function.  Free up memory if we can.  */
    free_after_parsing (cfun);
    free_after_compilation (cfun);

Reply via email to