GCC Middle and Back End API Reference
ipa_param_body_adjustments Class Reference

#include <ipa-param-manipulation.h>

Collaboration diagram for ipa_param_body_adjustments:

Public Member Functions

 ipa_param_body_adjustments (ipa_param_adjustments *adjustments, tree fndecl, tree old_fndecl, struct copy_body_data *id, tree *vars, vec< ipa_replace_map *, va_gc > *tree_map)
 
 ipa_param_body_adjustments (ipa_param_adjustments *adjustments, tree fndecl)
 
 ipa_param_body_adjustments (vec< ipa_adjusted_param, va_gc > *adj_params, tree fndecl)
 
bool perform_cfun_body_modifications ()
 
void modify_formal_parameters ()
 
void register_replacement (tree base, unsigned unit_offset, tree replacement)
 
void register_replacement (ipa_adjusted_param *apm, tree replacement)
 
void sort_replacements ()
 
tree lookup_replacement (tree base, unsigned unit_offset)
 
ipa_param_body_replacementget_expr_replacement (tree expr, bool ignore_default_def)
 
tree get_replacement_ssa_base (tree old_decl)
 
bool modify_gimple_stmt (gimple **stmt, gimple_seq *extra_stmts, gimple *orig_stmt)
 
tree get_new_param_chain ()
 
void remap_with_debug_expressions (tree *t)
 
void append_init_stmts (basic_block bb)
 

Data Fields

vec< ipa_adjusted_param, va_gc > * m_adj_params
 
ipa_param_adjustmentsm_adjustments
 
auto_vec< tree, 16 > m_reset_debug_decls
 
hash_set< gimple * > m_dead_stmts
 
hash_set< treem_dead_ssas
 
hash_map< tree, treem_dead_ssa_debug_equiv
 
hash_map< gimple *, treem_dead_stmt_debug_equiv
 

Private Member Functions

void common_initialization (tree old_fndecl, tree *vars, vec< ipa_replace_map *, va_gc > *tree_map)
 
tree carry_over_param (tree t)
 
unsigned get_base_index (ipa_adjusted_param *apm)
 
ipa_param_body_replacementlookup_replacement_1 (tree base, unsigned unit_offset)
 
ipa_param_body_replacementlookup_first_base_replacement (tree base)
 
tree replace_removed_params_ssa_names (tree old_name, gimple *stmt)
 
bool modify_expression (tree *expr_p, bool convert, gimple_seq *=nullptr)
 
bool modify_assignment (gimple *stmt, gimple_seq *extra_stmts)
 
bool modify_call_stmt (gcall **stmt_p, gimple *orig_stmt)
 
bool modify_cfun_body ()
 
void reset_debug_stmts ()
 
tree get_ddef_if_exists_and_is_used (tree decl)
 
void mark_dead_statements (tree dead_param, vec< tree > *debugstack)
 
void mark_clobbers_dead (tree dead_param)
 
bool prepare_debug_expressions (tree dead_ssa)
 

Private Attributes

tree m_fndecl
 
struct copy_body_datam_id
 
auto_vec< tree, 16 > m_oparms
 
auto_vec< tree, 16 > m_new_decls
 
auto_vec< tree, 16 > m_new_types
 
auto_vec< ipa_param_body_replacement, 16 > m_replacements
 
auto_vec< gimple *, 8 > m_split_agg_csts_inits
 
auto_vec< treem_removed_decls
 
hash_map< tree, unsigned > m_removed_map
 
bool m_method2func
 
bool m_sorted_replacements_p
 

Detailed Description

Class used when actually performing adjustments to formal parameters of a
function to map accesses that need to be replaced to replacements.  The
class attempts to work in two very different sets of circumstances: as a
part of tree-inine.c's tree_function_versioning machinery to clone functions
(when M_ID is not NULL) and in s standalone fashion, modifying an existing
function in place (when M_ID is NULL).  While a lot of stuff handled in a
unified way in both modes, there are many aspects of the processs that
requires distinct paths.   

Constructor & Destructor Documentation

◆ ipa_param_body_adjustments() [1/3]

