#include "attr-fnspec.h"
#include "gimple-range.h"
#include "value-range-storage.h"
+#include "vr-values.h"
/* Function summary where the parameter infos are actually stored. */
ipa_node_params_t *ipa_node_params_sum = NULL;
ipa_set_jfunc_vr (jf, tmp);
}
+
+/* If T is an SSA_NAME that is the result of a simple type conversion statement
+ from an integer type to another integer type which is known to be able to
+ represent the values the operand of the conversion can hold, return the
+ operand of that conversion, otherwise return T. */
+
+static tree
+skip_a_safe_conversion_op (tree t)
+{
+ if (TREE_CODE (t) != SSA_NAME
+ || SSA_NAME_IS_DEFAULT_DEF (t))
+ return t;
+
+ gimple *def = SSA_NAME_DEF_STMT (t);
+ if (!is_gimple_assign (def)
+ || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))
+ || !INTEGRAL_TYPE_P (TREE_TYPE (t))
+ || !INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def))))
+ return t;
+
+ tree rhs1 = gimple_assign_rhs1 (def);
+ if (TYPE_PRECISION (TREE_TYPE (t))
+ >= TYPE_PRECISION (TREE_TYPE (rhs1)))
+ return gimple_assign_rhs1 (def);
+
+ value_range vr (TREE_TYPE (rhs1));
+ if (!get_range_query (cfun)->range_of_expr (vr, rhs1, def)
+ || vr.undefined_p ())
+ return t;
+
+ irange &ir = as_a <irange> (vr);
+ if (range_fits_type_p (&ir, TYPE_PRECISION (TREE_TYPE (t)),
+ TYPE_SIGN (TREE_TYPE (t))))
+ return gimple_assign_rhs1 (def);
+
+ return t;
+}
+
/* Compute jump function for all arguments of callsite CS and insert the
information in the jump_functions array in the ipa_edge_args corresponding
to this callsite. */
gcc_assert (!jfunc->m_vr);
}
+ arg = skip_a_safe_conversion_op (arg);
if (is_gimple_ip_invariant (arg)
|| (VAR_P (arg)
&& is_global_var (arg)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int some_f1 (int);
+int some_f2 (int);
+int some_f3 (int);
+
+void remove_this_call ();
+
+int g;
+
+static int __attribute__((noinline))
+bar (int p)
+{
+ if (p)
+ remove_this_call ();
+ return g++;
+}
+
+static int __attribute__((noinline))
+foo (int (*f)(int))
+{
+ return bar (f == (void *)0);
+}
+
+int
+baz1 (void)
+{
+ int (*f)(int);
+ if (g)
+ f = some_f1;
+ else
+ f = some_f2;
+ return foo (f);
+}
+
+int
+baz2 (void)
+{
+ int (*f)(int);
+ if (g)
+ f = some_f2;
+ else
+ f = some_f3;
+ return foo (f);
+}
+
+/* { dg-final { scan-tree-dump-not "remove_this_call" "optimized" } } */