[patch] Avoid virtual operands for trigonometric builtins

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Tue Mar 8 23:06:00 GMT 2005


Hello,

some of builtins are declared 'pure' (or not even that), but still they
do not read memory.  This includes functions like sin (that checks the
rounding mode, thus cannot be const), or prefetch (that has side
effect), and probably other builtins.  It is obviously unnecessary to
have virtual operands for calls of these functions.

This patch adds new attribute 'novops' that prevents adding the virtual
operands to the function call, and applies it to the mentioned builtins.
I don't think it is desirable for users to have access to this attribute
(it seems quite error-prone), so I do not add it to the documentation.

Bootstrapped & regtested on i686 and ppc.

Zdenek

	* builtin-attrs.def (ATTR_NOVOPS, ATTR_NOVOPS_LIST,
	ATTR_PURE_NOTHROW_NOVOPS_LIST): New.
	* builtins.def (ATTR_MATHFN_FPROUNDING): Use NOVOPS.
	(BUILT_IN_PREFETCH): Set the NOVOPS attribute.
	* c-common.c (handle_novops_attribute): New function.
	(c_common_attribute_table): Add novops entry.
	* c-decl.c (merge_decls): Copy DECL_IS_NOVOPS.
	* calls.c (flags_from_decl_or_type): Set ECF_NOVOPS.
	* tree-ssa-operands.c (get_call_expr_operands): Do not
	create virtual operands for calls with ECF_NOVOPS flag.
	* tree.h (DECL_IS_NOVOPS): New macro.
	(struct tree_decl): Add novops_flag.
	(ECF_NOVOPS): New constant.

Index: builtin-attrs.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtin-attrs.def,v
retrieving revision 1.16
diff -c -3 -p -r1.16 builtin-attrs.def
*** builtin-attrs.def	15 Oct 2004 14:47:06 -0000	1.16
--- builtin-attrs.def	8 Mar 2005 22:58:31 -0000
*************** DEF_ATTR_IDENT (ATTR_GCC_DIAG, "gcc_diag
*** 83,99 ****
--- 83,104 ----
  DEF_ATTR_IDENT (ATTR_GCC_CDIAG, "gcc_cdiag")
  DEF_ATTR_IDENT (ATTR_GCC_CXXDIAG, "gcc_cxxdiag")
  DEF_ATTR_IDENT (ATTR_PURE, "pure")
+ DEF_ATTR_IDENT (ATTR_NOVOPS, "novops")
  DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
  DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel")
  DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
  DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
  
+ DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
+ 
  DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LIST, ATTR_NOTHROW, ATTR_NULL, ATTR_NULL)
  
  DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LIST, ATTR_CONST,	\
  			ATTR_NULL, ATTR_NOTHROW_LIST)
  DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_LIST, ATTR_PURE,		\
  			ATTR_NULL, ATTR_NOTHROW_LIST)
+ DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NOVOPS_LIST, ATTR_NOVOPS,	\
+ 			ATTR_NULL, ATTR_PURE_NOTHROW_LIST)
  DEF_ATTR_TREE_LIST (ATTR_NORETURN_NOTHROW_LIST, ATTR_NORETURN,	\
  			ATTR_NULL, ATTR_NOTHROW_LIST)
  DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_LIST, ATTR_MALLOC,	\
Index: builtins.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.def,v
retrieving revision 1.95
diff -c -3 -p -r1.95 builtins.def
*** builtins.def	10 Feb 2005 18:59:04 -0000	1.95
--- builtins.def	8 Mar 2005 22:58:31 -0000
*************** Software Foundation, 59 Temple Place - S
*** 134,140 ****
     global memory.  In "unsafe" mode we can be less careful.  */
  #undef ATTR_MATHFN_FPROUNDING
  #define ATTR_MATHFN_FPROUNDING (flag_unsafe_math_optimizations ? \
! 	ATTR_CONST_NOTHROW_LIST : ATTR_PURE_NOTHROW_LIST)
  
  /* Define an attribute list for math functions that are normally
     "impure" because some of them may write into global memory for
--- 134,140 ----
     global memory.  In "unsafe" mode we can be less careful.  */
  #undef ATTR_MATHFN_FPROUNDING
  #define ATTR_MATHFN_FPROUNDING (flag_unsafe_math_optimizations ? \