ipa_param_body_adjustments::ipa_param_body_adjustments ( ipa_param_adjustments * adjustments,
tree fndecl,
tree old_fndecl,
struct copy_body_data * id,
tree * vars,
vec< ipa_replace_map *, va_gc > * tree_map )
Constructor of ipa_param_body_adjustments which sets it up as a part of
running tree_function_versioning.  Planned modifications to the function are
in ADJUSTMENTS.  FNDECL designates the new function clone which is being
modified.  OLD_FNDECL is the function of which FNDECL is a clone (and which
at the time of invocation still share DECL_ARGUMENTS).  ID is the
copy_body_data structure driving the wholy body copying process.  VARS is a
pointer to the head of the list of new local variables, TREE_MAP is the map
that drives tree substitution in the cloning process.   

References common_initialization().

◆ ipa_param_body_adjustments() [2/3]

ipa_param_body_adjustments::ipa_param_body_adjustments ( ipa_param_adjustments * adjustments,
tree fndecl )
Constructor of ipa_param_body_adjustments from ipa_param_adjustments in
ADJUSTMENTS which will prepare ground for modification of parameters of
fndecl.  The object will assume it does not run as a part of
tree-function_versioning.   

References common_initialization(), and NULL.

◆ ipa_param_body_adjustments() [3/3]

ipa_param_body_adjustments::ipa_param_body_adjustments ( vec< ipa_adjusted_param, va_gc > * adj_params,
tree fndecl )
Constructor of ipa_param_body_adjustments from a simple list of
modifications to parameters listed in ADJ_PARAMS which will prepare ground
for modification of parameters of fndecl.  Return value of the function will
not be removed and the object will assume it does not run as a part of
tree-function_versioning.   

References common_initialization(), and NULL.

Member Function Documentation

◆ append_init_stmts()

void ipa_param_body_adjustments::append_init_stmts ( basic_block bb)
If there are any initialization statements that need to be emitted into
the basic block BB right at ther start of the new function, do so.   

References gsi_insert_after(), gsi_last_bb(), GSI_NEW_STMT, m_split_agg_csts_inits, and si.

Referenced by tree_function_versioning().

◆ carry_over_param()

tree ipa_param_body_adjustments::carry_over_param ( tree t)
private
Copy or not, as appropriate given m_id and decl context, a pre-existing
PARM_DECL T so that it can be included in the parameters of the modified
function.   

References copy_body_data::copy_decl, copy_node(), DECL_CONTEXT, m_fndecl, m_id, remap_decl(), and TREE_CODE.

Referenced by common_initialization().

◆ common_initialization()

void ipa_param_body_adjustments::common_initialization ( tree old_fndecl,
tree * vars,
vec< ipa_replace_map *, va_gc > * tree_map )
private
Common initialization performed by all ipa_param_body_adjustments
constructors.  OLD_FNDECL is the declaration we take original arguments
from, (it may be the same as M_FNDECL).  VARS, if non-NULL, is a pointer to
a chained list of new local variables.  TREE_MAP is the IPA-CP produced
mapping of trees to constants.

The function is rather long but it really onlu initializes all data members
of the class.  It creates new param DECLs, finds their new types,    

References AGGREGATE_TYPE_P, build_decl(), ipa_argagg_value::by_ref, carry_over_param(), copy_decl_to_var(), create_tmp_var, create_tmp_var_name(), DECL_ARG_TYPE, DECL_ARTIFICIAL, DECL_CHAIN, DECL_CONTEXT, DECL_IGNORED_P, copy_body_data::decl_map, DECL_NAME, fill_vector_of_new_param_types(), gcc_assert, gcc_checking_assert, gcc_unreachable, clone_info::get(), hash_map< KeyId, Value, Traits >::get(), ipa_param_adjustments::get_updated_indices(), gimple_build_assign(), i, ipa_argagg_value::index, insert_decl_map(), IPA_PARAM_OP_COPY, IPA_PARAM_OP_NEW, IPA_PARAM_OP_SPLIT, ipa_param_prefixes, ipcp_get_transformation_summary(), is_gimple_reg(), layout_decl(), lookup_replacement_1(), m_adj_params, m_fndecl, m_id, m_method2func, m_new_decls, m_new_types, m_oparms, m_removed_decls, m_removed_map, m_reset_debug_decls, m_split_agg_csts_inits, mark_clobbers_dead(), mark_dead_statements(), MAY_HAVE_DEBUG_STMTS, NULL_TREE, ipa_adjusted_param::op, clone_info::param_adjustments, ipa_adjusted_param::param_prefix_index, prepare_debug_expressions(), ipa_adjusted_param::prev_clone_adjustment, ipa_adjusted_param::prev_clone_index, push_function_arg_decls(), push_function_arg_types(), hash_map< KeyId, Value, Traits >::put(), register_replacement(), ipa_param_body_replacement::repl, sort_replacements(), copy_body_data::src_node, TREE_CODE, TREE_TYPE, TREE_USED, TYPE_ARG_TYPES, ipa_argagg_value::unit_offset, UNKNOWN_LOCATION, ipa_argagg_value::value, and vec_safe_length().

