diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 164bd56b48b..36097607bf9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2010-08-26 Jakub Jelinek + + PR tree-optimization/44485 + * calls.c (flags_from_decl_or_type): For const or pure + noreturn functions return ECF_LOOPING_CONST_OR_PURE|ECF_NORETURN + together with ECF_CONST resp. ECF_PURE. + * builtins.c (expand_builtin): Use flags_from_decl_or_type + instead of querying flags directly. + * tree-ssa-loop-niter.c (finite_loop_p): Likewise. + * tree-ssa-dce.c (find_obviously_necessary_stmts): Likewise. + 2010-08-26 Richard Guenther PR tree-optimization/45255 diff --git a/gcc/builtins.c b/gcc/builtins.c index e8974e1bbc2..6d755a1b5c7 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5748,6 +5748,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, tree fndecl = get_callee_fndecl (exp); enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); enum machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp)); + int flags; if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) return targetm.expand_builtin (exp, target, subtarget, mode, ignore); @@ -5770,8 +5771,8 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, none of its arguments are volatile, we can avoid expanding the built-in call and just evaluate the arguments for side-effects. */ if (target == const0_rtx - && (DECL_PURE_P (fndecl) || TREE_READONLY (fndecl)) - && !DECL_LOOPING_CONST_OR_PURE_P (fndecl)) + && ((flags = flags_from_decl_or_type (fndecl)) & (ECF_CONST | ECF_PURE)) + && !(flags & ECF_LOOPING_CONST_OR_PURE)) { bool volatilep = false; tree arg; diff --git a/gcc/calls.c b/gcc/calls.c index cd0d9c593f3..c50a79265f0 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -601,7 +601,7 @@ flags_from_decl_or_type (const_tree exp) flags |= ECF_RETURNS_TWICE; /* Process the pure and const attributes. */ - if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)) + if (TREE_READONLY (exp)) flags |= ECF_CONST; if (DECL_PURE_P (exp)) flags |= ECF_PURE; @@ -616,11 +616,15 @@ flags_from_decl_or_type (const_tree exp) flags = special_function_p (exp, flags); } - else if (TYPE_P (exp) && TYPE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)) + else if (TYPE_P (exp) && TYPE_READONLY (exp)) flags |= ECF_CONST; if (TREE_THIS_VOLATILE (exp)) - flags |= ECF_NORETURN; + { + flags |= ECF_NORETURN; + if (flags & (ECF_CONST|ECF_PURE)) + flags |= ECF_LOOPING_CONST_OR_PURE; + } return flags; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d27a2e2cf3c..8eb2f3a322f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-08-26 Jakub Jelinek + + PR tree-optimization/44485 + * gcc.dg/pr44485.c: New test. + 2010-08-26 Rainer Orth * gcc.dg/tls/thr-init-2.c: Use dg-add-options tls. diff --git a/gcc/testsuite/gcc.dg/pr44485.c b/gcc/testsuite/gcc.dg/pr44485.c new file mode 100644 index 00000000000..82f05f8ce6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr44485.c @@ -0,0 +1,31 @@ +/* PR tree-optimization/44485 */ +/* { dg-do compile } */ +/* { dg-options "-O1 -funsafe-math-optimizations" } */ + +unsigned short b; +int bar (unsigned); + +void +baz (void) +{ + if (bar (0)) + for (b = 0; b < 30; b++) + ; +} + +int +bar (unsigned z) +{ + unsigned short c; + for (; ; z += 1) +l1: + if (z) + goto l2; +l2: + for (z = 0; z < 9; z++) + if (z) + goto l1; + for (c = 0; c; c = (__UINTPTR_TYPE__) baz) + ; + return 0; +} diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index edec49d374f..a1a51914fa6 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -433,6 +433,7 @@ find_obviously_necessary_stmts (struct edge_list *el) gimple_stmt_iterator gsi; edge e; gimple phi, stmt; + int flags; FOR_EACH_BB (bb) { @@ -454,9 +455,8 @@ find_obviously_necessary_stmts (struct edge_list *el) /* Pure and const functions are finite and thus have no infinite loops in them. */ - if ((TREE_READONLY (current_function_decl) - || DECL_PURE_P (current_function_decl)) - && !DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)) + flags = flags_from_decl_or_type (current_function_decl); + if ((flags & (ECF_CONST|ECF_PURE)) && !(flags & ECF_LOOPING_CONST_OR_PURE)) return; /* Prevent the empty possibly infinite loops from being removed. */ diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 2630faf02fa..d23592dfa53 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -1970,12 +1970,12 @@ finite_loop_p (struct loop *loop) edge ex; struct tree_niter_desc desc; bool finite = false; + int flags; if (flag_unsafe_loop_optimizations) return true; - if ((TREE_READONLY (current_function_decl) - || DECL_PURE_P (current_function_decl)) - && !DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)) + flags = flags_from_decl_or_type (current_function_decl); + if ((flags & (ECF_CONST|ECF_PURE)) && !(flags & ECF_LOOPING_CONST_OR_PURE)) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Found loop %i to be finite: it is within pure or const function.\n",