#include "output.h"
#include "flags.h"
#include "timevar.h"
-#include "toplev.h"
#include "diagnostic.h"
#include "gimple-pretty-print.h"
#include "langhooks.h"
bool can_throw;
};
+/* State used when we know nothing about function. */
+static struct funct_state_d varying_state
+ = { IPA_NEITHER, IPA_NEITHER, true, true, true };
+
+
typedef struct funct_state_d * funct_state;
/* The storage of the funct_state is abstracted because there is the
struct pointer_set_t *warned_about,
const char * attrib_name)
{
- if (!option_enabled (option))
+ if (!option_enabled (option, &global_options))
return warned_about;
if (TREE_THIS_VOLATILE (decl)
|| (known_finite && function_always_visible_to_compiler_p (decl)))
static inline funct_state
get_function_state (struct cgraph_node *node)
{
- static struct funct_state_d varying
- = { IPA_NEITHER, IPA_NEITHER, true, true, true };
if (!funct_state_vec
- || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid)
+ || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid
+ || !VEC_index (funct_state, funct_state_vec, node->uid))
/* We might want to put correct previously_known state into varying. */
- return &varying;
- return VEC_index (funct_state, funct_state_vec, node->uid);
+ return &varying_state;
+ return VEC_index (funct_state, funct_state_vec, node->uid);
}
/* Set the function state S for NODE. */
return;
}
else if (t
- && INDIRECT_REF_P (t)
+ && (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF)
&& TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME
&& !ptr_deref_may_alias_global_p (TREE_OPERAND (t, 0)))
{
/* Recognize special cases of builtins that are by themself not pure or const
but function using them is. */
static bool
-special_builtlin_state (enum pure_const_state_e *state, bool *looping,
+special_builtin_state (enum pure_const_state_e *state, bool *looping,
tree callee)
{
if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
case BUILT_IN_FRAME_ADDRESS:
case BUILT_IN_APPLY:
case BUILT_IN_APPLY_ARGS:
- case BUILT_IN_ARGS_INFO:
*looping = false;
*state = IPA_CONST;
return true;
enum pure_const_state_e call_state;
bool call_looping;
- if (special_builtlin_state (&call_state, &call_looping, callee_t))
+ if (special_builtin_state (&call_state, &call_looping, callee_t))
{
worse_state (&local->pure_const_state, &local->looping,
call_state, call_looping);
print_gimple_stmt (dump_file, stmt, 0, 0);
}
+ if (gimple_has_volatile_ops (stmt))
+ {
+ local->pure_const_state = IPA_NEITHER;
+ if (dump_file)
+ fprintf (dump_file, " Volatile stmt is not const/pure\n");
+ }
+
/* Look for loads and stores. */
walk_stmt_load_store_ops (stmt, local,
ipa ? check_ipa_load : check_load,
{
if (has_function_state (node))
{
- free (get_function_state (node));
+ funct_state l = get_function_state (node);
+ if (l != &varying_state)
+ free (l);
set_function_state (node, NULL);
}
}
edge_looping = y_l->looping;
}
}
- else if (special_builtlin_state (&edge_state, &edge_looping,
+ else if (special_builtin_state (&edge_state, &edge_looping,
y->decl))
;
else
this_looping ? "looping " : "",
cgraph_node_name (w));
}
- cgraph_set_readonly_flag (w, true);
- cgraph_set_looping_const_or_pure_flag (w, this_looping);
+ cgraph_set_const_flag (w, true, this_looping);
break;
case IPA_PURE:
this_looping ? "looping " : "",
cgraph_node_name (w));
}
- cgraph_set_pure_flag (w, true);
- cgraph_set_looping_const_or_pure_flag (w, this_looping);
+ cgraph_set_pure_flag (w, true, this_looping);
break;
default:
&& skip)
return 0;
- /* First do NORETURN discovery. */
+ l = analyze_function (node, false);
+
+ /* Do NORETURN discovery. */
if (!skip && !TREE_THIS_VOLATILE (current_function_decl)
&& EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0)
{
changed = true;
}
- l = analyze_function (node, false);
switch (l->pure_const_state)
{
warn_function_const (current_function_decl, !l->looping);
if (!skip)
{
- cgraph_set_readonly_flag (node, true);
- cgraph_set_looping_const_or_pure_flag (node, l->looping);
+ cgraph_set_const_flag (node, true, l->looping);
changed = true;
}
if (dump_file)
{
if (!skip)
{
- cgraph_set_looping_const_or_pure_flag (node, false);
+ cgraph_set_const_flag (node, true, false);
changed = true;
}
if (dump_file)
{
if (!skip)
{
- cgraph_set_pure_flag (node, true);
- cgraph_set_looping_const_or_pure_flag (node, l->looping);
+ cgraph_set_pure_flag (node, true, l->looping);
changed = true;
}
warn_function_pure (current_function_decl, !l->looping);
{
if (!skip)
{
- cgraph_set_looping_const_or_pure_flag (node, false);
+ cgraph_set_pure_flag (node, true, false);
changed = true;
}
if (dump_file)