Referenced by ipa_param_body_adjustments(), ipa_param_body_adjustments(), and ipa_param_body_adjustments().

◆ get_base_index()

unsigned ipa_param_body_adjustments::get_base_index ( ipa_adjusted_param * apm)
private

◆ get_ddef_if_exists_and_is_used()

tree ipa_param_body_adjustments::get_ddef_if_exists_and_is_used ( tree decl)
private
If DECL is a gimple register that has a default definition SSA name and that
has some uses, return the default definition, otherwise return NULL_TREE.   

References has_zero_uses(), is_gimple_reg(), m_id, NULL_TREE, copy_body_data::src_cfun, and ssa_default_def().

Referenced by mark_clobbers_dead(), and mark_dead_statements().

◆ get_expr_replacement()

ipa_param_body_replacement * ipa_param_body_adjustments::get_expr_replacement ( tree expr,
bool ignore_default_def )
Given an expression, return the structure describing how it should be
replaced if it accesses a part of a split parameter or NULL otherwise.

Do not free the result, it will be deallocated when the object is destroyed.

If IGNORE_DEFAULT_DEF is cleared, consider only SSA_NAMEs of PARM_DECLs
which are default definitions, if set, consider all SSA_NAMEs of
PARM_DECLs.   

References get_ssa_base_param(), isra_get_ref_base_and_offset(), lookup_replacement_1(), NULL, and TREE_CODE.

Referenced by ipa_simd_modify_stmt_ops(), and modify_expression().

◆ get_new_param_chain()

tree ipa_param_body_adjustments::get_new_param_chain ( )
Chain new param decls up and return them.   

References DECL_CHAIN, i, m_adj_params, m_new_decls, NULL_TREE, and vec_safe_length().

Referenced by modify_formal_parameters(), and tree_function_versioning().

◆ get_replacement_ssa_base()

tree ipa_param_body_adjustments::get_replacement_ssa_base ( tree old_decl)
Given OLD_DECL, which is a PARM_DECL of a parameter that is being removed
(which includes it being split or replaced), return a new variable that
should be used for any SSA names that will remain in the function that
previously belonged to OLD_DECL.   

References copy_var_decl(), DECL_NAME, gcc_assert, hash_map< KeyId, Value, Traits >::get(), m_removed_decls, m_removed_map, NULL, TREE_CODE, and TREE_TYPE.

Referenced by ipa_simd_modify_function_body(), and replace_removed_params_ssa_names().

◆ lookup_first_base_replacement()

ipa_param_body_replacement * ipa_param_body_adjustments::lookup_first_base_replacement ( tree base)
private
Find the first replacement for BASE among m_replacements and return pointer
to it, or NULL if there is none.   

References ipa_param_body_replacement::base, gcc_assert, m_replacements, m_sorted_replacements_p, and NULL.

Referenced by modify_call_stmt().

◆ lookup_replacement()

tree ipa_param_body_adjustments::lookup_replacement ( tree base,
unsigned unit_offset )
Given BASE and UNIT_OFFSET, find the corresponding replacement expression
and return it, assuming it is known it does not hold value by reference or
in reverse storage order.   

References lookup_replacement_1(), NULL, and ipa_param_body_replacement::repl.

Referenced by ipa_simd_modify_function_body().

◆ lookup_replacement_1()

ipa_param_body_replacement * ipa_param_body_adjustments::lookup_replacement_1 ( tree base,
unsigned unit_offset )
private
Given BASE and UNIT_OFFSET, find the corresponding record among replacement
structures.   

References ipa_param_body_replacement::base, gcc_assert, m_replacements, m_sorted_replacements_p, NULL, and ipa_param_body_replacement::unit_offset.

