This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR56888


The following fixes us to not transform loops into memcpy or memset
or not transform malloc + memset into calloc if we implement that
functionality itself (and thus we "alias" the symbol we'd call when
emitting a call to the builtin).

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

The code is pretty awkward as builtins have no cgraph node and their
assembler name is still the "wrong" one appearantly.

Ok?  Any better way to implement this?

Thanks,
Richard.

2016-02-22  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/56888
	* cgraph.c (cgraph_node::aliases): New function.
	* cgraph.h (cgraph_node::aliases): Declare.
	* tree-loop-distribution.c: Include cgraph.h.
	(classify_partition): Check whether the current function aliases
	memset, memcpy or memmove.
	* tree-ssa-strlen.c (handle_builtin_memset): Check whether the
	current function aliases calloc.

Index: gcc/cgraph.c
===================================================================
*** gcc/cgraph.c	(revision 233598)
--- gcc/cgraph.c	(working copy)
*************** cgraph_node::has_thunk_p (cgraph_node *n
*** 3541,3544 ****
--- 3541,3564 ----
    return false;
  }
  
+ /* Return true if NODE aliases FN.  */
+ 
+ bool
+ cgraph_node::aliases (enum built_in_function fn)
+ {
+   tree fndecl = builtin_decl_implicit (fn);
+   if (! fndecl || ! DECL_ASSEMBLER_NAME_SET_P (fndecl))
+     return false;
+ 
+   /* ???  Builtins with aliases are weird.  */
+   cgraph_node *fnnode
+     = cgraph_node::get_for_asmname (DECL_ASSEMBLER_NAME (fndecl));
+   if (! fnnode)
+     return false;
+ 
+   fndecl = fnnode->ultimate_alias_target ()->decl;
+   return symbol_table::decl_assembler_name_equal (decl,
+ 						  DECL_ASSEMBLER_NAME (fndecl));
+ }
+ 
  #include "gt-cgraph.h"
Index: gcc/cgraph.h
===================================================================
*** gcc/cgraph.h	(revision 233598)
--- gcc/cgraph.h	(working copy)
*************** public:
*** 1181,1186 ****
--- 1181,1189 ----
    /* Return true if function should be optimized for size.  */
    bool optimize_for_size_p (void);
  
+   /* Return true if NODE aliases the specified builtin.  */
+   bool aliases (enum built_in_function);
+ 
    /* Dump the callgraph to file F.  */
    static void dump_cgraph (FILE *f);
  
Index: gcc/tree-loop-distribution.c
===================================================================
*** gcc/tree-loop-distribution.c	(revision 233598)
--- gcc/tree-loop-distribution.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 64,69 ****
--- 64,70 ----
  #include "cfgloop.h"
  #include "tree-scalar-evolution.h"
  #include "tree-vectorizer.h"
+ #include "cgraph.h"
  
  
  /* A Reduced Dependence Graph (RDG) vertex representing a statement.  */
*************** classify_partition (loop_p loop, struct
*** 1078,1083 ****
--- 1079,1086 ----
  	  || !dominated_by_p (CDI_DOMINATORS,
  			      loop->latch, gimple_bb (stmt)))
  	return;
+       if (cgraph_node::get (cfun->decl)->aliases (BUILT_IN_MEMSET))
+ 	return;
        partition->kind = PKIND_MEMSET;
        partition->main_dr = single_store;
        partition->niter = nb_iter;
*************** classify_partition (loop_p loop, struct
*** 1135,1140 ****
--- 1138,1146 ----
  	}
        free_dependence_relation (ddr);
        loops.release ();
+       if (cgraph_node::get (cfun->decl)->aliases (BUILT_IN_MEMCPY)
+ 	  || cgraph_node::get (cfun->decl)->aliases (BUILT_IN_MEMMOVE))
+ 	return;
        partition->kind = PKIND_MEMCPY;
        partition->main_dr = single_store;
        partition->secondary_dr = single_load;
Index: gcc/tree-ssa-strlen.c
===================================================================
*** gcc/tree-ssa-strlen.c	(revision 233598)
--- gcc/tree-ssa-strlen.c	(working copy)
*************** handle_builtin_memset (gimple_stmt_itera
*** 1817,1823 ****
    if (code1 == BUILT_IN_CALLOC)
      /* Not touching stmt1 */ ;
    else if (code1 == BUILT_IN_MALLOC
! 	   && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0))
      {
        gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
        update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
--- 1817,1824 ----
    if (code1 == BUILT_IN_CALLOC)
      /* Not touching stmt1 */ ;
    else if (code1 == BUILT_IN_MALLOC
! 	   && operand_equal_p (gimple_call_arg (stmt1, 0), size, 0)
! 	   && ! cgraph_node::get (cfun->decl)->aliases (BUILT_IN_CALLOC))
      {
        gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt1);
        update_gimple_call (&gsi1, builtin_decl_implicit (BUILT_IN_CALLOC), 2,
Index: gcc/testsuite/gcc.dg/pr56888.c
===================================================================
*** gcc/testsuite/gcc.dg/pr56888.c	(revision 0)
--- gcc/testsuite/gcc.dg/pr56888.c	(working copy)
***************
*** 0 ****
--- 1,21 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -ftree-loop-distribute-patterns -fdump-tree-optimized" } */
+ /* { dg-require-alias "" } */
+ /* { dg-require-weak "" } */
+ 
+ typedef __SIZE_TYPE__ size_t;
+ extern void *
+ memset (void *s, int c, size_t n) __attribute__ ((weak, alias("_memset")));
+ 
+ void *
+ _memset(void *s, int c, size_t n)
+ {
+   char *q = (char *)s;
+   while (n != 0)
+     {
+       *(q++) = c;
+       n--;
+     }
+ }
+ 
+ /* { dg-final { scan-tree-dump-not "__builtin_memset" "optimized" } } */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]