summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-20 08:21:25 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2011-04-20 08:21:25 +0000
commitfb049fbac341de8b83c1e9aef4855ab69697430a (patch)
tree302de9b13283837581d6bef410f79f930039eedc
parent8102101361cc08f95bc8b313bbba2cb6ee91ede8 (diff)
downloadgcc-fb049fbac341de8b83c1e9aef4855ab69697430a.tar.gz
gcc/
* Makefile.in (INTERNAL_FN_DEF, INTERNAL_FN_H): Define. (GIMPLE_H): Include $(INTERNAL_FN_H). (OBJS-common): Add internal-fn.o. (internal-fn.o): New rule. * internal-fn.def: New file. * internal-fn.h: Likewise. * internal-fn.c: Likewise. * gimple.h: Include internal-fn.h. (GF_CALL_INTERNAL): New gf_mask. (gimple_statement_call): Put fntype into a union with a new internal_fn field. (gimple_build_call_internal): Declare. (gimple_build_call_internal_vec): Likewise. (gimple_call_same_target_p): Likewise. (gimple_call_internal_p): New function. (gimple_call_internal_fn): Likewise. (gimple_call_fntype): Return null for internal calls. (gimple_call_set_fntype): Assert that the function is not internal. (gimple_call_set_fn): Likewise. (gimple_call_set_fndecl): Likewise. (gimple_call_set_internal_fn): New function. (gimple_call_addr_fndecl): Handle null functions. (gimple_call_return_type): Likewise null types. * gimple.c (gimple_build_call_internal_1): New function. (gimple_build_call_internal): Likewise. (gimple_build_call_internal_vec): Likewise. (gimple_call_same_target_p): Likewise. (gimple_call_flags): Handle calls to internal functions. (gimple_call_fnspec): New function. (gimple_call_arg_flags, gimple_call_return_flags): Use it. (gimple_has_side_effects): Handle null functions. (gimple_rhs_has_side_effects): Likewise. (gimple_call_copy_skip_args): Handle calls to internal functions. * cfgexpand.c (expand_call_stmt): Likewise. * expr.c (expand_expr_real_1): Assert that the call isn't internal. * gimple-fold.c (gimple_fold_call): Handle null functions. (gimple_fold_stmt_to_constant_1): Don't fold calls to internal functions. * gimple-low.c (gimple_check_call_args): Handle calls to internal functions. * gimple-pretty-print.c (dump_gimple_call): Likewise. * ipa-prop.c (ipa_analyze_call_uses): Handle null functions. * tree-cfg.c (verify_gimple_call): Handle calls to internal functions. (do_warn_unused_result): Likewise. * tree-eh.c (same_handler_p): Use gimple_call_same_target_p. * tree-ssa-ccp.c (ccp_fold_stmt): Handle calls to internal functions. * tree-ssa-dom.c (hashable_expr): Use the gimple statement to record the target of a call. (initialize_hash_element): Update accordingly. (hashable_expr_equal_p): Use gimple_call_same_target_p. (iterative_hash_hashable_expr): Handle calls to internal functions. (print_expr_hash_elt): Likewise. * tree-ssa-pre.c (can_value_number_call): Likewise. (eliminate): Handle null functions. * tree-ssa-sccvn.c (visit_use): Handle calls to internal functions. * tree-ssa-structalias.c (get_fi_for_callee): Likewise. (find_func_aliases): Likewise. * value-prof.c (gimple_ic_transform): Likewise. (gimple_indirect_call_to_profile): Likewise. * lto-streamer-in.c (input_gimple_stmt): Likewise. * lto-streamer-out.c (output_gimple_stmt): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@172758 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog64
-rw-r--r--gcc/Makefile.in9
-rw-r--r--gcc/cfgexpand.c9
-rw-r--r--gcc/expr.c9
-rw-r--r--gcc/gimple-fold.c10
-rw-r--r--gcc/gimple-low.c4
-rw-r--r--gcc/gimple-pretty-print.c13
-rw-r--r--gcc/gimple.c123
-rw-r--r--gcc/gimple.h57
-rw-r--r--gcc/internal-fn.c64
-rw-r--r--gcc/internal-fn.def39
-rw-r--r--gcc/internal-fn.h51
-rw-r--r--gcc/ipa-prop.c2
-rw-r--r--gcc/lto-streamer-in.c8
-rw-r--r--gcc/lto-streamer-out.c7
-rw-r--r--gcc/tree-cfg.c32
-rw-r--r--gcc/tree-eh.c2
-rw-r--r--gcc/tree-ssa-ccp.c5
-rw-r--r--gcc/tree-ssa-dom.c26
-rw-r--r--gcc/tree-ssa-pre.c6
-rw-r--r--gcc/tree-ssa-sccvn.c3
-rw-r--r--gcc/tree-ssa-structalias.c3
-rw-r--r--gcc/value-prof.c4
23 files changed, 498 insertions, 52 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9ca4ae40b68..e9b126bbd63 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,67 @@
+2011-04-20 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * Makefile.in (INTERNAL_FN_DEF, INTERNAL_FN_H): Define.
+ (GIMPLE_H): Include $(INTERNAL_FN_H).
+ (OBJS-common): Add internal-fn.o.
+ (internal-fn.o): New rule.
+ * internal-fn.def: New file.
+ * internal-fn.h: Likewise.
+ * internal-fn.c: Likewise.
+ * gimple.h: Include internal-fn.h.
+ (GF_CALL_INTERNAL): New gf_mask.
+ (gimple_statement_call): Put fntype into a union with a new
+ internal_fn field.
+ (gimple_build_call_internal): Declare.
+ (gimple_build_call_internal_vec): Likewise.
+ (gimple_call_same_target_p): Likewise.
+ (gimple_call_internal_p): New function.
+ (gimple_call_internal_fn): Likewise.
+ (gimple_call_fntype): Return null for internal calls.
+ (gimple_call_set_fntype): Assert that the function is not internal.
+ (gimple_call_set_fn): Likewise.
+ (gimple_call_set_fndecl): Likewise.
+ (gimple_call_set_internal_fn): New function.
+ (gimple_call_addr_fndecl): Handle null functions.
+ (gimple_call_return_type): Likewise null types.
+ * gimple.c (gimple_build_call_internal_1): New function.
+ (gimple_build_call_internal): Likewise.
+ (gimple_build_call_internal_vec): Likewise.
+ (gimple_call_same_target_p): Likewise.
+ (gimple_call_flags): Handle calls to internal functions.
+ (gimple_call_fnspec): New function.
+ (gimple_call_arg_flags, gimple_call_return_flags): Use it.
+ (gimple_has_side_effects): Handle null functions.
+ (gimple_rhs_has_side_effects): Likewise.
+ (gimple_call_copy_skip_args): Handle calls to internal functions.
+ * cfgexpand.c (expand_call_stmt): Likewise.
+ * expr.c (expand_expr_real_1): Assert that the call isn't internal.
+ * gimple-fold.c (gimple_fold_call): Handle null functions.
+ (gimple_fold_stmt_to_constant_1): Don't fold
+ calls to internal functions.
+ * gimple-low.c (gimple_check_call_args): Handle calls to internal
+ functions.
+ * gimple-pretty-print.c (dump_gimple_call): Likewise.
+ * ipa-prop.c (ipa_analyze_call_uses): Handle null functions.
+ * tree-cfg.c (verify_gimple_call): Handle calls to internal functions.
+ (do_warn_unused_result): Likewise.
+ * tree-eh.c (same_handler_p): Use gimple_call_same_target_p.
+ * tree-ssa-ccp.c (ccp_fold_stmt): Handle calls to internal functions.
+ * tree-ssa-dom.c (hashable_expr): Use the gimple statement to record
+ the target of a call.
+ (initialize_hash_element): Update accordingly.
+ (hashable_expr_equal_p): Use gimple_call_same_target_p.
+ (iterative_hash_hashable_expr): Handle calls to internal functions.
+ (print_expr_hash_elt): Likewise.
+ * tree-ssa-pre.c (can_value_number_call): Likewise.
+ (eliminate): Handle null functions.
+ * tree-ssa-sccvn.c (visit_use): Handle calls to internal functions.
+ * tree-ssa-structalias.c (get_fi_for_callee): Likewise.
+ (find_func_aliases): Likewise.
+ * value-prof.c (gimple_ic_transform): Likewise.
+ (gimple_indirect_call_to_profile): Likewise.
+ * lto-streamer-in.c (input_gimple_stmt): Likewise.
+ * lto-streamer-out.c (output_gimple_stmt): Likewise.
+
2011-04-19 Jan Hubicka <jh@suse.cz>
* ipa-inline-transform.c (save_inline_function_body): Add comments.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index e300a6c8ca6..68cf1ace61e 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -893,6 +893,8 @@ RTL_ERROR_H = $(RTL_H) $(DIAGNOSTIC_CORE_H)
READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
PARAMS_H = params.h params.def
BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def
+INTERNAL_FN_DEF = internal-fn.def
+INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
TREE_H = tree.h all-tree.def tree.def c-family/c-common.def \
$(lang_tree_files) $(MACHMODE_H) tree-check.h $(BUILTINS_DEF) \
$(INPUT_H) statistics.h $(VEC_H) treestruct.def $(HASHTAB_H) \
@@ -901,8 +903,8 @@ TREE_H = tree.h all-tree.def tree.def c-family/c-common.def \
REGSET_H = regset.h $(BITMAP_H) hard-reg-set.h
BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) cfghooks.h
GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \
- $(GGC_H) $(BASIC_BLOCK_H) $(TARGET_H) tree-ssa-operands.h \
- tree-ssa-alias.h vecir.h
+ vecir.h $(GGC_H) $(BASIC_BLOCK_H) $(TARGET_H) tree-ssa-operands.h \
+ tree-ssa-alias.h $(INTERNAL_FN_H)
GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
COVERAGE_H = coverage.h $(GCOV_IO_H)
DEMANGLE_H = $(srcdir)/../include/demangle.h
@@ -1274,6 +1276,7 @@ OBJS-common = \
init-regs.o \
input.o \
integrate.o \
+ internal-fn.o \
intl.o \
ira.o \
ira-build.o \
@@ -2760,6 +2763,8 @@ tree-object-size.o: tree-object-size.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) \
$(TREE_PASS_H) tree-ssa-propagate.h tree-pretty-print.h \
gimple-pretty-print.h
+internal-fn.o : internal-fn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(INTERNAL_FN_H) $(TREE_H) $(EXPR_H) $(OPTABS_H) $(GIMPLE_H)
gimple.o : gimple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
$(GGC_H) $(GIMPLE_H) $(DIAGNOSTIC_CORE_H) $(DIAGNOSTIC_H) gt-gimple.h \
$(TREE_FLOW_H) value-prof.h $(FLAGS_H) $(DEMANGLE_H) \
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index effb844ac66..a3abc8497df 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -1837,10 +1837,16 @@ expand_gimple_cond (basic_block bb, gimple stmt)
static void
expand_call_stmt (gimple stmt)
{
- tree exp, decl, lhs = gimple_call_lhs (stmt);
+ tree exp, decl, lhs;
bool builtin_p;
size_t i;
+ if (gimple_call_internal_p (stmt))
+ {
+ expand_internal_call (stmt);
+ return;
+ }
+
exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
CALL_EXPR_FN (exp) = gimple_call_fn (stmt);
@@ -1890,6 +1896,7 @@ expand_call_stmt (gimple stmt)
SET_EXPR_LOCATION (exp, gimple_location (stmt));
TREE_BLOCK (exp) = gimple_block (stmt);
+ lhs = gimple_call_lhs (stmt);
if (lhs)
expand_assignment (lhs, exp, false);
else
diff --git a/gcc/expr.c b/gcc/expr.c
index 1bafe6a2d04..8040d5116b8 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -8528,9 +8528,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (code == SSA_NAME
&& (g = SSA_NAME_DEF_STMT (ssa_name))
&& gimple_code (g) == GIMPLE_CALL)
- pmode = promote_function_mode (type, mode, &unsignedp,
- gimple_call_fntype (g),
- 2);
+ {
+ gcc_assert (!gimple_call_internal_p (g));
+ pmode = promote_function_mode (type, mode, &unsignedp,
+ gimple_call_fntype (g),
+ 2);
+ }
else
pmode = promote_decl_mode (exp, &unsignedp);
gcc_assert (GET_MODE (decl_rtl) == pmode);
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 8d3ab6eb1ff..f4251191c60 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1541,7 +1541,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
/* Check for virtual calls that became direct calls. */
callee = gimple_call_fn (stmt);
- if (TREE_CODE (callee) == OBJ_TYPE_REF)
+ if (callee && TREE_CODE (callee) == OBJ_TYPE_REF)
{
tree binfo, fndecl, delta, obj;
HOST_WIDE_INT token;
@@ -2958,7 +2958,13 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
case GIMPLE_CALL:
{
- tree fn = (*valueize) (gimple_call_fn (stmt));
+ tree fn;
+
+ if (gimple_call_internal_p (stmt))
+ /* No folding yet for these functions. */
+ return NULL_TREE;
+
+ fn = (*valueize) (gimple_call_fn (stmt));
if (TREE_CODE (fn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_BUILT_IN (TREE_OPERAND (fn, 0)))
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 01aeb4940d3..3afa0b2582d 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -219,6 +219,10 @@ gimple_check_call_args (gimple stmt, tree fndecl)
tree parms, p;
unsigned int i, nargs;
+ /* Calls to internal functions always match their signature. */
+ if (gimple_call_internal_p (stmt))
+ return true;
+
nargs = gimple_call_num_args (stmt);
/* Get argument types for verification. */
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index d841929fd84..b27b1a5b061 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -616,8 +616,12 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
if (flags & TDF_RAW)
{
- dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T",
- gs, gimple_call_fn (gs), lhs);
+ if (gimple_call_internal_p (gs))
+ dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T", gs,
+ internal_fn_name (gimple_call_internal_fn (gs)), lhs);
+ else
+ dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T",
+ gs, gimple_call_fn (gs), lhs);
if (gimple_call_num_args (gs) > 0)
{
pp_string (buffer, ", ");
@@ -637,7 +641,10 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
pp_space (buffer);
}
- print_call_name (buffer, gimple_call_fn (gs), flags);
+ if (gimple_call_internal_p (gs))
+ pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs)));
+ else
+ print_call_name (buffer, gimple_call_fn (gs), flags);
pp_string (buffer, " (");
dump_gimple_call_args (buffer, gs, flags);
pp_character (buffer, ')');
diff --git a/gcc/gimple.c b/gcc/gimple.c
index c6868befc59..909091bcfd0 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -277,6 +277,59 @@ gimple_build_call (tree fn, unsigned nargs, ...)
}
+/* Helper for gimple_build_call_internal and gimple_build_call_internal_vec.
+ Build the basic components of a GIMPLE_CALL statement to internal
+ function FN with NARGS arguments. */
+
+static inline gimple
+gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
+{
+ gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
+ s->gsbase.subcode |= GF_CALL_INTERNAL;
+ gimple_call_set_internal_fn (s, fn);
+ gimple_call_reset_alias_info (s);
+ return s;
+}
+
+
+/* Build a GIMPLE_CALL statement to internal function FN. NARGS is
+ the number of arguments. The ... are the arguments. */
+
+gimple
+gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
+{
+ va_list ap;
+ gimple call;
+ unsigned i;
+
+ call = gimple_build_call_internal_1 (fn, nargs);
+ va_start (ap, nargs);
+ for (i = 0; i < nargs; i++)
+ gimple_call_set_arg (call, i, va_arg (ap, tree));
+ va_end (ap);
+
+ return call;
+}
+
+
+/* Build a GIMPLE_CALL statement to internal function FN with the arguments
+ specified in vector ARGS. */
+
+gimple
+gimple_build_call_internal_vec (enum internal_fn fn, VEC(tree, heap) *args)
+{
+ unsigned i, nargs;
+ gimple call;
+
+ nargs = VEC_length (tree, args);
+ call = gimple_build_call_internal_1 (fn, nargs);
+ for (i = 0; i < nargs; i++)
+ gimple_call_set_arg (call, i, VEC_index (tree, args, i));
+
+ return call;
+}
+
+
/* Build a GIMPLE_CALL statement from CALL_EXPR T. Note that T is
assumed to be in GIMPLE form already. Minimal checking is done of
this fact. */
@@ -1778,6 +1831,20 @@ gimple_has_body_p (tree fndecl)
return (gimple_body (fndecl) || (fn && fn->cfg));
}
+/* Return true if calls C1 and C2 are known to go to the same function. */
+
+bool
+gimple_call_same_target_p (const_gimple c1, const_gimple c2)
+{
+ if (gimple_call_internal_p (c1))
+ return (gimple_call_internal_p (c2)
+ && gimple_call_internal_fn (c1) == gimple_call_internal_fn (c2));
+ else
+ return (gimple_call_fn (c1) == gimple_call_fn (c2)
+ || (gimple_call_fndecl (c1)
+ && gimple_call_fndecl (c1) == gimple_call_fndecl (c2)));
+}
+
/* Detect flags from a GIMPLE_CALL. This is just like
call_expr_flags, but for gimple tuples. */
@@ -1789,6 +1856,8 @@ gimple_call_flags (const_gimple stmt)
if (decl)
flags = flags_from_decl_or_type (decl);
+ else if (gimple_call_internal_p (stmt))
+ flags = internal_fn_flags (gimple_call_internal_fn (stmt));
else
flags = flags_from_decl_or_type (gimple_call_fntype (stmt));
@@ -1798,18 +1867,32 @@ gimple_call_flags (const_gimple stmt)
return flags;
}
+/* Return the "fn spec" string for call STMT. */
+
+static tree
+gimple_call_fnspec (const_gimple stmt)
+{
+ tree type, attr;
+
+ type = gimple_call_fntype (stmt);
+ if (!type)
+ return NULL_TREE;
+
+ attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
+ if (!attr)
+ return NULL_TREE;
+
+ return TREE_VALUE (TREE_VALUE (attr));
+}
+
/* Detects argument flags for argument number ARG on call STMT. */
int
gimple_call_arg_flags (const_gimple stmt, unsigned arg)
{
- tree type = gimple_call_fntype (stmt);
- tree attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
- if (!attr)
- return 0;
+ tree attr = gimple_call_fnspec (stmt);
- attr = TREE_VALUE (TREE_VALUE (attr));
- if (1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
+ if (!attr || 1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
return 0;
switch (TREE_STRING_POINTER (attr)[1 + arg])
@@ -1841,19 +1924,13 @@ gimple_call_arg_flags (const_gimple stmt, unsigned arg)
int
gimple_call_return_flags (const_gimple stmt)
{
- tree type;
- tree attr = NULL_TREE;
+ tree attr;
if (gimple_call_flags (stmt) & ECF_MALLOC)
return ERF_NOALIAS;
- type = gimple_call_fntype (stmt);
- attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
- if (!attr)
- return 0;
-
- attr = TREE_VALUE (TREE_VALUE (attr));
- if (TREE_STRING_LENGTH (attr) < 1)
+ attr = gimple_call_fnspec (stmt);
+ if (!attr || TREE_STRING_LENGTH (attr) < 1)
return 0;
switch (TREE_STRING_POINTER (attr)[0])
@@ -2278,6 +2355,7 @@ gimple_has_side_effects (const_gimple s)
if (is_gimple_call (s))
{
unsigned nargs = gimple_call_num_args (s);
+ tree fn;
if (!(gimple_call_flags (s) & (ECF_CONST | ECF_PURE)))
return true;
@@ -2292,7 +2370,8 @@ gimple_has_side_effects (const_gimple s)
return true;
}
- if (TREE_SIDE_EFFECTS (gimple_call_fn (s)))
+ fn = gimple_call_fn (s);
+ if (fn && TREE_SIDE_EFFECTS (fn))
return true;
for (i = 0; i < nargs; i++)
@@ -2331,14 +2410,15 @@ gimple_rhs_has_side_effects (const_gimple s)
if (is_gimple_call (s))
{
unsigned nargs = gimple_call_num_args (s);
+ tree fn;
if (!(gimple_call_flags (s) & (ECF_CONST | ECF_PURE)))
return true;
/* We cannot use gimple_has_volatile_ops here,
because we must ignore a volatile LHS. */
- if (TREE_SIDE_EFFECTS (gimple_call_fn (s))
- || TREE_THIS_VOLATILE (gimple_call_fn (s)))
+ fn = gimple_call_fn (s);
+ if (fn && (TREE_SIDE_EFFECTS (fn) || TREE_THIS_VOLATILE (fn)))
{
gcc_assert (gimple_has_volatile_ops (s));
return true;
@@ -3094,7 +3174,6 @@ gimple
gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
{
int i;
- tree fn = gimple_call_fn (stmt);
int nargs = gimple_call_num_args (stmt);
VEC(tree, heap) *vargs = VEC_alloc (tree, heap, nargs);
gimple new_stmt;
@@ -3103,7 +3182,11 @@ gimple_call_copy_skip_args (gimple stmt, bitmap args_to_skip)
if (!bitmap_bit_p (args_to_skip, i))
VEC_quick_push (tree, vargs, gimple_call_arg (stmt, i));
- new_stmt = gimple_build_call_vec (fn, vargs);
+ if (gimple_call_internal_p (stmt))
+ new_stmt = gimple_build_call_internal_vec (gimple_call_internal_fn (stmt),
+ vargs);
+ else
+ new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
VEC_free (tree, heap, vargs);
if (gimple_call_lhs (stmt))
gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 322ce99eb5c..a5374a9620c 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "tree-ssa-operands.h"
#include "tree-ssa-alias.h"
+#include "internal-fn.h"
struct gimple_seq_node_d;
typedef struct gimple_seq_node_d *gimple_seq_node;
@@ -103,6 +104,7 @@ enum gf_mask {
GF_CALL_VA_ARG_PACK = 1 << 4,
GF_CALL_NOTHROW = 1 << 5,
GF_CALL_ALLOCA_FOR_VAR = 1 << 6,
+ GF_CALL_INTERNAL = 1 << 7,
GF_OMP_PARALLEL_COMBINED = 1 << 0,
/* True on an GIMPLE_OMP_RETURN statement if the return does not require
@@ -407,7 +409,10 @@ struct GTY(()) gimple_statement_call
struct pt_solution call_clobbered;
/* [ WORD 13 ] */
- tree fntype;
+ union GTY ((desc ("%1.membase.opbase.gsbase.subcode & GF_CALL_INTERNAL"))) {
+ tree GTY ((tag ("0"))) fntype;
+ enum internal_fn GTY ((tag ("GF_CALL_INTERNAL"))) internal_fn;
+ } u;
/* [ WORD 14 ]
Operand vector. NOTE! This must always be the last field
@@ -821,6 +826,8 @@ gimple gimple_build_debug_bind_stat (tree, tree, gimple MEM_STAT_DECL);
gimple gimple_build_call_vec (tree, VEC(tree, heap) *);
gimple gimple_build_call (tree, unsigned, ...);
+gimple gimple_build_call_internal (enum internal_fn, unsigned, ...);
+gimple gimple_build_call_internal_vec (enum internal_fn, VEC(tree, heap) *);
gimple gimple_build_call_from_tree (tree);
gimple gimplify_assign (tree, tree, gimple_seq *);
gimple gimple_build_cond (enum tree_code, tree, tree, tree, tree);
@@ -865,6 +872,7 @@ gimple_seq gimple_seq_alloc (void);
void gimple_seq_free (gimple_seq);
void gimple_seq_add_seq (gimple_seq *, gimple_seq);
gimple_seq gimple_seq_copy (gimple_seq);
+bool gimple_call_same_target_p (const_gimple, const_gimple);
int gimple_call_flags (const_gimple);
int gimple_call_return_flags (const_gimple);
int gimple_call_arg_flags (const_gimple, unsigned);
@@ -2007,13 +2015,36 @@ gimple_call_set_lhs (gimple gs, tree lhs)
}
+/* Return true if call GS calls an internal-only function, as enumerated
+ by internal_fn. */
+
+static inline bool
+gimple_call_internal_p (const_gimple gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_CALL);
+ return (gs->gsbase.subcode & GF_CALL_INTERNAL) != 0;
+}
+
+
+/* Return the target of internal call GS. */
+
+static inline enum internal_fn
+gimple_call_internal_fn (const_gimple gs)
+{
+ gcc_gimple_checking_assert (gimple_call_internal_p (gs));
+ return gs->gimple_call.u.internal_fn;
+}
+
+
/* Return the function type of the function called by GS. */
static inline tree
gimple_call_fntype (const_gimple gs)
{
GIMPLE_CHECK (gs, GIMPLE_CALL);
- return gs->gimple_call.fntype;
+ if (gimple_call_internal_p (gs))
+ return NULL_TREE;
+ return gs->gimple_call.u.fntype;
}
/* Set the type of the function called by GS to FNTYPE. */
@@ -2022,7 +2053,8 @@ static inline void
gimple_call_set_fntype (gimple gs, tree fntype)
{
GIMPLE_CHECK (gs, GIMPLE_CALL);
- gs->gimple_call.fntype = fntype;
+ gcc_gimple_checking_assert (!gimple_call_internal_p (gs));
+ gs->gimple_call.u.fntype = fntype;
}
@@ -2053,6 +2085,7 @@ static inline void
gimple_call_set_fn (gimple gs, tree fn)
{
GIMPLE_CHECK (gs, GIMPLE_CALL);
+ gcc_gimple_checking_assert (!gimple_call_internal_p (gs));
gimple_set_op (gs, 1, fn);
}
@@ -2063,16 +2096,29 @@ static inline void
gimple_call_set_fndecl (gimple gs, tree decl)
{
GIMPLE_CHECK (gs, GIMPLE_CALL);
+ gcc_gimple_checking_assert (!gimple_call_internal_p (gs));
gimple_set_op (gs, 1, build_fold_addr_expr_loc (gimple_location (gs), decl));
}
+
+/* Set internal function FN to be the function called by call statement GS. */
+
+static inline void
+gimple_call_set_internal_fn (gimple gs, enum internal_fn fn)
+{
+ GIMPLE_CHECK (gs, GIMPLE_CALL);
+ gcc_gimple_checking_assert (gimple_call_internal_p (gs));
+ gs->gimple_call.u.internal_fn = fn;
+}
+
+
/* Given a valid GIMPLE_CALL function address return the FUNCTION_DECL
associated with the callee if known. Otherwise return NULL_TREE. */
static inline tree
gimple_call_addr_fndecl (const_tree fn)
{
- if (TREE_CODE (fn) == ADDR_EXPR)
+ if (fn && TREE_CODE (fn) == ADDR_EXPR)
{
tree fndecl = TREE_OPERAND (fn, 0);
if (TREE_CODE (fndecl) == MEM_REF
@@ -2103,6 +2149,9 @@ gimple_call_return_type (const_gimple gs)
{
tree type = gimple_call_fntype (gs);
+ if (type == NULL_TREE)
+ return TREE_TYPE (gimple_call_lhs (gs));
+
/* The type returned by a function is the type of its
function type. */
return TREE_TYPE (type);
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
new file mode 100644
index 00000000000..9f087b83105
--- /dev/null
+++ b/gcc/internal-fn.c
@@ -0,0 +1,64 @@
+/* Internal functions.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "internal-fn.h"
+#include "tree.h"
+#include "expr.h"
+#include "optabs.h"
+#include "gimple.h"
+
+/* The names of each internal function, indexed by function number. */
+const char *const internal_fn_name_array[] = {
+#define DEF_INTERNAL_FN(CODE, FLAGS) #CODE,
+#include "internal-fn.def"
+#undef DEF_INTERNAL_FN
+ "<invalid-fn>"
+};
+
+/* The ECF_* flags of each internal function, indexed by function number. */
+const int internal_fn_flags_array[] = {
+#define DEF_INTERNAL_FN(CODE, FLAGS) FLAGS,
+#include "internal-fn.def"
+#undef DEF_INTERNAL_FN
+ 0
+};
+
+/* Routines to expand each internal function, indexed by function number.
+ Each routine has the prototype:
+
+ expand_<NAME> (gimple stmt)
+
+ where STMT is the statement that performs the call. */
+static void (*const internal_fn_expanders[]) (gimple) = {
+#define DEF_INTERNAL_FN(CODE, FLAGS) expand_##CODE,
+#include "internal-fn.def"
+#undef DEF_INTERNAL_FN
+ 0
+};
+
+/* Expand STMT, which is a call to internal function FN. */
+
+void
+expand_internal_call (gimple stmt)
+{
+ internal_fn_expanders[(int) gimple_call_internal_fn (stmt)] (stmt);
+}
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
new file mode 100644
index 00000000000..b9b622db71c
--- /dev/null
+++ b/gcc/internal-fn.def
@@ -0,0 +1,39 @@
+/* Internal functions.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This file specifies a list of internal "functions". These functions
+ differ from built-in functions in that they have no linkage and cannot
+ be called directly by the user. They represent operations that are only
+ synthesised by GCC itself.
+
+ Internal functions are used instead of tree codes if the operation
+ and its operands are more naturally represented as a GIMPLE_CALL
+ than a GIMPLE_ASSIGN.
+
+ Each entry in this file has the form:
+
+ DEF_INTERNAL_FN (NAME, FLAGS)
+
+ where NAME is the name of the function and FLAGS is a set of
+ ECF_* flags. Each entry must have a corresponding expander
+ of the form:
+
+ void expand_NAME (gimple stmt)
+
+ where STMT is the statement that performs the call. */
diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
new file mode 100644
index 00000000000..c9e660b2d6a
--- /dev/null
+++ b/gcc/internal-fn.h
@@ -0,0 +1,51 @@
+/* Internal functions.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_INTERNAL_FN_H
+#define GCC_INTERNAL_FN_H
+
+enum internal_fn {
+#define DEF_INTERNAL_FN(CODE, FLAGS) IFN_##CODE,
+#include "internal-fn.def"
+#undef DEF_INTERNAL_FN
+ IFN_LAST
+};
+
+/* Return the name of internal function FN. The name is only meaningful
+ for dumps; it has no linkage. */
+
+static inline const char *
+internal_fn_name (enum internal_fn fn)
+{
+ extern const char *const internal_fn_name_array[];
+ return internal_fn_name_array[(int) fn];
+}
+
+/* Return the ECF_* flags for function FN. */
+
+static inline int
+internal_fn_flags (enum internal_fn fn)
+{
+ extern const int internal_fn_flags_array[];
+ return internal_fn_flags_array[(int) fn];
+}
+
+extern void expand_internal_call (gimple);
+
+#endif
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 6620d5791cd..3fdebc1f2c5 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -1456,6 +1456,8 @@ ipa_analyze_call_uses (struct cgraph_node *node,
{
tree target = gimple_call_fn (call);
+ if (!target)
+ return;
if (TREE_CODE (target) == SSA_NAME)
ipa_analyze_indirect_call_uses (node, info, parms_info, call, target);
else if (TREE_CODE (target) == OBJ_TYPE_REF)
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index f1e426aac34..ce5e33d0929 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1063,7 +1063,13 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
}
}
if (is_gimple_call (stmt))
- gimple_call_set_fntype (stmt, lto_input_tree (ib, data_in));
+ {
+ if (gimple_call_internal_p (stmt))
+ gimple_call_set_internal_fn
+ (stmt, (enum internal_fn) lto_input_sleb128 (ib));
+ else
+ gimple_call_set_fntype (stmt, lto_input_tree (ib, data_in));
+ }
break;
case GIMPLE_NOP:
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 1f5b054582b..959498312a5 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1760,7 +1760,12 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
lto_output_tree_ref (ob, op);
}
if (is_gimple_call (stmt))
- lto_output_tree_ref (ob, gimple_call_fntype (stmt));
+ {
+ if (gimple_call_internal_p (stmt))
+ output_sleb128 (ob, (int) gimple_call_internal_fn (stmt));
+ else
+ lto_output_tree_ref (ob, gimple_call_fntype (stmt));
+ }
break;
case GIMPLE_NOP:
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 3df4dcc8e23..40f768886ee 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3046,16 +3046,35 @@ verify_gimple_call (gimple stmt)
tree fntype, fndecl;
unsigned i;
- if (!is_gimple_call_addr (fn))
+ if (gimple_call_internal_p (stmt))
+ {
+ if (fn)
+ {
+ error ("gimple call has two targets");
+ debug_generic_stmt (fn);
+ return true;
+ }
+ }
+ else
+ {
+ if (!fn)
+ {
+ error ("gimple call has no target");
+ return true;
+ }
+ }
+
+ if (fn && !is_gimple_call_addr (fn))
{
error ("invalid function in gimple call");
debug_generic_stmt (fn);
return true;
}
- if (!POINTER_TYPE_P (TREE_TYPE (fn))
- || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE))
+ if (fn
+ && (!POINTER_TYPE_P (TREE_TYPE (fn))
+ || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE)))
{
error ("non-function in gimple call");
return true;
@@ -3087,7 +3106,8 @@ verify_gimple_call (gimple stmt)
}
fntype = gimple_call_fntype (stmt);
- if (gimple_call_lhs (stmt)
+ if (fntype
+ && gimple_call_lhs (stmt)
&& !useless_type_conversion_p (TREE_TYPE (gimple_call_lhs (stmt)),
TREE_TYPE (fntype))
/* ??? At least C++ misses conversions at assignments from
@@ -7436,6 +7456,8 @@ do_warn_unused_result (gimple_seq seq)
case GIMPLE_CALL:
if (gimple_call_lhs (g))
break;
+ if (gimple_call_internal_p (g))
+ break;
/* This is a naked call, as opposed to a GIMPLE_CALL with an
LHS. All calls whose value is ignored should be
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index f189b9b6a96..5ef319dc2ca 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2743,7 +2743,7 @@ same_handler_p (gimple_seq oneh, gimple_seq twoh)
|| gimple_call_lhs (twos)
|| gimple_call_chain (ones)
|| gimple_call_chain (twos)
- || !operand_equal_p (gimple_call_fn (ones), gimple_call_fn (twos), 0)
+ || !gimple_call_same_target_p (ones, twos)
|| gimple_call_num_args (ones) != gimple_call_num_args (twos))
return false;
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 3aa2773ad8f..2caec4c5679 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1722,6 +1722,11 @@ ccp_fold_stmt (gimple_stmt_iterator *gsi)
return true;
}
+ /* Internal calls provide no argument types, so the extra laxity
+ for normal calls does not apply. */
+ if (gimple_call_internal_p (stmt))
+ return false;
+
/* Propagate into the call arguments. Compared to replace_uses_in
this can use the argument slot types for type verification
instead of the current argument type. We also can safely
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 0f649f3cfed..2e9498efdcc 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -64,7 +64,7 @@ struct hashable_expr
struct { enum tree_code op; tree opnd; } unary;
struct { enum tree_code op; tree opnd0, opnd1; } binary;
struct { enum tree_code op; tree opnd0, opnd1, opnd2; } ternary;
- struct { tree fn; bool pure; size_t nargs; tree *args; } call;
+ struct { gimple fn_from; bool pure; size_t nargs; tree *args; } call;
} ops;
};
@@ -258,7 +258,7 @@ initialize_hash_element (gimple stmt, tree lhs,
expr->type = TREE_TYPE (gimple_call_lhs (stmt));
expr->kind = EXPR_CALL;
- expr->ops.call.fn = gimple_call_fn (stmt);
+ expr->ops.call.fn_from = stmt;
if (gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE))
expr->ops.call.pure = true;
@@ -422,8 +422,8 @@ hashable_expr_equal_p (const struct hashable_expr *expr0,
/* If the calls are to different functions, then they
clearly cannot be equal. */
- if (! operand_equal_p (expr0->ops.call.fn,
- expr1->ops.call.fn, 0))
+ if (!gimple_call_same_target_p (expr0->ops.call.fn_from,
+ expr1->ops.call.fn_from))
return false;
if (! expr0->ops.call.pure)
@@ -503,9 +503,15 @@ iterative_hash_hashable_expr (const struct hashable_expr *expr, hashval_t val)
{
size_t i;
enum tree_code code = CALL_EXPR;
+ gimple fn_from;
val = iterative_hash_object (code, val);
- val = iterative_hash_expr (expr->ops.call.fn, val);
+ fn_from = expr->ops.call.fn_from;
+ if (gimple_call_internal_p (fn_from))
+ val = iterative_hash_hashval_t
+ ((hashval_t) gimple_call_internal_fn (fn_from), val);
+ else
+ val = iterative_hash_expr (gimple_call_fn (fn_from), val);
for (i = 0; i < expr->ops.call.nargs; i++)
val = iterative_hash_expr (expr->ops.call.args[i], val);
}
@@ -565,8 +571,14 @@ print_expr_hash_elt (FILE * stream, const struct expr_hash_elt *element)
{
size_t i;
size_t nargs = element->expr.ops.call.nargs;
-
- print_generic_expr (stream, element->expr.ops.call.fn, 0);
+ gimple fn_from;
+
+ fn_from = element->expr.ops.call.fn_from;
+ if (gimple_call_internal_p (fn_from))
+ fputs (internal_fn_name (gimple_call_internal_fn (fn_from)),
+ stream);
+ else
+ print_generic_expr (stream, gimple_call_fn (fn_from), 0);
fprintf (stream, " (");
for (i = 0; i < nargs; i++)
{
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index df2a13867d1..ee9ee6fe080 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2657,11 +2657,13 @@ compute_antic (void)
}
/* Return true if we can value number the call in STMT. This is true
- if we have a pure or constant call. */
+ if we have a pure or constant call to a real function. */
static bool
can_value_number_call (gimple stmt)
{
+ if (gimple_call_internal_p (stmt))
+ return false;
if (gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
return true;
return false;
@@ -4384,6 +4386,8 @@ eliminate (void)
{
tree orig_fn = gimple_call_fn (stmt);
tree fn;
+ if (!orig_fn)
+ continue;
if (TREE_CODE (orig_fn) == SSA_NAME)
fn = VN_INFO (orig_fn)->valnum;
else if (TREE_CODE (orig_fn) == OBJ_TYPE_REF
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 29b80ea5780..ab56e3d534a 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -3125,7 +3125,8 @@ visit_use (tree use)
/* ??? We should handle stores from calls. */
else if (TREE_CODE (lhs) == SSA_NAME)
{
- if (gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
+ if (!gimple_call_internal_p (stmt)
+ && gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
changed = visit_reference_op_call (lhs, stmt);
else
changed = defs_to_varying (stmt);
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index de17312a716..70405a16137 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -4026,6 +4026,8 @@ get_fi_for_callee (gimple call)
{
tree decl;
+ gcc_assert (!gimple_call_internal_p (call));
+
/* If we can directly resolve the function being called, do so.
Otherwise, it must be some sort of indirect expression that
we should still be able to handle. */
@@ -4319,6 +4321,7 @@ find_func_aliases (gimple origt)
/* Fallthru to general call handling. */;
}
if (!in_ipa_mode
+ || gimple_call_internal_p (t)
|| (fndecl
&& (!(fi = lookup_vi_for_tree (fndecl))
|| !fi->is_fn_info)))
diff --git a/gcc/value-prof.c b/gcc/value-prof.c
index b2a082de7e2..056bcbe5693 100644
--- a/gcc/value-prof.c
+++ b/gcc/value-prof.c
@@ -1258,6 +1258,9 @@ gimple_ic_transform (gimple stmt)
if (gimple_call_fndecl (stmt) != NULL_TREE)
return false;
+ if (gimple_call_internal_p (stmt))
+ return false;
+
histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_INDIR_CALL);
if (!histogram)
return false;
@@ -1649,6 +1652,7 @@ gimple_indirect_call_to_profile (gimple stmt, histogram_values *values)
tree callee;
if (gimple_code (stmt) != GIMPLE_CALL
+ || gimple_call_internal_p (stmt)
|| gimple_call_fndecl (stmt) != NULL_TREE)
return;