Referenced by common_initialization(), get_expr_replacement(), lookup_replacement(), and modify_call_stmt().

◆ mark_clobbers_dead()

void ipa_param_body_adjustments::mark_clobbers_dead ( tree param)
private
Put all clobbers of of dereference of default definition of PARAM into
m_dead_stmts.  If there are returns among uses of the default definition of
PARAM, verify they will be stripped off the return value.   

References hash_set< KeyId, Lazy, Traits >::add(), FOR_EACH_IMM_USE_FAST, gcc_assert, get_ddef_if_exists_and_is_used(), gimple_clobber_p(), is_gimple_reg(), m_adjustments, m_dead_stmts, ipa_param_adjustments::m_skip_return, and USE_STMT.

Referenced by common_initialization().

◆ mark_dead_statements()

void ipa_param_body_adjustments::mark_dead_statements ( tree dead_param,
vec< tree > * debugstack )
private

◆ modify_assignment()

bool ipa_param_body_adjustments::modify_assignment ( gimple * stmt,
gimple_seq * extra_stmts )
private
If the assignment statement STMT contains any expressions that need to
replaced with a different one as noted by ADJUSTMENTS, do so.  Handle any
potential type incompatibilities.  If any conversion sttements have to be
pre-pended to STMT, they will be added to EXTRA_STMTS.  Return true iff the
statement was modified.   

References build_constructor(), build_zero_cst(), fold_build1_loc(), force_gimple_operand(), gcc_checking_assert, gimple_assign_lhs_ptr(), gimple_assign_rhs1_ptr(), gimple_assign_set_rhs1(), gimple_assign_single_p(), gimple_location(), is_gimple_reg_type(), m_replacements, modify_expression(), NULL, NULL_TREE, TREE_CODE, tree_to_shwi(), TREE_TYPE, TYPE_SIZE, and useless_type_conversion_p().

Referenced by modify_gimple_stmt().

◆ modify_call_stmt()

bool ipa_param_body_adjustments::modify_call_stmt ( gcall ** stmt_p,
gimple * orig_stmt )
private
If the call statement pointed at by STMT_P contains any expressions that
need to replaced with a different one as noted by ADJUSTMENTS, do so.  f the
statement needs to be rebuilt, do so.  Return true if any modifications have
been performed.  ORIG_STMT, if not NULL, is the original statement in the
function that is being cloned from, which at this point can be used to look
up call_graph edges.

If the method is invoked as a part of IPA clone materialization and if any
parameter split is pass-through, i.e. it applies to the functin that is
being modified and also to the callee of the statement, replace the
parameter passed to old callee with all of the replacement a callee might
possibly want and record the performed argument modifications in
ipa_edge_modifications.  Likewise if any argument has already been left out
because it is not necessary.   

References AGGREGATE_TYPE_P, pass_through_split_map::base_index, hash_set< KeyId, Lazy, Traits >::contains(), gcc_assert, gcc_checking_assert, gimple_build_call_vec(), gimple_call_arg(), gimple_call_arg_ptr(), gimple_call_chain(), gimple_call_copy_flags(), gimple_call_fn(), gimple_call_lhs(), gimple_call_lhs_ptr(), gimple_call_num_args(), gimple_call_set_chain(), gimple_has_location(), gimple_location(), gimple_set_location(), i, isra_get_ref_base_and_offset(), lookup_first_base_replacement(), lookup_replacement_1(), m_dead_ssas, m_id, m_replacements, m_sorted_replacements_p, modify_expression(), pass_through_split_map::new_index, POINTER_TYPE_P, record_argument_state(), ipa_param_body_replacement::repl, SSA_NAME_IS_DEFAULT_DEF, SSA_NAME_VAR, TREE_CODE, TREE_TYPE, TYPE_MAIN_VARIANT, and pass_through_split_map::unit_offset.

Referenced by modify_gimple_stmt().

◆ modify_cfun_body()

◆ modify_expression()

bool ipa_param_body_adjustments::modify_expression ( tree * expr_p,
bool convert,
gimple_seq * extra_stmts = nullptr )
private
If the expression *EXPR_P should be replaced, do so.  CONVERT specifies
whether the function should care about type incompatibility of the current
and new expressions.  If it is false, the function will leave
incompatibility issues to the caller - note that when the function
encounters a BIT_FIELD_REF, IMAGPART_EXPR or REALPART_EXPR, it will modify
their bases instead of the expressions themselves and then also performs any
necessary conversions.   

