New function attribute "pure"

Jan Hubicka hubicka@atrey.karlin.mff.cuni.cz
Sun Apr 9 15:49:00 GMT 2000


Hi
This adds support for function attribute "pure". It follows closely the
"malloc" attribute so I hope it will be OK.  It don't support attribute
for types, I have patch prepared for both attributes I will send later.

I've also found one problem with current "pure" functions handling.  The cse
ignores the FUSAGE field and is driven only by "equal from" node, so after my
fix sent recently (and Jeff's one installed few months ago) it csees two same
calls to pure function with memory store in between. This didn't happend
originally, but as an accident.  So I've changed calls.c
to emit (mem:BLK (scratch)) to the equal_from field too. The fix is boundled
to this patch.

Sadly cse is now unable to recognize two cseable calls, but still is able
to kill call with dead return value.  I can try to handle first case later.
With this change installed I am able to bootstrap gcc with number of pure
flags installed in the headers.

Honza

Mon Apr  3 22:26:14 CEST 2000  Jan Hubicka  <jh@suse.cz>
	* tree.h (DECL_IS_PURE): New macro.
	(struct tree_decl): Add pure_flag.
	* c-common.c (enum attrs): Add attribute "pure".
	(init_attributes): Initialize attribute "pure"
	(decl_attributes): Handle attribute "pure".
	* extend.texi (Attribute "pure"): Document.
	* calls.c (expand_call): Add (mem:BLK (scratch)) to "equal from"
	in pure function.
	(flags_from_decl_or_type): Support attribute "pure".

*** ../../egcs-20000306.orig/gcc/tree.h	Mon Apr  3 17:21:07 2000
--- tree.h	Mon Apr  3 17:23:12 2000
*************** struct tree_type
*** 1253,1258 ****
--- 1253,1262 ----
     not an alias.  */
  #define DECL_IS_MALLOC(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.malloc_flag)
  
+ /* Nonzero in a FUNCTION_DECL means this function should be treated
+    as "pure" function (like const function, but may read global memory).  */
+ #define DECL_IS_PURE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.pure_flag)
+ 
  /* Nonzero in a FIELD_DECL means it is a bit field, and must be accessed
     specially.  */
  #define DECL_BIT_FIELD(NODE) (FIELD_DECL_CHECK (NODE)->decl.bit_field_flag)
*************** struct tree_decl
*** 1392,1397 ****
--- 1396,1402 ----
    unsigned comdat_flag : 1;
    unsigned malloc_flag : 1;
    unsigned no_limit_stack : 1;
+   unsigned pure_flag : 1;
  #ifdef ONLY_INT_FIELDS
    unsigned int built_in_class : 2;
  #else
*** ../../egcs-20000306.orig/gcc/c-common.c	Mon Apr  3 17:21:07 2000
--- c-common.c	Mon Apr  3 17:24:39 2000
*************** enum attrs {A_PACKED, A_NOCOMMON, A_COMM
*** 145,151 ****
  	    A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
  	    A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
  	    A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS, A_MALLOC,
! 	    A_NO_LIMIT_STACK};
  
  enum format_type { printf_format_type, scanf_format_type,
  		   strftime_format_type };
--- 145,151 ----
  	    A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
  	    A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
  	    A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS, A_MALLOC,
! 	    A_NO_LIMIT_STACK, A_PURE};
  
  enum format_type { printf_format_type, scanf_format_type,
  		   strftime_format_type };
*************** init_attributes ()
*** 457,462 ****
--- 457,463 ----
    add_attribute (A_NO_CHECK_MEMORY_USAGE, "no_check_memory_usage", 0, 0, 1);
    add_attribute (A_MALLOC, "malloc", 0, 0, 1);
    add_attribute (A_NO_LIMIT_STACK, "no_stack_limit", 0, 0, 1);
+   add_attribute (A_PURE, "pure", 0, 0, 1);
  }
  
  /* Default implementation of valid_lang_attribute, below.  By default, there
*************** decl_attributes (node, attributes, prefi
*** 596,601 ****
--- 597,603 ----
  	case A_MALLOC:
  	  if (TREE_CODE (decl) == FUNCTION_DECL)
  	    DECL_IS_MALLOC (decl) = 1;
+ 	  /* ??? TODO: Support types.  */
  	  else
  	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
  	  break;
