+2018-06-01 Richard Biener <rguenther@suse.de>
+
+ PR ipa/85960
+ * tree-ssa-structalias.c (get_function_part_constraint):
+ Handle NULL fi->decl.
+ (find_func_aliases_for_call): Properly handle indirect
+ fi from direct call.
+ (find_func_clobbers): Likewise.
+ (ipa_pta_execute): Likewise.
+ (create_variable_info_for): For functions that are ifunc_resolver
+ resolve to a varinfo that contains the result of the resolver
+ call.
+ (associate_varinfo_to_alias): Do not treat ifunc resolvers as
+ aliases.
+
2018-05-31 Michael Collison <michael.collison@arm.com>
* config/aarch64/aarch64.md:
--- /dev/null
+/* { dg-do run } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O2 -fipa-pta" } */
+
+#include <stdlib.h>
+#include <stdbool.h>
+
+#define hot __attribute__((hot))
+
+static hot void multiver_default(unsigned int in, bool *ret)
+{
+ if ( in & 1 ) {
+ *ret = false;
+ }else{
+ *ret = true;
+ }
+}
+
+static void (*resolve_multiver(void))(unsigned int in, bool *out)
+{
+ return &multiver_default;
+}
+
+__attribute__ ((ifunc("resolve_multiver")))
+static void multiver_test(unsigned int val, bool *ret);
+
+static hot bool do_test(unsigned int val)
+{
+ bool ret = false;
+
+ multiver_test(val, &ret);
+
+ return (ret == !(val & 0x1));
+}
+
+volatile unsigned int x = 2;
+int main()
+{
+ int i;
+ for(i = 1; i < x; i++) {
+ unsigned int val = x;
+ if ( !do_test(val) )
+ abort ();
+ }
+ return 0;
+}
c.offset = 0;
c.type = SCALAR;
}
- else if (TREE_CODE (fi->decl) == FUNCTION_DECL)
+ else if (fi->decl && TREE_CODE (fi->decl) == FUNCTION_DECL)
{
varinfo_t ai = first_vi_for_offset (fi, part);
if (ai)
fi = get_fi_for_callee (t);
if (!in_ipa_mode
- || (fndecl && !fi->is_fn_info))
+ || (fi->decl && fndecl && !fi->is_fn_info))
{
auto_vec<ce_s, 16> rhsc;
int flags = gimple_call_flags (t);
/* For callees without function info (that's external functions),
ESCAPED is clobbered and used. */
- if (gimple_call_fndecl (t)
+ if (cfi->decl
&& !cfi->is_fn_info)
{
varinfo_t vi;
static unsigned int
create_variable_info_for (tree decl, const char *name, bool add_id)
{
+ /* First see if we are dealing with an ifunc resolver call and
+ assiociate that with a call to the resolver function result. */
+ cgraph_node *node;
+ if (in_ipa_mode
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && (node = cgraph_node::get (decl))->ifunc_resolver)
+ {
+ varinfo_t fi = get_vi_for_tree (node->get_alias_target ()->decl);
+ constraint_expr rhs
+ = get_function_part_constraint (fi, fi_result);
+ fi = new_var_info (NULL_TREE, "ifuncres", true);
+ fi->is_reg_var = true;
+ constraint_expr lhs;
+ lhs.type = SCALAR;
+ lhs.var = fi->id;
+ lhs.offset = 0;
+ process_constraint (new_constraint (lhs, rhs));
+ insert_vi_for_tree (decl, fi);
+ return fi->id;
+ }
+
varinfo_t vi = create_variable_info_for_1 (decl, name, add_id, false, NULL);
unsigned int id = vi->id;
if ((node->alias
|| (node->thunk.thunk_p
&& ! node->global.inlined_to))
- && node->analyzed)
+ && node->analyzed
+ && !node->ifunc_resolver)
insert_vi_for_tree (node->decl, (varinfo_t)data);
return false;
}
(node->decl, first_vi_for_offset (fi, fi_uses));
}
/* Handle direct calls to external functions. */
- else if (decl)
+ else if (decl && (!fi || fi->decl))
{
pt = gimple_call_use_set (stmt);
if (gimple_call_flags (stmt) & ECF_CONST)
}
}
/* Handle indirect calls. */
- else if (!decl
- && (fi = get_fi_for_callee (stmt)))
+ else if ((fi = get_fi_for_callee (stmt)))
{
/* We need to accumulate all clobbers/uses of all possible
callees. */
}
}
}
+ else
+ gcc_unreachable ();
}
}