! 	ATTR_CONST_NOTHROW_LIST : ATTR_PURE_NOTHROW_NOVOPS_LIST)
  
  /* Define an attribute list for math functions that are normally
     "impure" because some of them may write into global memory for
*************** DEF_GCC_BUILTIN        (BUILT_IN_POPCOUN
*** 612,618 ****
  DEF_GCC_BUILTIN        (BUILT_IN_POPCOUNTIMAX, "popcountimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_POPCOUNTL, "popcountl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_POPCOUNTLL, "popcountll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LIST)
! DEF_GCC_BUILTIN        (BUILT_IN_PREFETCH, "prefetch", BT_FN_VOID_CONST_PTR_VAR, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UINT, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
--- 612,618 ----
  DEF_GCC_BUILTIN        (BUILT_IN_POPCOUNTIMAX, "popcountimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_POPCOUNTL, "popcountl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_POPCOUNTLL, "popcountll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LIST)
! DEF_GCC_BUILTIN        (BUILT_IN_PREFETCH, "prefetch", BT_FN_VOID_CONST_PTR_VAR, ATTR_NOVOPS_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LIST)
  DEF_GCC_BUILTIN        (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UINT, ATTR_NULL)
  DEF_GCC_BUILTIN        (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.608
diff -c -3 -p -r1.608 c-common.c
*** c-common.c	8 Mar 2005 13:56:51 -0000	1.608
--- c-common.c	8 Mar 2005 22:58:31 -0000
*************** static tree handle_returns_twice_attribu
*** 541,546 ****
--- 541,547 ----
  static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
  					     bool *);
  static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+ static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
  static tree handle_deprecated_attribute (tree *, tree, tree, int,
  					 bool *);
  static tree handle_vector_size_attribute (tree *, tree, tree, int,
*************** const struct attribute_spec c_common_att
*** 614,619 ****
--- 615,622 ----
  			      handle_no_limit_stack_attribute },
    { "pure",                   0, 0, true,  false, false,
  			      handle_pure_attribute },
+   { "novops",                 0, 0, true,  false, false,
+ 			      handle_novops_attribute },
    { "deprecated",             0, 0, false, false, false,
  			      handle_deprecated_attribute },
    { "vector_size",	      1, 1, false, true, false,
*************** handle_pure_attribute (tree *node, tree 
*** 4854,4859 ****
--- 4857,4880 ----
    return NULL_TREE;
  }
  
+ /* Handle a "novops" attribute; arguments as in
+    struct attribute_spec.handler.  */
+ 
+ static tree
+ handle_novops_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ 			 int ARG_UNUSED (flags), bool *no_add_attrs)
+ {
+   if (TREE_CODE (*node) == FUNCTION_DECL)
+     DECL_IS_NOVOPS (*node) = 1;
+   else
+     {
+       warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+       *no_add_attrs = true;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
  /* Handle a "deprecated" attribute; arguments as in
     struct attribute_spec.handler.  */
  
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.633
diff -c -3 -p -r1.633 c-decl.c
*** c-decl.c	7 Mar 2005 21:14:08 -0000	1.633
--- c-decl.c	8 Mar 2005 22:58:32 -0000
*************** merge_decls (tree newdecl, tree olddecl,
*** 1689,1694 ****
--- 1689,1695 ----
        TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
        DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
        DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+       DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
      }
  
    /* Merge the storage class information.  */
Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.381
diff -c -3 -p -r1.381 calls.c
*** calls.c	8 Mar 2005 13:19:32 -0000	1.381
--- calls.c	8 Mar 2005 22:58:32 -0000
*************** flags_from_decl_or_type (tree exp)
*** 593,598 ****
--- 593,601 ----
        if (DECL_IS_PURE (exp))
  	flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
  
+       if (DECL_IS_NOVOPS (exp))
+ 	flags |= ECF_NOVOPS;
+ 
        if (TREE_NOTHROW (exp))
  	flags |= ECF_NOTHROW;
  
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.64
diff -c -3 -p -r2.64 tree-ssa-operands.c
*** tree-ssa-operands.c	7 Mar 2005 13:58:08 -0000	2.64
--- tree-ssa-operands.c	8 Mar 2005 22:58:32 -0000
*************** get_call_expr_operands (tree stmt, tree 
*** 1465,1471 ****
       computed.  By not bothering with virtual operands for CALL_EXPRs
       we avoid adding superfluous virtual operands, which can be a
       significant compile time sink (See PR 15855).  */
!   if (aliases_computed_p && !bitmap_empty_p (call_clobbered_vars))
      {
        /* A 'pure' or a 'const' functions never call clobber anything. 
  	 A 'noreturn' function might, but since we don't return anyway 
--- 1465,1473 ----
       computed.  By not bothering with virtual operands for CALL_EXPRs
       we avoid adding superfluous virtual operands, which can be a
       significant compile time sink (See PR 15855).  */
!   if (aliases_computed_p
!       && !bitmap_empty_p (call_clobbered_vars)
!       && !(call_flags & ECF_NOVOPS))
      {
        /* A 'pure' or a 'const' functions never call clobber anything. 
  	 A 'noreturn' function might, but since we don't return anyway 
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.700
diff -c -3 -p -r1.700 tree.h
*** tree.h	8 Mar 2005 13:57:01 -0000	1.700
--- tree.h	8 Mar 2005 22:58:32 -0000
*************** struct tree_binfo GTY (())
*** 2185,2190 ****
--- 2185,2195 ----
     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 FUNCTION_DECL means this function should be treated
+    as "novops" function (function that does not read global memory,
+    but may have arbitrary side effects).  */
+ #define DECL_IS_NOVOPS(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.novops_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 GTY(())
*** 2359,2364 ****
--- 2364,2370 ----
    unsigned no_limit_stack : 1;
    ENUM_BITFIELD(built_in_class) built_in_class : 2;
    unsigned pure_flag : 1;
+   unsigned novops_flag : 1;
  
    unsigned non_addressable : 1;
    unsigned user_align : 1;
*************** struct tree_decl GTY(())
*** 2383,2389 ****
    unsigned gimple_formal_temp : 1;
    unsigned debug_expr_is_from : 1;
    unsigned returns_twice_flag : 1;
!   /* 11 unused bits.  */
  
    union tree_decl_u1 {
      /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
--- 2389,2395 ----
    unsigned gimple_formal_temp : 1;
    unsigned debug_expr_is_from : 1;
    unsigned returns_twice_flag : 1;
!   /* 10 unused bits.  */
  
    union tree_decl_u1 {
      /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is
*************** extern rtx emit_line_note (location_t);
*** 3688,3693 ****
--- 3694,3702 ----
  #define ECF_SP_DEPRESSED	256
  /* Create libcall block around the call.  */
  #define ECF_LIBCALL_BLOCK	512
+ /* Function does not read or write memory (but may have side effects, so
+    it does not necessarily fit ECF_CONST).  */
+ #define ECF_NOVOPS		1024
  
  extern int flags_from_decl_or_type (tree);
  extern int call_expr_flags (tree);



More information about the Gcc-patches mailing list