*************** decl_attributes (node, attributes, prefi
*** 624,629 ****
--- 626,640 ----
  	  else
  	    warning ( "`%s' attribute ignored", IDENTIFIER_POINTER (name));
  	  break;
+ 
+ 	case A_PURE:
+ 	  if (TREE_CODE (decl) == FUNCTION_DECL)
+ 	    DECL_IS_PURE (decl) = 1;
+ 	  /* ??? TODO: Support types.  */
+ 	  else
+ 	    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ 	  break;
+ 
  
  	case A_T_UNION:
  	  if (is_type
*** ../../egcs-20000306.orig/gcc/extend.texi	Mon Apr  3 17:21:07 2000
--- extend.texi	Mon Apr  3 18:20:27 2000
*************** typedef void voidfn ();
*** 1379,1400 ****
  volatile voidfn fatal;
  @end smallexample
  
! @cindex @code{const} function attribute
! @item const
! Many functions do not examine any values except their arguments, and
! have no effects except the return value.  Such a function can be subject
  to common subexpression elimination and loop optimization just as an
  arithmetic operator would be.  These functions should be declared
! with the attribute @code{const}.  For example,
  
  @smallexample
! int square (int) __attribute__ ((const));
  @end smallexample
  
  @noindent
  says that the hypothetical function @code{square} is safe to call
  fewer times than the program says.
  
  The attribute @code{const} is not implemented in GNU C versions earlier
  than 2.5.  An alternative way to declare that a function has no side
  effects, which works in the current version and in some older versions,
--- 1379,1422 ----
  volatile voidfn fatal;
  @end smallexample
  
! @cindex @code{pure} function attribute
! @item pure
! Many functions have no effects except the return value and their
! return value and depends only on the parameters and/or global variables.
! Such a function can be subject
  to common subexpression elimination and loop optimization just as an
  arithmetic operator would be.  These functions should be declared
! with the attribute @code{pure}.  For example,
  
  @smallexample
! int square (int) __attribute__ ((pure));
  @end smallexample
  
  @noindent
  says that the hypothetical function @code{square} is safe to call
  fewer times than the program says.
  
+ Some of common examples of pure functions are @code{strlen} or @code{memcmp}.
+ Interesting non-pure functions are functions with infinite loops or those
+ depending on volatile memory or other system resource, that may change between
+ two consetuctive calls (such as @code{feof} in multithreding environment).
+ 
+ The attribute @code{const} is not implemented in GNU C versions earlier
+ than 2.96.
+ @cindex @code{const} function attribute
+ @item const
+ Many functions do not examine any values except their arguments, and
+ have no effects except the return value.  Basically this is just slightly
+ more strict class than the "pure" attribute above, since function is not
+ alloved to read global memory.
+ 
+ @cindex pointer arguments
+ Note that a function that has pointer arguments and examines the data
+ pointed to must @emph{not} be declared @code{const}.  Likewise, a
+ function that calls a non-@code{const} function usually must not be
+ @code{const}.  It does not make sense for a @code{const} function to
+ return @code{void}.
+ 
  The attribute @code{const} is not implemented in GNU C versions earlier
  than 2.5.  An alternative way to declare that a function has no side
  effects, which works in the current version and in some older versions,
*************** extern const intfn square;
*** 1409,1420 ****
  This approach does not work in GNU C++ from 2.6.0 on, since the language
  specifies that the @samp{const} must be attached to the return value.
  
- @cindex pointer arguments
- Note that a function that has pointer arguments and examines the data
- pointed to must @emph{not} be declared @code{const}.  Likewise, a
- function that calls a non-@code{const} function usually must not be
- @code{const}.  It does not make sense for a @code{const} function to
- return @code{void}.
  
  @item format (@var{archetype}, @var{string-index}, @var{first-to-check})
  @cindex @code{format} function attribute
--- 1431,1436 ----
*** ../../egcs-20000306.orig/gcc/calls.c	Mon Apr  3 17:21:07 2000
--- calls.c	Mon Apr  3 22:29:20 2000
*************** flags_from_decl_or_type (exp)
*** 758,763 ****
--- 768,777 ----
        if (DECL_P (exp) && DECL_IS_MALLOC (exp))
  	flags |= ECF_MALLOC;
  
+       /* The function exp may have the `pure' attribute.  */
+       if (DECL_P (exp) && DECL_IS_PURE (exp))
+ 	flags |= ECF_PURE;
+ 
        if (TREE_NOTHROW (exp))
  	flags |= ECF_NOTHROW;
      }
*************** expand_call (exp, target, ignore)
*** 2845,2850 ****
--- 2860,2872 ----
  	  else
  	    for (i = num_actuals - 1; i >= 0; i--)
  	      note = gen_rtx_EXPR_LIST (VOIDmode, args[i].initial_value, note);
+ 
+ 	  if (flags & ECF_PURE)
+ 	    note = gen_rtx_EXPR_LIST (VOIDmode,
+ 	       gen_rtx_USE (VOIDmode,
+ 			    gen_rtx_MEM (BLKmode,
+ 				    	 gen_rtx_SCRATCH (VOIDmode))), note);
+ 
  	  note = gen_rtx_EXPR_LIST (VOIDmode, funexp, note);
  
  	  insns = get_insns ();


More information about the Gcc-patches mailing list