References build1(), convert(), dump_file, dump_flags, force_gimple_operand(), gcc_assert, gcc_checking_assert, get_expr_replacement(), is_gimple_reg(), is_gimple_reg_type(), m_replacements, NULL_TREE, print_generic_expr(), ipa_param_body_replacement::repl, TDF_DETAILS, TREE_CODE, TREE_OPERAND, tree_to_shwi(), TREE_TYPE, TYPE_SIZE, and useless_type_conversion_p().

Referenced by modify_assignment(), modify_call_stmt(), and modify_gimple_stmt().

◆ modify_formal_parameters()

void ipa_param_body_adjustments::modify_formal_parameters ( )
Modify the function parameters FNDECL and its type according to the plan in
ADJUSTMENTS.  This function needs to be called when the decl has not already
been processed with ipa_param_adjustments::adjust_decl, otherwise just
seting DECL_ARGUMENTS to whatever get_new_param_chain will do is enough.   

References build_adjusted_function_type(), DECL_ARGUMENTS, DECL_LANG_SPECIFIC, DECL_VINDEX, DECL_VIRTUAL_P, fndecl_built_in_p(), gcc_assert, get_new_param_chain(), IPA_PARAM_OP_COPY, m_adj_params, m_adjustments, m_fndecl, m_method2func, m_new_types, ipa_param_adjustments::m_skip_return, NOT_BUILT_IN, NULL, NULL_TREE, set_decl_built_in_function(), TREE_CHAIN, TREE_TYPE, and TYPE_ARG_TYPES.

Referenced by duplicate_thunk_for_node(), perform_cfun_body_modifications(), and simd_clone_adjust().

◆ modify_gimple_stmt()

bool ipa_param_body_adjustments::modify_gimple_stmt ( gimple ** stmt,
gimple_seq * extra_stmts,
gimple * orig_stmt )
If the statement STMT contains any expressions that need to replaced with a
different one as noted by ADJUSTMENTS, do so.  Handle any potential type
incompatibilities.  If any conversion sttements have to be pre-pended to
STMT, they will be added to EXTRA_STMTS.  Return true iff the statement was
modified.   

References as_a(), gimple_asm_input_op(), gimple_asm_ninputs(), gimple_asm_noutputs(), gimple_asm_output_op(), gimple_return_retval_ptr(), i, m_adjustments, ipa_param_adjustments::m_skip_return, modify_assignment(), modify_call_stmt(), modify_expression(), NULL_TREE, and TREE_VALUE.

Referenced by modify_cfun_body().

◆ perform_cfun_body_modifications()

bool ipa_param_body_adjustments::perform_cfun_body_modifications ( )
Perform all necessary body changes to change signature, body and debug info
of fun according to adjustments passed at construction.  Return true if CFG
was changed in any way.  The main entry point for modification of standalone
functions that is not part of IPA clone materialization.   

References cfg_changed, modify_cfun_body(), modify_formal_parameters(), and reset_debug_stmts().

◆ prepare_debug_expressions()

bool ipa_param_body_adjustments::prepare_debug_expressions ( tree dead_ssa)
private
For an SSA_NAME DEAD_SSA which is about to be DCEd because it is based on a
useless parameter, prepare an expression that should represent it in
debug_binds in the cloned function and add a mapping from DEAD_SSA to
m_dead_ssa_debug_equiv.  That mapping is to NULL when the associated
debug_statement has to be reset instead.  In such case return false,
ottherwise return true.  If DEAD_SSA comes from a basic block which is not
about to be copied, ignore it and return true.   

References as_a(), bitmap_bit_p, copy_body_data::blocks_to_copy, build_debug_expr_decl(), hash_set< KeyId, Lazy, Traits >::contains(), degenerate_phi_result(), FOR_EACH_PHI_OR_STMT_USE, gcc_assert, gcc_checking_assert, gcc_unreachable, hash_map< KeyId, Value, Traits >::get(), gimple_assign_copy_p(), gimple_assign_rhs1(), gimple_assign_rhs_to_tree(), gimple_bb(), gimple_clobber_p(), is_gimple_assign(), m_dead_ssa_debug_equiv, m_dead_ssas, m_dead_stmt_debug_equiv, m_id, NULL_TREE, prepare_debug_expressions(), hash_map< KeyId, Value, Traits >::put(), remap_with_debug_expressions(), SSA_NAME_DEF_STMT, SSA_NAME_IS_DEFAULT_DEF, SSA_OP_USE, TREE_CODE, TREE_TYPE, unshare_expr_without_location(), and USE_FROM_PTR.

