This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][RFC] Use overloads for gimple_build_assign_with_ops
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Diego Novillo <dnovillo at google dot com>
- Date: Mon, 17 Sep 2012 15:25:50 +0200 (CEST)
- Subject: [PATCH][RFC] Use overloads for gimple_build_assign_with_ops
This makes use of the new builtin functions for FILE, LINE and FUNCTION
to turn gimple_build_assign_with_ops/gimple_build_assign_with_ops3 into
two overloads of gimple_build_assign_with_ops (in theory the _stats
function can go and we could move the inlines to gimple.c instead,
eventually removing the assert and simply calling the 3-op overload
from the 2-op overload?)
The patch merely serves as an example on how to transform mem-stat
code to non-macros.
Quickly build-tested with --disable-gather-detailed-mem-stats,
stage1 with --enable-gather-detailed-mem-stats and host GCC 4.6
prints
gimple.h:766 ((null)) 112: 0.0%
0: 0.0% 0: 0.0% 0: 0.0%
for a former gimple_build_assign_with_ops3 call, stage2 (or stage1
with a GCC 4.8 host compiler) prints
tree-ssa-math-opts.c:2610 (convert_mult_to_fma) 112: 0.0%
0: 0.0% 0: 0.0% 0: 0.0% 1
so it effectively cripples -fmem-report when not compiled with
a compiler supporting the builtins.
Any comments/objections?
Thanks,
Richard.
2012-09-17 Richard Guenther <rguenther@suse.de>
* statistics.h (CXX_MEM_STAT_INFO): New define.
* gimple.h (gimple_build_assign_with_ops): Turn into an
overload of the inline function gimple_build_assign_with_ops.
(gimple_build_assign_with_ops3): Likewise.
* tree-ssa-loop-im.c (move_computations_stmt): Adjust.
* tree-ssa-math-opts.c (convert_mult_to_fma): Likewise.
* tree-vect-data-refs.c (vect_permute_store_chain): Likewise.
(vect_permute_load_chain): Likewise.
* tree-vect-generic.c (expand_vector_divmod): Likewise.
* tree-vect-patterns.c (vect_recog_dot_prod_pattern): Likewise.
(vect_recog_divmod_pattern): Likewise.
(vect_recog_mixed_size_cond_pattern): Likewise.
(adjust_bool_pattern): Likewise.
* tree-vect-slp.c (vect_create_mask_and_perm): Likewise.
* tree-vect-stmts.c (vectorizable_operation): Likewise.
(permute_vec_elements): Likewise.
(vectorizable_load): Likewise.
Index: trunk/gcc/gimple.h
===================================================================
*** trunk.orig/gcc/gimple.h 2012-09-11 12:25:21.000000000 +0200
--- trunk/gcc/gimple.h 2012-09-17 15:02:10.727065806 +0200
*************** gimple gimple_build_assign_stat (tree, t
*** 744,755 ****
void extract_ops_from_tree_1 (tree, enum tree_code *, tree *, tree *, tree *);
gimple gimple_build_assign_with_ops_stat (enum tree_code, tree, tree,
tree, tree MEM_STAT_DECL);
! #define gimple_build_assign_with_ops(c,o1,o2,o3) \
! gimple_build_assign_with_ops_stat (c, o1, o2, o3, NULL_TREE MEM_STAT_INFO)
! #define gimple_build_assign_with_ops3(c,o1,o2,o3,o4) \
! gimple_build_assign_with_ops_stat (c, o1, o2, o3, o4 MEM_STAT_INFO)
gimple gimple_build_debug_bind_stat (tree, tree, gimple MEM_STAT_DECL);
#define gimple_build_debug_bind(var,val,stmt) \
--- 744,774 ----
void extract_ops_from_tree_1 (tree, enum tree_code *, tree *, tree *, tree *);
+ inline enum gimple_rhs_class get_gimple_rhs_class (enum tree_code);
gimple gimple_build_assign_with_ops_stat (enum tree_code, tree, tree,
tree, tree MEM_STAT_DECL);
!
! inline gimple
! gimple_build_assign_with_ops (enum tree_code code, tree lhs,
! tree op1, tree op2 CXX_MEM_STAT_INFO)
! {
! return gimple_build_assign_with_ops_stat (code, lhs,
! op1, op2, NULL_TREE PASS_MEM_STAT);
! }
!
! /* Build and return a GIMPLE assignment statement assigning CODE applied
! to OP1, OP2 and OP3 to LHS.
! CODE, OP1, OP2 and OP3 should be appropriate for a GIMPLE_TERNARY_RHS
! assign. */
!
! inline gimple
! gimple_build_assign_with_ops (enum tree_code code, tree lhs,
! tree op1, tree op2, tree op3 CXX_MEM_STAT_INFO)
! {
! gcc_checking_assert (get_gimple_rhs_class (code) == GIMPLE_TERNARY_RHS);
! return gimple_build_assign_with_ops_stat (code, lhs,
! op1, op2, op3 PASS_MEM_STAT);
! }
gimple gimple_build_debug_bind_stat (tree, tree, gimple MEM_STAT_DECL);
#define gimple_build_debug_bind(var,val,stmt) \
*************** is_gimple_assign (const_gimple gs)
*** 1811,1817 ****
/* Determine if expression CODE is one of the valid expressions that can
be used on the RHS of GIMPLE assignments. */
! static inline enum gimple_rhs_class
get_gimple_rhs_class (enum tree_code code)
{
return (enum gimple_rhs_class) gimple_rhs_class_table[(int) code];
--- 1830,1836 ----
/* Determine if expression CODE is one of the valid expressions that can
be used on the RHS of GIMPLE assignments. */
! inline enum gimple_rhs_class
get_gimple_rhs_class (enum tree_code code)
{
return (enum gimple_rhs_class) gimple_rhs_class_table[(int) code];
Index: trunk/gcc/tree-ssa-loop-im.c
===================================================================
*** trunk.orig/gcc/tree-ssa-loop-im.c 2012-09-11 16:02:22.000000000 +0200
--- trunk/gcc/tree-ssa-loop-im.c 2012-09-17 14:50:36.634089905 +0200
*************** move_computations_stmt (struct dom_walk_
*** 1273,1281 ****
gcc_assert (arg0 && arg1);
t = build2 (gimple_cond_code (cond), boolean_type_node,
gimple_cond_lhs (cond), gimple_cond_rhs (cond));
! new_stmt = gimple_build_assign_with_ops3 (COND_EXPR,
! gimple_phi_result (stmt),
! t, arg0, arg1);
SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
*((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg;
}
--- 1273,1281 ----
gcc_assert (arg0 && arg1);
t = build2 (gimple_cond_code (cond), boolean_type_node,
gimple_cond_lhs (cond), gimple_cond_rhs (cond));
! new_stmt = gimple_build_assign_with_ops (COND_EXPR,
! gimple_phi_result (stmt),
! t, arg0, arg1);
SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
*((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg;
}
Index: trunk/gcc/tree-ssa-math-opts.c
===================================================================
*** trunk.orig/gcc/tree-ssa-math-opts.c 2012-09-17 14:49:19.000000000 +0200
--- trunk/gcc/tree-ssa-math-opts.c 2012-09-17 14:50:36.634089905 +0200
*************** convert_mult_to_fma (gimple mul_stmt, tr
*** 2604,2613 ****
true, NULL_TREE, true,
GSI_SAME_STMT);
! fma_stmt = gimple_build_assign_with_ops3 (FMA_EXPR,
! gimple_assign_lhs (use_stmt),
! mulop1, op2,
! addop);
gsi_replace (&gsi, fma_stmt, true);
widen_mul_stats.fmas_inserted++;
}
--- 2604,2613 ----
true, NULL_TREE, true,
GSI_SAME_STMT);
! fma_stmt = gimple_build_assign_with_ops (FMA_EXPR,
! gimple_assign_lhs (use_stmt),
! mulop1, op2,
! addop);
gsi_replace (&gsi, fma_stmt, true);
widen_mul_stats.fmas_inserted++;
}
Index: trunk/gcc/tree-vect-data-refs.c
===================================================================
*** trunk.orig/gcc/tree-vect-data-refs.c 2012-08-22 11:30:14.000000000 +0200
--- trunk/gcc/tree-vect-data-refs.c 2012-09-17 14:50:36.635089901 +0200
*************** vect_permute_store_chain (VEC(tree,heap)
*** 4170,4177 ****
high = VEC_PERM_EXPR <vect1, vect2, {0, nelt, 1, nelt+1, ...}> */
high = make_temp_ssa_name (vectype, NULL, "vect_inter_high");
perm_stmt
! = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, high,
! vect1, vect2, perm_mask_high);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
VEC_replace (tree, *result_chain, 2*j, high);
--- 4170,4177 ----
high = VEC_PERM_EXPR <vect1, vect2, {0, nelt, 1, nelt+1, ...}> */
high = make_temp_ssa_name (vectype, NULL, "vect_inter_high");
perm_stmt
! = gimple_build_assign_with_ops (VEC_PERM_EXPR, high,
! vect1, vect2, perm_mask_high);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
VEC_replace (tree, *result_chain, 2*j, high);
*************** vect_permute_store_chain (VEC(tree,heap)
*** 4180,4187 ****
nelt*3/2+1, ...}> */
low = make_temp_ssa_name (vectype, NULL, "vect_inter_low");
perm_stmt
! = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, low,
! vect1, vect2, perm_mask_low);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
VEC_replace (tree, *result_chain, 2*j+1, low);
}
--- 4180,4187 ----
nelt*3/2+1, ...}> */
low = make_temp_ssa_name (vectype, NULL, "vect_inter_low");
perm_stmt
! = gimple_build_assign_with_ops (VEC_PERM_EXPR, low,
! vect1, vect2, perm_mask_low);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
VEC_replace (tree, *result_chain, 2*j+1, low);
}
*************** vect_permute_load_chain (VEC(tree,heap)
*** 4618,4634 ****
/* data_ref = permute_even (first_data_ref, second_data_ref); */
data_ref = make_temp_ssa_name (vectype, NULL, "vect_perm_even");
! perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, data_ref,
! first_vect, second_vect,
! perm_mask_even);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
VEC_replace (tree, *result_chain, j/2, data_ref);
/* data_ref = permute_odd (first_data_ref, second_data_ref); */
data_ref = make_temp_ssa_name (vectype, NULL, "vect_perm_odd");
! perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, data_ref,
! first_vect, second_vect,
! perm_mask_odd);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
VEC_replace (tree, *result_chain, j/2+length/2, data_ref);
}
--- 4618,4634 ----
/* data_ref = permute_even (first_data_ref, second_data_ref); */
data_ref = make_temp_ssa_name (vectype, NULL, "vect_perm_even");
! perm_stmt = gimple_build_assign_with_ops (VEC_PERM_EXPR, data_ref,
! first_vect, second_vect,
! perm_mask_even);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
VEC_replace (tree, *result_chain, j/2, data_ref);
/* data_ref = permute_odd (first_data_ref, second_data_ref); */
data_ref = make_temp_ssa_name (vectype, NULL, "vect_perm_odd");
! perm_stmt = gimple_build_assign_with_ops (VEC_PERM_EXPR, data_ref,
! first_vect, second_vect,
! perm_mask_odd);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
VEC_replace (tree, *result_chain, j/2+length/2, data_ref);
}
Index: trunk/gcc/tree-vect-generic.c
===================================================================
*** trunk.orig/gcc/tree-vect-generic.c 2012-09-11 10:30:13.000000000 +0200
--- trunk/gcc/tree-vect-generic.c 2012-09-17 14:50:36.635089901 +0200
*************** expand_vector_divmod (gimple_stmt_iterat
*** 667,674 ****
<< shifts[i]) - 1);
cst = build_vector (type, vec);
addend = make_ssa_name (type, NULL);
! stmt = gimple_build_assign_with_ops3 (VEC_COND_EXPR, addend,
! cond, cst, zero);
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
}
}
--- 667,674 ----
<< shifts[i]) - 1);
cst = build_vector (type, vec);
addend = make_ssa_name (type, NULL);
! stmt = gimple_build_assign_with_ops (VEC_COND_EXPR, addend,
! cond, cst, zero);
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
}
}
Index: trunk/gcc/tree-vect-patterns.c
===================================================================
*** trunk.orig/gcc/tree-vect-patterns.c 2012-08-20 13:56:21.000000000 +0200
--- trunk/gcc/tree-vect-patterns.c 2012-09-17 14:50:36.636089897 +0200
*************** vect_recog_dot_prod_pattern (VEC (gimple
*** 413,420 ****
/* Pattern detected. Create a stmt to be used to replace the pattern: */
var = vect_recog_temp_ssa_var (type, NULL);
! pattern_stmt = gimple_build_assign_with_ops3 (DOT_PROD_EXPR, var,
! oprnd00, oprnd01, oprnd1);
if (vect_print_dump_info (REPORT_DETAILS))
{
--- 413,420 ----
/* Pattern detected. Create a stmt to be used to replace the pattern: */
var = vect_recog_temp_ssa_var (type, NULL);
! pattern_stmt = gimple_build_assign_with_ops (DOT_PROD_EXPR, var,
! oprnd00, oprnd01, oprnd1);
if (vect_print_dump_info (REPORT_DETAILS))
{
*************** vect_recog_divmod_pattern (VEC (gimple,
*** 1688,1699 ****
tree var = vect_recog_temp_ssa_var (itype, NULL);
tree shift;
def_stmt
! = gimple_build_assign_with_ops3 (COND_EXPR, var, cond,
! fold_build2 (MINUS_EXPR, itype,
! oprnd1,
! build_int_cst (itype,
! 1)),
! build_int_cst (itype, 0));
new_pattern_def_seq (stmt_vinfo, def_stmt);
var = vect_recog_temp_ssa_var (itype, NULL);
def_stmt
--- 1688,1699 ----
tree var = vect_recog_temp_ssa_var (itype, NULL);
tree shift;
def_stmt
! = gimple_build_assign_with_ops (COND_EXPR, var, cond,
! fold_build2 (MINUS_EXPR, itype,
! oprnd1,
! build_int_cst (itype,
! 1)),
! build_int_cst (itype, 0));
new_pattern_def_seq (stmt_vinfo, def_stmt);
var = vect_recog_temp_ssa_var (itype, NULL);
def_stmt
*************** vect_recog_divmod_pattern (VEC (gimple,
*** 1716,1724 ****
{
signmask = vect_recog_temp_ssa_var (itype, NULL);
def_stmt
! = gimple_build_assign_with_ops3 (COND_EXPR, signmask, cond,
! build_int_cst (itype, 1),
! build_int_cst (itype, 0));
append_pattern_def_seq (stmt_vinfo, def_stmt);
}
else
--- 1716,1724 ----
{
signmask = vect_recog_temp_ssa_var (itype, NULL);
def_stmt
! = gimple_build_assign_with_ops (COND_EXPR, signmask, cond,
! build_int_cst (itype, 1),
! build_int_cst (itype, 0));
append_pattern_def_seq (stmt_vinfo, def_stmt);
}
else
*************** vect_recog_divmod_pattern (VEC (gimple,
*** 1732,1740 ****
tree var = vect_recog_temp_ssa_var (utype, NULL);
def_stmt
! = gimple_build_assign_with_ops3 (COND_EXPR, var, cond,
! build_int_cst (utype, -1),
! build_int_cst (utype, 0));
def_stmt_vinfo
= new_stmt_vec_info (def_stmt, loop_vinfo, bb_vinfo);
set_vinfo_for_stmt (def_stmt, def_stmt_vinfo);
--- 1732,1740 ----
tree var = vect_recog_temp_ssa_var (utype, NULL);
def_stmt
! = gimple_build_assign_with_ops (COND_EXPR, var, cond,
! build_int_cst (utype, -1),
! build_int_cst (utype, 0));
def_stmt_vinfo
= new_stmt_vec_info (def_stmt, loop_vinfo, bb_vinfo);
set_vinfo_for_stmt (def_stmt, def_stmt_vinfo);
*************** vect_recog_mixed_size_cond_pattern (VEC
*** 2172,2182 ****
}
def_stmt
! = gimple_build_assign_with_ops3 (COND_EXPR,
! vect_recog_temp_ssa_var (itype, NULL),
! unshare_expr (cond_expr),
! fold_convert (itype, then_clause),
! fold_convert (itype, else_clause));
pattern_stmt
= gimple_build_assign_with_ops (NOP_EXPR,
vect_recog_temp_ssa_var (type, NULL),
--- 2172,2182 ----
}
def_stmt
! = gimple_build_assign_with_ops (COND_EXPR,
! vect_recog_temp_ssa_var (itype, NULL),
! unshare_expr (cond_expr),
! fold_convert (itype, then_clause),
! fold_convert (itype, else_clause));
pattern_stmt
= gimple_build_assign_with_ops (NOP_EXPR,
vect_recog_temp_ssa_var (type, NULL),
*************** adjust_bool_pattern (tree var, tree out_
*** 2476,2485 ****
gcc_checking_assert (useless_type_conversion_p (itype,
TREE_TYPE (trueval)));
pattern_stmt
! = gimple_build_assign_with_ops3 (COND_EXPR,
! vect_recog_temp_ssa_var (itype, NULL),
! cond_expr, trueval,
! build_int_cst (itype, 0));
break;
}
--- 2476,2485 ----
gcc_checking_assert (useless_type_conversion_p (itype,
TREE_TYPE (trueval)));
pattern_stmt
! = gimple_build_assign_with_ops (COND_EXPR,
! vect_recog_temp_ssa_var (itype, NULL),
! cond_expr, trueval,
! build_int_cst (itype, 0));
break;
}
Index: trunk/gcc/tree-vect-slp.c
===================================================================
*** trunk.orig/gcc/tree-vect-slp.c 2012-09-11 10:30:16.000000000 +0200
--- trunk/gcc/tree-vect-slp.c 2012-09-17 14:50:36.636089897 +0200
*************** vect_create_mask_and_perm (gimple stmt,
*** 2672,2679 ****
second_vec = VEC_index (tree, dr_chain, second_vec_indx);
/* Generate the permute statement. */
! perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
! first_vec, second_vec, mask);
data_ref = make_ssa_name (perm_dest, perm_stmt);
gimple_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
--- 2672,2679 ----
second_vec = VEC_index (tree, dr_chain, second_vec_indx);
/* Generate the permute statement. */
! perm_stmt = gimple_build_assign_with_ops (VEC_PERM_EXPR, perm_dest,
! first_vec, second_vec, mask);
data_ref = make_ssa_name (perm_dest, perm_stmt);
gimple_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
Index: trunk/gcc/tree-vect-stmts.c
===================================================================
*** trunk.orig/gcc/tree-vect-stmts.c 2012-08-23 12:08:08.000000000 +0200
--- trunk/gcc/tree-vect-stmts.c 2012-09-17 14:50:36.637089892 +0200
*************** vectorizable_operation (gimple stmt, gim
*** 3702,3709 ****
? VEC_index (tree, vec_oprnds1, i) : NULL_TREE);
vop2 = ((op_type == ternary_op)
? VEC_index (tree, vec_oprnds2, i) : NULL_TREE);
! new_stmt = gimple_build_assign_with_ops3 (code, vec_dest,
! vop0, vop1, vop2);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
--- 3702,3709 ----
? VEC_index (tree, vec_oprnds1, i) : NULL_TREE);
vop2 = ((op_type == ternary_op)
? VEC_index (tree, vec_oprnds2, i) : NULL_TREE);
! new_stmt = gimple_build_assign_with_ops (code, vec_dest,
! vop0, vop1, vop2);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
*************** permute_vec_elements (tree x, tree y, tr
*** 4235,4242 ****
data_ref = make_ssa_name (perm_dest, NULL);
/* Generate the permute statement. */
! perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, data_ref,
! x, y, mask_vec);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
return data_ref;
--- 4235,4242 ----
data_ref = make_ssa_name (perm_dest, NULL);
/* Generate the permute statement. */
! perm_stmt = gimple_build_assign_with_ops (VEC_PERM_EXPR, data_ref,
! x, y, mask_vec);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
return data_ref;
*************** vectorizable_load (gimple stmt, gimple_s
*** 5047,5055 ****
realignment_token = dataref_ptr;
vec_dest = vect_create_destination_var (scalar_dest, vectype);
new_stmt
! = gimple_build_assign_with_ops3 (REALIGN_LOAD_EXPR,
! vec_dest, msq, lsq,
! realignment_token);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
--- 5047,5055 ----
realignment_token = dataref_ptr;
vec_dest = vect_create_destination_var (scalar_dest, vectype);
new_stmt
! = gimple_build_assign_with_ops (REALIGN_LOAD_EXPR,
! vec_dest, msq, lsq,
! realignment_token);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
Index: trunk/gcc/statistics.h
===================================================================
*** trunk.orig/gcc/statistics.h 2012-08-15 14:42:31.000000000 +0200
--- trunk/gcc/statistics.h 2012-09-17 15:07:35.415054634 +0200
***************
*** 38,43 ****
--- 38,48 ----
#define PASS_MEM_STAT , ALONE_PASS_MEM_STAT
#define FINAL_PASS_MEM_STAT , ALONE_FINAL_PASS_MEM_STAT
#define MEM_STAT_INFO , ALONE_MEM_STAT_INFO
+ #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ #define CXX_MEM_STAT_INFO , const char * _loc_name = __builtin_FILE (), int _loc_line = __builtin_LINE (), const char * _loc_function = __builtin_FUNCTION ()
+ #else
+ #define CXX_MEM_STAT_INFO , const char * _loc_name = __FILE__, int _loc_line = __LINE__, const char * _loc_function = NULL
+ #endif
#else
#define ALONE_MEM_STAT_DECL void
#define ALONE_FINAL_MEM_STAT_DECL GCC_MEM_STAT_ARGUMENTS
***************
*** 49,54 ****
--- 54,60 ----
#define PASS_MEM_STAT
#define FINAL_PASS_MEM_STAT , ALONE_FINAL_PASS_MEM_STAT
#define MEM_STAT_INFO ALONE_MEM_STAT_INFO
+ #define CXX_MEM_STAT_INFO
#endif
struct function;