diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 04024683b7a..0d01767f7dd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2005-03-14 Zdenek Dvorak + + * 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 "no vops" 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. + 2005-03-14 Uros Bizjak PR target/17688 diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def index bfb70521bf2..971723de695 100644 --- a/gcc/builtin-attrs.def +++ b/gcc/builtin-attrs.def @@ -83,17 +83,22 @@ DEF_ATTR_IDENT (ATTR_GCC_DIAG, "gcc_diag") 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, "no vops") 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, \ diff --git a/gcc/builtins.def b/gcc/builtins.def index 33617c493b6..d324e01a584 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -134,7 +134,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 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) + 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 @@ -612,7 +612,7 @@ DEF_GCC_BUILTIN (BUILT_IN_POPCOUNT, "popcount", BT_FN_INT_UINT, ATTR_CONS 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_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) diff --git a/gcc/c-common.c b/gcc/c-common.c index d26c8b1452d..313b554249d 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -541,6 +541,7 @@ static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); 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, @@ -614,6 +615,10 @@ const struct attribute_spec c_common_attribute_table[] = handle_no_limit_stack_attribute }, { "pure", 0, 0, true, false, false, handle_pure_attribute }, + /* For internal use (marking of builtins) only. The name contains space + to prevent its usage in source code. */ + { "no vops", 0, 0, true, false, false, + handle_novops_attribute }, { "deprecated", 0, 0, false, false, false, handle_deprecated_attribute }, { "vector_size", 1, 1, false, true, false, @@ -4854,6 +4859,19 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args), return NULL_TREE; } +/* Handle a "no vops" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_novops_attribute (tree *node, tree ARG_UNUSED (name), + tree ARG_UNUSED (args), int ARG_UNUSED (flags), + bool *ARG_UNUSED (no_add_attrs)) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + DECL_IS_NOVOPS (*node) = 1; + return NULL_TREE; +} + /* Handle a "deprecated" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 400c6cf293b..eee7b66a7b5 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -1689,6 +1689,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) 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. */ diff --git a/gcc/calls.c b/gcc/calls.c index d6032fc78bc..4b9e051298d 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -593,6 +593,9 @@ flags_from_decl_or_type (tree exp) 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 841c7330a6c..24dc38a4acc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2005-03-14 Zdenek Dvorak + + * gcc.dg/tree-ssa/20050314-1.c: New test. + 2005-03-14 Kriang Lerdsuwanakij PR c++/4403 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20050314-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20050314-1.c new file mode 100644 index 00000000000..3f8cfb3f662 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20050314-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-lim-details" } */ + +float a[100]; + +int foo(void); +float sinf (float); + +void xxx (void) +{ + int i, k = foo (); + + for (i = 0; i < 100; i++) + a[k] += sinf (i); +} + +/* Store motion may be applied to the assignment to a[k], since sinf + cannot read nor write the memory. */ + +/* { dg-final { scan-tree-dump-times "Moving statement" 1 "lim" } } */ + diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 8db74e1fadb..2a63d0874a6 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1529,7 +1529,9 @@ get_call_expr_operands (tree stmt, tree expr) 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)) + 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 diff --git a/gcc/tree.h b/gcc/tree.h index 3857ff909cc..8854b7df8fd 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2185,6 +2185,11 @@ struct tree_binfo GTY (()) 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) @@ -2365,7 +2370,6 @@ struct tree_decl GTY(()) unsigned uninlinable : 1; unsigned thread_local_flag : 1; unsigned declared_inline_flag : 1; - unsigned seen_in_bind_expr : 1; ENUM_BITFIELD(symbol_visibility) visibility : 2; unsigned visibility_specified : 1; @@ -2383,7 +2387,9 @@ struct tree_decl GTY(()) unsigned gimple_formal_temp : 1; unsigned debug_expr_is_from : 1; unsigned returns_twice_flag : 1; - /* 11 unused bits. */ + unsigned seen_in_bind_expr : 1; + unsigned novops_flag : 1; + /* 9 unused bits. */ union tree_decl_u1 { /* In a FUNCTION_DECL for which DECL_BUILT_IN holds, this is @@ -3688,6 +3694,9 @@ extern rtx emit_line_note (location_t); #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);