Referenced by common_initialization(), and prepare_debug_expressions().

◆ register_replacement() [1/2]

void ipa_param_body_adjustments::register_replacement ( ipa_adjusted_param * apm,
tree replacement )

◆ register_replacement() [2/2]

void ipa_param_body_adjustments::register_replacement ( tree base,
unsigned unit_offset,
tree replacement )

◆ remap_with_debug_expressions()

void ipa_param_body_adjustments::remap_with_debug_expressions ( tree * t)
Replace all occurances of SSAs in m_dead_ssa_debug_equiv in t with what they
are mapped to.   

References error_mark_node, hash_map< KeyId, Value, Traits >::get(), m_dead_ssa_debug_equiv, NULL, NULL_TREE, replace_with_mapped_expr(), TREE_CODE, and walk_tree.

Referenced by prepare_debug_expressions().

◆ replace_removed_params_ssa_names()

tree ipa_param_body_adjustments::replace_removed_params_ssa_names ( tree old_name,
gimple * stmt )
private
If OLD_NAME, which is being defined by statement STMT, is an SSA_NAME of a
parameter which is to be removed because its value is not used, create a new
SSA_NAME relating to a replacement VAR_DECL, replace all uses of the
original with it and return it.  If there is no need to re-map, return NULL.
ADJUSTMENTS is a pointer to a vector of IPA-SRA adjustments.   

References dump_file, dump_flags, gcc_assert, get_replacement_ssa_base(), m_id, make_ssa_name(), NULL, NULL_TREE, print_generic_expr(), replace_uses_by(), SSA_NAME_OCCURS_IN_ABNORMAL_PHI, SSA_NAME_VAR, TDF_DETAILS, and TREE_CODE.

Referenced by modify_cfun_body().

◆ reset_debug_stmts()

◆ sort_replacements()

void ipa_param_body_adjustments::sort_replacements ( )
Sort m_replacements and set m_sorted_replacements_p to true.   

References compare_param_body_replacement(), m_replacements, and m_sorted_replacements_p.

Referenced by common_initialization(), and ipa_simd_modify_function_body().

Field Documentation

◆ m_adj_params

◆ m_adjustments

◆ m_dead_ssa_debug_equiv

hash_map<tree, tree> ipa_param_body_adjustments::m_dead_ssa_debug_equiv

◆ m_dead_ssas

hash_set<tree> ipa_param_body_adjustments::m_dead_ssas

◆ m_dead_stmt_debug_equiv

hash_map<gimple *, tree> ipa_param_body_adjustments::m_dead_stmt_debug_equiv

◆ m_dead_stmts

hash_set<gimple *> ipa_param_body_adjustments::m_dead_stmts

◆ m_fndecl

tree ipa_param_body_adjustments::m_fndecl
private

◆ m_id

◆ m_method2func

bool ipa_param_body_adjustments::m_method2func
private

◆ m_new_decls

auto_vec<tree, 16> ipa_param_body_adjustments::m_new_decls
private

◆ m_new_types

auto_vec<tree, 16> ipa_param_body_adjustments::m_new_types
private

◆ m_oparms

auto_vec<tree, 16> ipa_param_body_adjustments::m_oparms
private

◆ m_removed_decls

auto_vec<tree> ipa_param_body_adjustments::m_removed_decls
private

◆ m_removed_map

hash_map<tree, unsigned> ipa_param_body_adjustments::m_removed_map
private

◆ m_replacements

◆ m_reset_debug_decls

auto_vec<tree, 16> ipa_param_body_adjustments::m_reset_debug_decls

◆ m_sorted_replacements_p

bool ipa_param_body_adjustments::m_sorted_replacements_p
private

◆ m_split_agg_csts_inits

auto_vec<gimple *, 8> ipa_param_body_adjustments::m_split_agg_csts_inits
private

The documentation for this class was generated from the following files: