PIPS
inlining.c File Reference

add inlining support to pips, with two flavors More...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "effects.h"
#include "ri-util.h"
#include "prettyprint.h"
#include "effects-util.h"
#include "text.h"
#include "pipsdbm.h"
#include "workspace-util.h"
#include "resources.h"
#include "properties.h"
#include "misc.h"
#include "callgraph.h"
#include "effects-generic.h"
#include "effects-convex.h"
#include "preprocessor.h"
#include "text-util.h"
#include "parser_private.h"
#include "pipsmake.h"
#include "accel-util.h"
+ Include dependency graph for inlining.c:

Go to the source code of this file.

Data Structures

struct  iparam
 structure containing all the parameters needed by inlining. More...
 

Functions

unfolding
static bool run_inlining (string caller_name, const char *module_name, inlining_parameters p)
 get ressources for the call to inline and call apropriate inlining function More...
 
static bool do_unfolding (inlining_parameters p, char *module_name)
 this should inline all call in module ‘module_name’ it does not works recursievly, so multiple pass may be needed returns true if at least one function has been inlined More...
 
bool unfolding (char *module_name)
 perform unfolding using effect More...
 
bool unfolding_simple (char *module_name)
 perform unfolding without using effects More...
 

inlining

#define IPARAM_INIT
 
#define inlined_module(p)   (p)->_inlined_module_
 
#define inlined_module_statement(p)   (p)->_inlined_module_statement_
 
#define new_statements(p)   (p)->_new_statements_
 
#define has_static_declaration(p)   (p)->_has_static_declaration_
 
#define has_inlinable_calls(p)   (p)->_has_inlinable_calls_
 
#define laststmt(p)   (p)->_laststmt_
 
#define tail_ins(p)   (p)->_tail_ins_
 
#define returned_entity(p)   (p)->_returned_entity_
 
#define use_effects(p)   (p)->_use_effects_
 
typedef struct iparaminlining_parameters
 
static statement expanded
 
static void inline_return_remover (statement s, inlining_parameters p)
 replace return instruction by a goto More...
 
static void inline_return_crawler (statement s, inlining_parameters p)
 replace return instruction by an assignment and a goto More...
 
static bool inline_should_inline (entity inlined_module, call callee)
 helper function to check if a call is a call to the inlined function More...
 
static bool has_similar_entity (entity e, set se)
 
static void solve_name_clashes (statement s, entity new)
 look for entity locally named has ‘new’ in statements ‘s’ when found, find a new name and perform substitution More...
 
static bool inline_has_static_declaration (list iter)
 return true if an entity declared in ‘iter’ is static to ‘module’ More...
 
static void statement_with_static_declarations_p (statement s, inlining_parameters p)
 return true if an entity declared in the statement ‘s’ from ‘p->inlined_module’ More...
 
static entity make_temporary_scalar_entity (expression from, statement *assign)
 create a scalar similar to ‘efrom’ initialized with expression ‘from’ More...
 
static void inlining_regenerate_labels (statement s, entity new_module)
 regenerate the label of each statement with a label. More...
 
bool has_entity_with_same_name (entity e, list l)
 inlining.c More...
 
static void do_slightly_rename_entities (statement s, hash_table old_new)
 
static void slightly_rename_entities (statement s)
 sg: this is another inlining mostruosity it ensures all entities in s have new pointer and different name (is it usefull ?) it takes care of dependant types More...
 
static statement inline_expression_call (inlining_parameters p, expression modified_expression, call callee)
 this should inline the call callee calling module inlined_module More...
 
static void inline_expression (expression expr, inlining_parameters p)
 recursievly inline an expression if needed More...
 
static void inline_has_inlinable_calls_crawler (call callee, inlining_parameters p)
 check if a call has inlinable calls More...
 
static bool inline_has_inlinable_calls (entity inlined_module, void *elem)
 
static void inline_statement_crawler (statement stmt, inlining_parameters p)
 this is in charge of replacing instruction by new ones only apply if this instruction does not contain other instructions More...
 
static void inline_split_declarations (statement s, entity inlined_module)
 split the declarations from s from their initialization if they contain a call to inlined_module More...
 
static void inline_calls (inlining_parameters p, char *module)
 this should replace all call to ‘inlined’ in ‘module’ by the expansion of ‘inlined’ More...
 
static bool do_inlining (inlining_parameters p, const char *module_name)
 this should inline all calls to module ‘module_name’ in calling modules, if possible ... More...
 
bool inlining (const char *module_name)
 perform inlining using effects More...
 
bool inlining_simple (const char *module_name)
 perform inlining without using effects More...
 

Detailed Description

add inlining support to pips, with two flavors

Author
Serge Guelton serge.nosp@m..gue.nosp@m.lton@.nosp@m.enst.nosp@m.-bret.nosp@m.agne.nosp@m..fr I am not proud of this code, it is a real mess !
Date
2009-01-07

Definition in file inlining.c.

Macro Definition Documentation

◆ has_inlinable_calls

#define has_inlinable_calls (   p)    (p)->_has_inlinable_calls_

Definition at line 99 of file inlining.c.

◆ has_static_declaration

#define has_static_declaration (   p)    (p)->_has_static_declaration_

Definition at line 98 of file inlining.c.

◆ inlined_module

#define inlined_module (   p)    (p)->_inlined_module_

Definition at line 95 of file inlining.c.

◆ inlined_module_statement

#define inlined_module_statement (   p)    (p)->_inlined_module_statement_

Definition at line 96 of file inlining.c.

◆ IPARAM_INIT

#define IPARAM_INIT
Value:
{ \
._inlined_module_=entity_undefined,\
._inlined_module_statement_=statement_undefined,\
._new_statements_=statement_undefined,\
._has_static_declaration_=false,\
._has_inlinable_calls_=false,\
._laststmt_=statement_undefined,\
._tail_ins_=instruction_undefined,\
._returned_entity_=entity_undefined,\
._use_effects_=true\
}
#define instruction_undefined
Definition: ri.h:1454
#define entity_undefined
Definition: ri.h:2761
#define statement_undefined
Definition: ri.h:2419

Definition at line 84 of file inlining.c.

◆ laststmt

#define laststmt (   p)    (p)->_laststmt_

Definition at line 100 of file inlining.c.

◆ new_statements

#define new_statements (   p)    (p)->_new_statements_

Definition at line 97 of file inlining.c.

◆ returned_entity

#define returned_entity (   p)    (p)->_returned_entity_

Definition at line 102 of file inlining.c.

◆ tail_ins

#define tail_ins (   p)    (p)->_tail_ins_

Definition at line 101 of file inlining.c.

◆ use_effects

#define use_effects (   p)    (p)->_use_effects_

Definition at line 103 of file inlining.c.

Typedef Documentation

◆ inlining_parameters

typedef struct iparam * inlining_parameters

Function Documentation

◆ do_inlining()

static bool do_inlining ( inlining_parameters  p,
const char *  module_name 
)
static

this should inline all calls to module ‘module_name’ in calling modules, if possible ...

Parameters
module_namename of the module to inline
Returns
true if we did something

Get the module ressource

check them

parse filter property

or get module's callers

inline call in each caller

Should have worked:

Definition at line 885 of file inlining.c.

886 {
887  if(get_bool_property("INLINING_IGNORE_STUBS") && db_resource_p(DBR_STUBS, "")) {
888  // Look for stubs and prevent inlining them
889  callees stubs=(callees)db_get_memory_resource(DBR_STUBS,"",true);
890  FOREACH(string,stub,callees_callees(stubs)) {
891  if(same_string_p(module_name,stub)) {
892  return true;
893  }
894  }
895  }
896 
897  /* Get the module ressource */
900 
902 
903  /* check them */
906  debug_on("INLINING_DEBUG_LEVEL");
907 
908 
909  /* parse filter property */
910  string inlining_callers_name = strdup(get_string_property("INLINING_CALLERS"));
911  list callers_l = NIL;
912 
913  string c_name= NULL;
914  for(c_name = strtok(inlining_callers_name," ") ; c_name ; c_name=strtok(NULL," ") )
915  {
916  callers_l = CONS(STRING, c_name, callers_l);
917  }
918  /* or get module's callers */
919  callees callers = (callees)db_get_memory_resource(DBR_CALLERS, module_name, true);
920  if(ENDP(callers_l))
921  {
922  callers_l = callees_callees(callers);
923  }
924 
925  /* inline call in each caller */
926  FOREACH(STRING, caller_name,callers_l)
927  {
930  }
931  FOREACH(STRING,c0,callers_l) {
932  FOREACH(STRING,c1,callees_callees(callers)) {
933  if(same_string_p(c0,c1)) {
934  gen_remove_once(&callees_callees(callers),c1);
935  break;
936  }
937  }
938  }
939 
940  DB_PUT_MEMORY_RESOURCE(DBR_CALLERS,module_name,callers);
941 
943 
944  pips_debug(2, "inlining done for %s\n", module_name);
945  debug_off();
946  /* Should have worked: */
947  return true;
948 }
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524
static const char * caller_name
Definition: alias_check.c:122
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
void set_cumulated_rw_effects(statement_effects)
void reset_cumulated_rw_effects(void)
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
char * get_string_property(const char *)
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
#define STRING(x)
Definition: genC.h:87
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
void gen_remove_once(list *pl, const void *o)
Remove the first occurence of o in list pl:
Definition: list.c:691
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
#define inlined_module(p)
Definition: inlining.c:95
#define use_effects(p)
Definition: inlining.c:103
static void inline_calls(inlining_parameters p, char *module)
this should replace all call to ‘inlined’ in ‘module’ by the expansion of ‘inlined’
Definition: inlining.c:848
#define inlined_module_statement(p)
Definition: inlining.c:96
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
#define same_string_p(s1, s2)
bool recompile_module(const string module)
build a textual representation of the modified module and update db
Definition: module.c:87
bool entity_subroutine_p(entity e)
Definition: entity.c:737
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool entity_function_p(entity e)
Definition: entity.c:724
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define callees_callees(x)
Definition: ri.h:675
#define statement_undefined_p(x)
Definition: ri.h:2420
char * strdup()
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References callees_callees, caller_name, CONS, db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, db_resource_p(), debug_off, debug_on, ENDP, entity_function_p(), entity_subroutine_p(), FOREACH, gen_remove_once(), get_bool_property(), get_string_property(), inline_calls(), inlined_module, inlined_module_statement, module_name(), module_name_to_entity(), NIL, pips_assert, pips_debug, recompile_module(), reset_cumulated_rw_effects(), same_string_p, set_cumulated_rw_effects(), statement_undefined_p, strdup(), STRING, and use_effects.

Referenced by inlining(), and inlining_simple().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ do_slightly_rename_entities()

static void do_slightly_rename_entities ( statement  s,
hash_table  old_new 
)
static

forge a new name with a magical block number

beacause of bottom up transversal, we are sure old_new has already been fed

Definition at line 262 of file inlining.c.

262  {
263  static const unsigned int magic_block_number = (unsigned int)-1;
264  /* forge a new name with a magical block number */
265  if(declaration_statement_p(s)) {
266  for(list iter=statement_declarations(s);!ENDP(iter);POP(iter)) {
267  entity *e=(entity*)REFCAR(iter);
268  if(!formal_parameter_p(*e)) {
269  entity ebis = copy_entity(*e);
270  char* ename = entity_name(ebis);
271  const char* euname = entity_user_name(ebis);
272  const char* eprefix = strndup(ename,euname-ename);
273  asprintf(&entity_name(ebis),"%s%u"BLOCK_SEP_STRING"%s",eprefix,magic_block_number,euname);
274  free(ename);
275  hash_put(old_new,*e,ebis);
276  *e=ebis;
277  }
278  }
279  }
280  /* beacause of bottom up transversal,
281  * we are sure old_new has already been fed
282  */
283  else if(statement_block_p(s)) {
284  for(list iter=statement_declarations(s);!ENDP(iter);POP(iter)) {
285  entity *e=(entity*)REFCAR(iter);
286  entity new = (entity)hash_get(old_new,*e);
287  if(new != HASH_UNDEFINED_VALUE)
288  *e=new;
289  }
290  }
291 }
entity copy_entity(entity p)
ENTITY.
Definition: ri.c:2521
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
void const char const char const int
void free(void *)
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define REFCAR(pc)
Get the adress of the first element of a list.
Definition: newgen_list.h:119
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_put(hash_table htp, const void *key, const void *val)
This functions stores a couple (key,val) in the hash table pointed to by htp.
Definition: hash.c:364
#define asprintf
Definition: misc-local.h:225
#define BLOCK_SEP_STRING
Scope separator.
Definition: naming-local.h:50
#define HASH_UNDEFINED_VALUE
value returned by hash_get() when the key is not found; could also be called HASH_KEY_NOT_FOUND,...
Definition: newgen_hash.h:56
#define statement_block_p(stat)
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define entity_name(x)
Definition: ri.h:2790
#define statement_declarations(x)
Definition: ri.h:2460
char * strndup(char const *s, size_t n)
A replacement function, for systems that lack strndup.
Definition: strndup.c:26

References asprintf, BLOCK_SEP_STRING, copy_entity(), declaration_statement_p(), ENDP, entity_name, entity_user_name(), formal_parameter_p(), free(), hash_get(), hash_put(), HASH_UNDEFINED_VALUE, int, POP, REFCAR, statement_block_p, statement_declarations, and strndup().

Referenced by slightly_rename_entities().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ do_unfolding()

static bool do_unfolding ( inlining_parameters  p,
char *  module_name 
)
static

this should inline all call in module ‘module_name’ it does not works recursievly, so multiple pass may be needed returns true if at least one function has been inlined

Parameters
module_namename of the module to unfold
Returns
true if we did something

parse filter property

parse callee property

gather all referenced calls as long as there are some

gather all referenced calls

maybe the user put a restriction on the calls to inline ?

maybe the user used a filter ?

there is something to inline

Definition at line 1032 of file inlining.c.

1033 {
1034  debug_on("UNFOLDING_DEBUG_LEVEL");
1035 
1036  /* parse filter property */
1037  string unfolding_filter_names = strdup(get_string_property("UNFOLDING_FILTER"));
1038  set unfolding_filters = set_make(set_string);
1039 
1040  list filtersname = strsplit(unfolding_filter_names," ");
1041  FOREACH(STRING,filter_name,filtersname)
1042  {
1043  set_add_element(unfolding_filters, unfolding_filters, filter_name);
1045  }
1046  gen_map(free,filtersname);gen_free_list(filtersname);
1047 
1048  /* parse callee property */
1049  string unfolding_callees_names = strdup(get_string_property("UNFOLDING_CALLEES"));
1050  set unfolding_callees = set_make(set_string);
1051 
1052  string callee_name= NULL;
1053  for(callee_name = strtok(unfolding_callees_names," ") ; callee_name ; callee_name=strtok(NULL," ") )
1054  {
1055  set_add_element(unfolding_callees, unfolding_callees, callee_name);
1056  }
1057 
1058  /* gather all referenced calls as long as there are some */
1059  bool statement_has_callee = false;
1060  do {
1061  statement_has_callee = false;
1062  statement unfolded_module_statement =
1063  (statement) db_get_memory_resource(DBR_CODE, module_name, true);
1064  /* gather all referenced calls */
1065  callees cc =compute_callees(unfolded_module_statement);
1066  set calls_name = set_make(set_string);
1067  set_assign_list(calls_name,callees_callees(cc));
1068 
1069 
1070  /* maybe the user put a restriction on the calls to inline ?*/
1071  if(!set_empty_p(unfolding_callees))
1072  calls_name=set_intersection(calls_name,calls_name,unfolding_callees);
1073 
1074  /* maybe the user used a filter ?*/
1075  calls_name=set_difference(calls_name,calls_name,unfolding_filters);
1076 
1077 
1078 
1079  /* there is something to inline */
1080  if( (statement_has_callee=!set_empty_p(calls_name)) )
1081  {
1083  FOREACH(STRING,call_name,sorted) {
1084  if(!run_inlining(module_name,call_name,p))
1085  set_add_element(unfolding_filters,unfolding_filters,call_name);
1086  }
1087  free(sorted);
1089 #if 0
1090  /* we can try to remove some labels now*/
1091  if( get_bool_property("INLINING_PURGE_LABELS"))
1093  pips_user_warning("failed to remove useless labels after restructure_control in inlining");
1094 #endif
1095  }
1096  set_free(calls_name);
1097  free_callees(cc);
1098  } while(statement_has_callee);
1099 
1100  set_free(unfolding_filters);
1101  free(unfolding_filter_names);
1102 
1103 
1104  pips_debug(2, "unfolding done for %s\n", module_name);
1105 
1106  debug_off();
1107  return true;
1108 }
void free_callees(callees p)
Definition: ri.c:194
callees compute_callees(const statement stat)
Recompute the callees of a module statement.
Definition: callgraph.c:355
void gen_map(gen_iter_func_t fp, const list l)
Definition: list.c:172
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
static bool run_inlining(string caller_name, const char *module_name, inlining_parameters p)
get ressources for the call to inline and call apropriate inlining function
Definition: inlining.c:992
#define pips_user_warning
Definition: misc-local.h:146
list strsplit(const char *, const char *)
Definition: string.c:318
int gen_qsort_string_cmp(const void *, const void *)
Callback for sorting string with qsort.
Definition: string.c:332
bool set_empty_p(const set)
tell whether set s is empty.
Definition: set.c:367
set set_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
set set_intersection(set, const set, const set)
Definition: set.c:229
list set_to_sorted_list(const set, gen_cmp_func_t)
Definition: set.c:447
set set_difference(set, const set, const set)
Definition: set.c:256
void set_free(set)
Definition: set.c:332
@ set_string
Definition: newgen_set.h:42
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
bool remove_useless_label(const string)

References callees_callees, compute_callees(), db_get_memory_resource(), debug_off, debug_on, FOREACH, free(), free_callees(), gen_free_list(), gen_map(), gen_qsort_string_cmp(), get_bool_property(), get_string_property(), module_name(), pips_debug, pips_user_warning, recompile_module(), remove_useless_label(), run_inlining(), set_add_element(), set_assign_list(), set_difference(), set_empty_p(), set_free(), set_intersection(), set_make(), set_string, set_to_sorted_list(), strdup(), STRING, and strsplit().

Referenced by unfolding(), and unfolding_simple().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ has_entity_with_same_name()

bool has_entity_with_same_name ( entity  e,
list  l 
)

inlining.c

Definition at line 256 of file inlining.c.

256  {
257  FOREACH(ENTITY,ent,l)
258  if(same_entity_name_p(e,ent)) return true;
259  return false;
260 }
bool same_entity_name_p(entity e1, entity e2)
compare entity names
Definition: entity.c:2208
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755

References ENTITY, FOREACH, and same_entity_name_p().

Referenced by check_private_variables_loop_walker(), inline_expression_call(), and outliner_independent_recursively().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ has_similar_entity()

static bool has_similar_entity ( entity  e,
set  se 
)
static

Definition at line 148 of file inlining.c.

149 {
150  SET_FOREACH(entity,ee,se)
152  return true;
153  return false;
154 }
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78

References entity_user_name(), same_string_p, and SET_FOREACH.

Referenced by solve_name_clashes().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_calls()

static void inline_calls ( inlining_parameters  p,
char *  module 
)
static

this should replace all call to ‘inlined’ in ‘module’ by the expansion of ‘inlined’

get target module's ressources

first pass : convert some declaration with assignment to declarations + statements, if needed

inline all calls to inlined_module

Definition at line 848 of file inlining.c.

849 {
850  entity modified_module = module_name_to_entity(module);
851  /* get target module's ressources */
852  statement modified_module_statement =
853  (statement) db_get_memory_resource(DBR_CODE, module, true);
854  pips_assert("statements found", !statement_undefined_p(modified_module_statement) );
855  pips_debug(2,"inlining %s in %s\n",entity_user_name(inlined_module(p)),module);
856 
857  set_current_module_entity( modified_module );
858  set_current_module_statement( modified_module_statement );
859 
860  /* first pass : convert some declaration with assignment to declarations + statements, if needed */
862  /* inline all calls to inlined_module */
864  ifdebug(1) statement_consistent_p(modified_module_statement);
865  ifdebug(2) {
866  pips_debug(2,"in inline_calls for %s\n",module);
867  print_statement(modified_module_statement);
868  }
869 
870  DB_PUT_MEMORY_RESOURCE(DBR_CODE, module, modified_module_statement);
871  DB_PUT_MEMORY_RESOURCE(DBR_CALLEES, module, compute_callees(modified_module_statement));
874 }
bool statement_consistent_p(statement p)
Definition: ri.c:2195
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
static void inline_split_declarations(statement s, entity inlined_module)
split the declarations from s from their initialization if they contain a call to inlined_module
Definition: inlining.c:808
static void inline_statement_crawler(statement stmt, inlining_parameters p)
this is in charge of replacing instruction by new ones only apply if this instruction does not contai...
Definition: inlining.c:749
static char * module
Definition: pips.c:74
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define ifdebug(n)
Definition: sg.c:47

References compute_callees(), db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, entity_user_name(), gen_context_recurse, gen_true2(), ifdebug, inline_split_declarations(), inline_statement_crawler(), inlined_module, module, module_name_to_entity(), pips_assert, pips_debug, print_statement(), reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), statement_consistent_p(), statement_domain, and statement_undefined_p.

Referenced by do_inlining(), and run_inlining().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_expression()

static void inline_expression ( expression  expr,
inlining_parameters  p 
)
static

recursievly inline an expression if needed

Definition at line 705 of file inlining.c.

706 {
707  if( expression_call_p(expr) )
708  {
711  {
712  statement s = inline_expression_call(p, expr, callee );
713  if( !statement_undefined_p(s) )
714  {
715  insert_statement(new_statements(p),s,true);
716  }
718  ifdebug(2) {
719  pips_debug(2,"inserted inline statement\n");
721  }
722  }
723  }
724 }
static entity callee
Definition: alias_pairs.c:62
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
static bool inline_should_inline(entity inlined_module, call callee)
helper function to check if a call is a call to the inlined function
Definition: inlining.c:143
static statement inline_expression_call(inlining_parameters p, expression modified_expression, call callee)
this should inline the call callee calling module inlined_module
Definition: inlining.c:314
#define new_statements(p)
Definition: inlining.c:97
bool expression_call_p(expression e)
Definition: expression.c:415
#define syntax_call(x)
Definition: ri.h:2736
#define expression_syntax(x)
Definition: ri.h:1247

References callee, expression_call_p(), expression_syntax, ifdebug, inline_expression_call(), inline_should_inline(), inlined_module, insert_statement(), new_statements, pips_debug, print_statement(), statement_consistent_p(), statement_undefined_p, and syntax_call.

Referenced by inline_statement_crawler().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_expression_call()

static statement inline_expression_call ( inlining_parameters  p,
expression  modified_expression,
call  callee 
)
static

this should inline the call callee calling module inlined_module

only inline the right call

stop if the function has static declaration

create the new instruction sequence no need to change all entities in the new statements, because we build a new text resource later sg: not so true, because of dependant types

add external declarations for all extern referenced entities it is needed because inlined module and current module may not share the same compilation unit. Not relevant for Fortran

FI: However, it would be nice to check first if the entity is not already in the scope for the function or in the scope of its compilation unit (OK, the later is difficult because the order of declarations has to be taken into account).

special hook for struct member : consider their structure instead of the field

enum member cannot be added to declarations

formal parameters are not considered

g: unsafe sg: I am unsure this is still needed

ensure block status

avoid duplicated label due to copy_statement

add label at the end of the statement

fix ‘return’ calls in case a goto is immediately followed by its targeted label the goto is not needed (SG: seems difficult to do in the previous gen_recurse)

only replace return statement by gotos

replace by affectation + goto

create new variable to receive computation result

do the replacement

change the caller from an expression call to a call to a constant

... or to a reference

fix declarations

retrieve formal parameters

store association between new and old declarations

some basic checks

iterate over the parameters and perform substitution between formal and actual parameters

check if there is a write effect on this parameter

generate a copy for this parameter

fix value

add the entity to our list

substitute variables

get new reference

need a temporary variable

this one is more complicated than I thought, what of the side effect of the call ? we must create a new variable holding the call result before

need a temporary variable

check wether the substitution will cause naming clashes then perform the substitution

SG: C dependant types are a pain in the a**, we fix them here, that is perform substitution if needed

add declaration at the beginning of the statement

final cleanings

Definition at line 314 of file inlining.c.

315 {
316  /* only inline the right call */
317  pips_assert("inline the right call",inline_should_inline(inlined_module(p),callee));
318 
319  value inlined_value = entity_initial(inlined_module(p));
320  pips_assert("is a code", value_code_p(inlined_value));
321  code inlined_code = value_code(inlined_value);
322 
323  /* stop if the function has static declaration */
324  {
325  has_static_declaration(p)=false;
326  if( c_module_p(inlined_module(p)) )
328  else
330 
331  if( has_static_declaration(p))
332  {
333  pips_user_warning("cannot inline function with static declarations\n");
334  return statement_undefined;
335  }
336  }
337 
338  /* create the new instruction sequence
339  * no need to change all entities in the new statements, because we build a new text resource later
340  * sg: not so true, because of dependant types
341  */
343 
344  statement declaration_holder = make_empty_block_statement();
345 
346  /* add external declarations for all extern referenced entities it
347  * is needed because inlined module and current module may not
348  * share the same compilation unit.
349  * Not relevant for Fortran
350  *
351  * FI: However, it would be nice to check first if the entity is not
352  * already in the scope for the function or in the scope of its
353  * compilation unit (OK, the later is difficult because the order
354  * of declarations has to be taken into account).
355  */
357  {
359  set inlined_referenced_entities = get_referenced_entities(expanded);
360  list lire = set_to_sorted_list(inlined_referenced_entities,(gen_cmp_func_t)compare_entities);
361  set_free(inlined_referenced_entities);
362 
363 
364  FOREACH(ENTITY,ref_ent,lire)
365  {
366  if( entity_field_p(ref_ent) ) /* special hook for struct member : consider their structure instead of the field */
367  {
369  }
370 
371  if(!entity_enum_member_p(ref_ent) && /* enum member cannot be added to declarations */
372  !entity_formal_p(ref_ent) ) /* formal parameters are not considered */
373  {
374  const char* emn = entity_module_name(ref_ent);
377  {
380  }
381  else if(variable_static_p(ref_ent) &&
383  {
384  pips_user_warning("replacing static variable \"%s\" by a global one, this may lead to incorrect code\n", entity_user_name(ref_ent));
385  entity add = make_global_entity_from_local(ref_ent);
386  replace_entity(expanded,ref_ent,add);
390  }
391  else if(!variable_entity_p(ref_ent) && !same_string_p(emn,cu_name) &&
393  {
395  }
396  }
397  }
398  gen_free_list(lire);
400  }
401  else {
402  bool did_something = false;
404  {
405  if(!entity_area_p(e) && !implicit_c_variable_p(e))
406  {
407  entity new;
408  if(entity_variable_p(e)) {
409  if(entity_scalar_p(e)||entity_pointer_p(e)) {
411  }
412  else {
415  }
416  }
417  else
418  {
419  /*sg: unsafe
420  *sg: I am unsure this is still needed */
423  if(regenerate)
424  {
425  pips_user_warning("regenerating entity, should this happen ?\n");
429  }
430  }
433  replace_entity(expanded,e,new);
434  did_something=true;
435  }
436  }
437  if(did_something)
438  {
440  if(decls && !empty_string_p(decls)){
441  free(decls);
443  }
444  }
445  }
446 
447 
448  /* ensure block status */
449  if( ! statement_block_p( expanded ) )
450  {
453  }
454 
455 
456  /* avoid duplicated label due to copy_statement */
459 
460  /* add label at the end of the statement */
463 
464  /* fix `return' calls
465  * in case a goto is immediately followed by its targeted label
466  * the goto is not needed (SG: seems difficult to do in the previous gen_recurse)
467  */
468  {
470  {
471 
473  if( type_void_p(treturn) ) /* only replace return statement by gotos */
474  {
476  }
477  else /* replace by affectation + goto */
478  {
479  /* create new variable to receive computation result */
480  pips_assert("returned value is a variable", type_variable_p(treturn));
482  "_return",
485  );
487 
488  /* do the replacement */
489  if(!ENDP(tail) && !ENDP(CDR(tail))) {
492  }
493 
494  /* change the caller from an expression call to a call to a constant */
496  {
497  expression_syntax(modified_expression) = make_syntax_call(make_call(returned_entity(p),NIL));
498  }
499  /* ... or to a reference */
500  else
501  {
503  expression_syntax(modified_expression) = make_syntax_reference(r);
504  }
505  }
506  }
507  }
508 
509  /* fix declarations */
510  {
511  /* retrieve formal parameters*/
512  list formal_parameters = module_formal_parameters(inlined_module(p));
513  list new_old_pairs = NIL ; /* store association between new and old declarations */
514  { /* some basic checks */
515  size_t n1 = gen_length(formal_parameters), n2 = gen_length(call_arguments(callee));
516  pips_assert("function call has enough arguments",n1 >= n2);
517  }
518  /* iterate over the parameters and perform substitution between formal and actual parameters */
519  for(list iter = formal_parameters,c_iter = call_arguments(callee) ; !ENDP(c_iter); POP(iter),POP(c_iter) )
520  {
521  entity e = ENTITY(CAR(iter));
522  expression from = EXPRESSION(CAR(c_iter));
523 
524  /* check if there is a write effect on this parameter */
526 
527  /* generate a copy for this parameter */
528  entity new = entity_undefined;
529  if(need_copy)
530  {
531  if(entity_scalar_p(e)||entity_pointer_p(e)) {
533  }
534  else {
535  if(formal_parameter_p(e)) {
539  free_expression(etmp);
540  }
541  else
544  }
545 
546  /* fix value */
547  if(get_bool_property("INLINING_USE_INITIALIZATION_LIST"))
549  else
550  insert_statement(declaration_holder,make_assign_statement(entity_to_expression(new),copy_expression(from)),false);
551 
552 
553  /* add the entity to our list */
554  //statement_declarations(declaration_holder)=CONS(ENTITY,new,statement_declarations(declaration_holder));
557  replace_entity(expanded,e,new);
558  pips_debug(2,"replace %s by %s",entity_user_name(e),entity_user_name(new));
559  }
560  /* substitute variables */
561  else
562  {
563  /* get new reference */
564 
565  bool add_dereferencment = false;
566  reget:
567  switch(syntax_tag(expression_syntax(from)))
568  {
569  case is_syntax_reference:
570  {
572  size_t nb_indices = gen_length(reference_indices(r));
573  if( nb_indices == 0 )
574  {
575  new = reference_variable(r);
576  }
577  else /* need a temporary variable */
578  {
580  {
582  new = make_temporary_scalar_entity(from,&st);
583  if(!statement_undefined_p(st))
584  insert_statement(declaration_holder,st,false);
585  }
586  else
587  {
589  add_dereferencment=true;
590  }
592 
593  }
594  } break;
595  /* this one is more complicated than I thought,
596  * what of the side effect of the call ?
597  * we must create a new variable holding the call result before
598  */
599  case is_syntax_call:
600  {
602  size_t nb_param = gen_length(call_arguments(c));
603  if( nb_param == 0 && expression_constant_p(from))
604  new = call_function(c);
605  else
606  {
608  {
610  new = make_temporary_scalar_entity(from,&st);
611  if(!statement_undefined_p(st))
612  insert_statement(declaration_holder,st,false);
613  }
614  else
615  {
617  new = make_temporary_scalar_entity(from,&st);
618  if(!statement_undefined_p(st))
619  insert_statement(declaration_holder,st,false);
620  }
622  }
623  } break;
624  case is_syntax_subscript:
625  /* need a temporary variable */
626  {
628  {
630  new = make_temporary_scalar_entity(from,&st);
631  if(!statement_undefined_p(st))
632  insert_statement(declaration_holder,st,false);
633  }
634  else
635  {
637  add_dereferencment=true;
638  }
640 
641  } break;
644  new = make_temporary_scalar_entity(from,&st);
645  if(!statement_undefined_p(st))
646  insert_statement(declaration_holder,st,false);
648  } break;
649 
650  case is_syntax_cast:
651  pips_user_warning("ignoring cast\n");
653  goto reget;
654 
655  default:
656  pips_internal_error("unhandled tag %d", syntax_tag(expression_syntax(from)) );
657  };
658 
659  /* check wether the substitution will cause naming clashes
660  * then perform the substitution
661  */
664  else replace_entity(expanded ,e,new);
665  pips_debug(3,"replace %s by %s\n",entity_user_name(e),entity_user_name(new));
666 
667 
668  }
669  new_old_pairs=CONS(ENTITY,new,CONS(ENTITY,e,new_old_pairs));
670 
671  }
672  gen_free_list(formal_parameters);
673  /* SG: C dependant types are a pain in the a**,
674  we fix them here, that is perform substitution if needed
675  */
676  for(list iter = new_old_pairs;!ENDP(iter);POP(iter)) {
677  entity new = ENTITY(CAR(iter));
678  POP(iter);
679  entity old = ENTITY(CAR(iter));
680  replace_entity(declaration_holder,old,new);
681  }
682  gen_free_list(new_old_pairs);
683  }
684 
685 
686  /* add declaration at the beginning of the statement */
687  insert_statement(declaration_holder,expanded,false);
688 
689  /* final cleanings
690  */
693  ifdebug(1) statement_consistent_p(declaration_holder);
694  ifdebug(2) {
695  pips_debug(2,"inlined statement after substitution\n");
696  print_statement(declaration_holder);
697  }
698  return declaration_holder;
699 }
call make_call(entity a1, list a2)
Definition: ri.c:269
value make_value_expression(expression _field_)
Definition: ri.c:2850
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
type copy_type(type p)
TYPE.
Definition: ri.c:2655
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
statement copy_statement(statement p)
STATEMENT.
Definition: ri.c:2186
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
instruction make_instruction_sequence(sequence _field_)
Definition: ri.c:1169
value copy_value(value p)
VALUE.
Definition: ri.c:2784
void free_expression(expression p)
Definition: ri.c:853
storage copy_storage(storage p)
STORAGE.
Definition: ri.c:2228
sequence make_sequence(list a)
Definition: ri.c:2125
syntax make_syntax_reference(reference _field_)
Definition: ri.c:2494
string compilation_unit_of_module(const char *)
The output is undefined if the module is referenced but not defined in the workspace,...
Definition: module.c:350
bool find_write_effect_on_entity(statement, entity)
bool empty_string_p(const char *s)
Definition: entity_names.c:239
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
statement make_empty_block_statement(void)
Build an empty statement (block/sequence)
Definition: statement.c:625
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
void replace_entity(void *s, entity old, entity new)
per variable version of replace_entities.
Definition: replace.c:113
void replace_entity_by_expression(void *s, entity ent, expression exp)
replace all reference to entity ent by expression exp in s.
Definition: replace.c:220
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
size_t gen_length(const list l)
Definition: list.c:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
list gen_append(list l1, const list l2)
Definition: list.c:471
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
statement make_assign_statement(expression, expression)
Definition: statement.c:583
statement make_continue_statement(entity)
Definition: statement.c:953
void fix_statement_attributes_if_sequence(statement)
Apply fix_sequence_statement_attributes() on the statement only if it really a sequence.
Definition: statement.c:2078
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
static void inline_return_crawler(statement s, inlining_parameters p)
replace return instruction by an assignment and a goto
Definition: inlining.c:118
static entity make_temporary_scalar_entity(expression from, statement *assign)
create a scalar similar to ‘efrom’ initialized with expression ‘from’
Definition: inlining.c:216
static void solve_name_clashes(statement s, entity new)
look for entity locally named has ‘new’ in statements ‘s’ when found, find a new name and perform sub...
Definition: inlining.c:163
#define returned_entity(p)
Definition: inlining.c:102
static void statement_with_static_declarations_p(statement s, inlining_parameters p)
return true if an entity declared in the statement ‘s’ from ‘p->inlined_module’
Definition: inlining.c:208
static statement expanded
Definition: inlining.c:157
bool has_entity_with_same_name(entity e, list l)
inlining.c
Definition: inlining.c:256
#define laststmt(p)
Definition: inlining.c:100
static void inlining_regenerate_labels(statement s, entity new_module)
regenerate the label of each statement with a label.
Definition: inlining.c:236
static void inline_return_remover(statement s, inlining_parameters p)
replace return instruction by a goto
Definition: inlining.c:109
static bool inline_has_static_declaration(list iter)
return true if an entity declared in ‘iter’ is static to ‘module’
Definition: inlining.c:194
#define tail_ins(p)
Definition: inlining.c:101
#define has_static_declaration(p)
Definition: inlining.c:98
static void slightly_rename_entities(statement s)
sg: this is another inlining mostruosity it ensures all entities in s have new pointer and different ...
Definition: inlining.c:298
#define pips_internal_error
Definition: misc-local.h:149
void unnormalize_expression(void *st)
void unnormalize_expression(expression exp): puts all the normalized field of expressions in "st" to ...
Definition: normalize.c:452
#define DEREFERENCING_OPERATOR_NAME
Definition: ri-util-local.h:93
#define entity_declarations(e)
MISC: newgen shorthands.
#define ADDRESS_OF_OPERATOR_NAME
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
#define entity_constant_p(e)
bool entity_area_p(entity e)
Definition: area.c:149
bool entity_enum_member_p(entity e)
Definition: entity.c:980
entity FindEntity(const char *package, const char *name)
Retrieve an entity from its package/module name and its local name.
Definition: entity.c:1503
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
int compare_entities(const entity *pe1, const entity *pe2)
Comparison function for qsort.
Definition: entity.c:1328
bool entity_formal_p(entity p)
is p a formal parameter?
Definition: entity.c:1935
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
code entity_code(entity e)
Definition: entity.c:1098
bool extern_entity_p(entity module, entity e)
Definition: entity.c:1977
basic entity_basic(entity e)
return the basic associated to entity e if it's a function/variable/constant basic_undefined otherwis...
Definition: entity.c:1380
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
entity make_new_label(entity module)
This function returns a new label.
Definition: entity.c:357
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
bool entity_pointer_p(entity e)
Definition: entity.c:745
entity entity_field_to_entity_struct_or_union(entity f)
Definition: entity.c:925
set get_referenced_entities(void *elem)
retrieves the set of entities used in elem beware that this entities may be formal parameters,...
Definition: entity.c:3063
entity entity_intrinsic(const char *name)
FI: I do not understand this function name (see next one!).
Definition: entity.c:1292
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
list module_formal_parameters(entity func)
list module_formal_parameters(entity func) input : an entity representing a function.
Definition: module.c:327
void AddLocalEntityToDeclarations(entity, entity, statement)
Add the variable entity e to the list of variables of the function module.
Definition: variable.c:233
bool entity_scalar_p(entity)
The concrete type of e is a scalar type.
Definition: variable.c:1113
entity make_new_array_variable_with_prefix(const char *, entity, basic, list)
J'ai ameliore la fonction make_new_scalar_variable_with_prefix
Definition: variable.c:785
bool variable_entity_p(entity)
variable.c
Definition: variable.c:70
entity make_temporary_pointer_to_array_entity(entity, expression, entity)
Definition: variable.c:819
void AddEntityToDeclarations(entity, entity)
END_EOLE.
Definition: variable.c:108
void AddEntityToCurrentModule(entity)
Add a variable entity to the current module declarations.
Definition: variable.c:260
entity make_new_scalar_variable_with_prefix(const char *, entity, basic)
Create a new scalar variable of type b in the given module.
Definition: variable.c:592
bool implicit_c_variable_p(entity)
Definition: variable.c:1877
entity make_global_entity_from_local(entity)
Definition: variable.c:281
bool variable_static_p(entity)
true if v appears in a SAVE statement, or in a DATA statement, or is declared static i C.
Definition: variable.c:1579
#define value_code_p(x)
Definition: ri.h:3065
#define functional_result(x)
Definition: ri.h:1444
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define code_externs(x)
Definition: ri.h:790
#define syntax_cast(x)
Definition: ri.h:2739
#define type_functional(x)
Definition: ri.h:2952
#define type_variable(x)
Definition: ri.h:2949
#define entity_storage(x)
Definition: ri.h:2794
#define code_declarations(x)
Definition: ri.h:784
@ is_syntax_cast
Definition: ri.h:2694
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_reference
Definition: ri.h:2691
@ is_syntax_sizeofexpression
Definition: ri.h:2695
@ is_syntax_subscript
Definition: ri.h:2696
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define cast_expression(x)
Definition: ri.h:747
#define entity_undefined_p(x)
Definition: ri.h:2762
#define expression_undefined
Definition: ri.h:1223
#define type_void_p(x)
Definition: ri.h:2959
#define sequence_statements(x)
Definition: ri.h:2360
#define reference_indices(x)
Definition: ri.h:2328
#define value_code(x)
Definition: ri.h:3067
#define instruction_sequence(x)
Definition: ri.h:1514
#define variable_dimensions(x)
Definition: ri.h:3122
#define code_decls_text(x)
Definition: ri.h:786
#define statement_instruction(x)
Definition: ri.h:2458
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define type_variable_p(x)
Definition: ri.h:2947
#define variable_basic(x)
Definition: ri.h:3120
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
void AddEntityToModuleCompilationUnit(entity e, entity module)
Definition: module.c:301

References AddEntityToCurrentModule(), AddEntityToDeclarations(), AddEntityToModuleCompilationUnit(), AddLocalEntityToDeclarations(), ADDRESS_OF_OPERATOR_NAME, c_module_p(), call_arguments, call_function, callee, CAR, cast_expression, CDR, code_declarations, code_decls_text, code_externs, compare_entities(), compilation_unit_of_module(), CONS, copy_basic(), copy_expression(), copy_statement(), copy_storage(), copy_type(), copy_value(), DEREFERENCING_OPERATOR_NAME, empty_string_p(), ENDP, ENTITY, entity_area_p(), entity_basic(), entity_code(), entity_constant_p, entity_declarations, entity_enum_member_p(), entity_field_p(), entity_field_to_entity_struct_or_union(), entity_formal_p(), entity_initial, entity_intrinsic(), entity_local_name(), entity_module_name(), entity_pointer_p(), entity_scalar_p(), entity_storage, entity_to_expression(), entity_type, entity_undefined, entity_undefined_p, entity_user_name(), entity_variable_p, expanded, EXPRESSION, expression_constant_p(), expression_syntax, expression_undefined, extern_entity_p(), find_write_effect_on_entity(), FindEntity(), FindOrCreateEntity(), fix_statement_attributes_if_sequence(), FOREACH, formal_parameter_p(), free(), free_expression(), functional_result, gen_append(), gen_context_recurse, gen_free_list(), gen_full_copy_list(), gen_last(), gen_length(), gen_recurse, gen_true(), gen_true2(), get_bool_property(), get_current_module_entity(), get_current_module_name(), get_referenced_entities(), has_entity_with_same_name(), has_static_declaration, ifdebug, implicit_c_variable_p(), inline_has_static_declaration(), inline_return_crawler(), inline_return_remover(), inline_should_inline(), inlined_module, inlined_module_statement, inlining_regenerate_labels(), insert_statement(), instruction_sequence, instruction_to_statement(), is_syntax_call, is_syntax_cast, is_syntax_reference, is_syntax_sizeofexpression, is_syntax_subscript, laststmt, make_assign_statement(), make_call(), make_continue_statement(), make_empty_block_statement(), make_global_entity_from_local(), make_instruction_sequence(), make_new_array_variable_with_prefix(), make_new_label(), make_new_scalar_variable_with_prefix(), make_reference(), make_sequence(), make_syntax_call(), make_syntax_reference(), make_temporary_pointer_to_array_entity(), make_temporary_scalar_entity(), make_value_expression(), MakeUnaryCall(), module_formal_parameters(), module_name_to_entity(), NIL, pips_assert, pips_debug, pips_internal_error, pips_user_warning, POP, print_statement(), reference_indices, reference_variable, replace_entity(), replace_entity_by_expression(), returned_entity, same_string_p, sequence_statements, set_free(), set_to_sorted_list(), slightly_rename_entities(), solve_name_clashes(), STATEMENT, statement_block_p, statement_consistent_p(), statement_domain, statement_instruction, statement_undefined, statement_undefined_p, statement_with_static_declarations_p(), strdup(), syntax_call, syntax_cast, syntax_reference, syntax_tag, tail_ins, type_functional, type_variable, type_variable_p, type_void_p, unnormalize_expression(), use_effects, value_code, value_code_p, variable_basic, variable_dimensions, variable_entity_p(), and variable_static_p().

Referenced by inline_expression().

+ Here is the caller graph for this function:

◆ inline_has_inlinable_calls()

static bool inline_has_inlinable_calls ( entity  inlined_module,
void *  elem 
)
static

Definition at line 736 of file inlining.c.

737 {
738  iparam p = { ._inlined_module_=inlined_module,._has_inlinable_calls_=false};
739  gen_context_recurse(elem, &p,
741  return has_inlinable_calls(&p);
742 }
#define has_inlinable_calls(p)
Definition: inlining.c:99
static void inline_has_inlinable_calls_crawler(call callee, inlining_parameters p)
check if a call has inlinable calls
Definition: inlining.c:729
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
structure containing all the parameters needed by inlining.
Definition: inlining.c:73
entity _inlined_module_
Definition: inlining.c:74

References iparam::_inlined_module_, call_domain, gen_context_recurse, gen_true2(), has_inlinable_calls, inline_has_inlinable_calls_crawler(), and inlined_module.

Referenced by inline_split_declarations(), and inline_statement_crawler().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_has_inlinable_calls_crawler()

static void inline_has_inlinable_calls_crawler ( call  callee,
inlining_parameters  p 
)
static

check if a call has inlinable calls

Definition at line 729 of file inlining.c.

730 {
732  gen_recurse_stop(0);
733 }
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251

References callee, gen_recurse_stop(), has_inlinable_calls, inline_should_inline(), and inlined_module.

Referenced by inline_has_inlinable_calls().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_has_static_declaration()

static bool inline_has_static_declaration ( list  iter)
static

return true if an entity declared in ‘iter’ is static to ‘module’

Definition at line 194 of file inlining.c.

195 {
196  FOREACH(ENTITY, e ,iter)
197  {
198  if ( variable_static_p(e))
199  return true;
200  }
201  return false;
202 }

References ENTITY, FOREACH, and variable_static_p().

Referenced by inline_expression_call(), and statement_with_static_declarations_p().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_return_crawler()

static void inline_return_crawler ( statement  s,
inlining_parameters  p 
)
static

replace return instruction by an assignment and a goto

Definition at line 118 of file inlining.c.

119 {
120  if( return_statement_p( s ) )
121  {
122  // create the goto
123  list l= (statement_instruction(s) == tail_ins(p)) ?
124  NIL :
126  // create the assign and push it if needed
127  call ic = statement_call(s);
128  if( !ENDP(call_arguments(ic)) )
129  {
130  pips_assert("return is called with one argument",ENDP(CDR(call_arguments(ic))));
134  l = CONS( STATEMENT, assign , l );
135  }
137  }
138 }
instruction make_instruction_goto(statement _field_)
Definition: ri.c:1181
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
statement update_statement_instruction(statement, instruction)
Replace the instruction in statement s by instruction i.
Definition: statement.c:3039
bool return_statement_p(statement)
Test if a statement is a C or Fortran "return".
Definition: statement.c:172
#define make_statement_list(stats...)
easy list constructor

References call_arguments, CAR, CDR, CONS, copy_expression(), copy_statement(), ENDP, entity_to_expression(), EXPRESSION, instruction_to_statement(), laststmt, make_assign_statement(), make_instruction_goto(), make_instruction_sequence(), make_sequence(), make_statement_list, NIL, pips_assert, return_statement_p(), returned_entity, STATEMENT, statement_call(), statement_instruction, tail_ins, and update_statement_instruction().

Referenced by inline_expression_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_return_remover()

static void inline_return_remover ( statement  s,
inlining_parameters  p 
)
static

replace return instruction by a goto

Definition at line 109 of file inlining.c.

References copy_statement(), laststmt, make_instruction_goto(), return_statement_p(), and update_statement_instruction().

Referenced by inline_expression_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_should_inline()

static bool inline_should_inline ( entity  inlined_module,
call  callee 
)
static

helper function to check if a call is a call to the inlined function

Definition at line 143 of file inlining.c.

144 {
146 }
bool same_entity_lname_p(entity, entity)
Definition: same_names.c:64

References call_function, callee, inlined_module, and same_entity_lname_p().

Referenced by inline_expression(), inline_expression_call(), and inline_has_inlinable_calls_crawler().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_split_declarations()

static void inline_split_declarations ( statement  s,
entity  inlined_module 
)
static

split the declarations from s from their initialization if they contain a call to inlined_module

the first condition is a bit tricky : check int a = foo(); int b=bar(); once we decide to inline foo(), we must split b=bar() because foo may touch a global variable used in bar()

Definition at line 808 of file inlining.c.

809 {
810 
811  if(statement_block_p(s))
812  {
813  list prelude = NIL;
814  set selected_entities = set_make(set_pointer);
816  {
817  value v = entity_initial(e);
819  {
820  /* the first condition is a bit tricky :
821  * check int a = foo(); int b=bar();
822  * once we decide to inline foo(), we must split b=bar()
823  * because foo may touch a global variable used in bar()
824  */
825  if( !ENDP(prelude) ||
827  {
828  set_add_element(selected_entities,selected_entities,e);
832  }
833  }
834  }
835  set_free(selected_entities);
836  FOREACH(STATEMENT,st,prelude)
837  insert_statement(s,st,true);
838  gen_free_list(prelude);
839  }
841  pips_user_warning("only blocks and declaration statements should have declarations\n");
842 }
value make_value_unknown(void)
Definition: ri.c:2847
void free_value(value p)
Definition: ri.c:2787
static bool inline_has_inlinable_calls(entity inlined_module, void *elem)
Definition: inlining.c:736
@ set_pointer
Definition: newgen_set.h:44
#define value_undefined_p(x)
Definition: ri.h:3017
#define value_expression_p(x)
Definition: ri.h:3080
#define value_expression(x)
Definition: ri.h:3082

References CONS, copy_expression(), declaration_statement_p(), ENDP, ENTITY, entity_initial, entity_to_expression(), FOREACH, free_value(), gen_free_list(), inline_has_inlinable_calls(), inlined_module, insert_statement(), make_assign_statement(), make_value_unknown(), NIL, pips_user_warning, set_add_element(), set_free(), set_make(), set_pointer, STATEMENT, statement_block_p, statement_declarations, value_expression, value_expression_p, and value_undefined_p.

Referenced by inline_calls().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inline_statement_crawler()

static void inline_statement_crawler ( statement  stmt,
inlining_parameters  p 
)
static

this is in charge of replacing instruction by new ones only apply if this instruction does not contain other instructions

the gen_recurse can only handle expressions, so we turn this call into an expression

something happens on the way to heaven

Definition at line 749 of file inlining.c.

750 {
754  {
755  /* the gen_recurse can only handle expressions, so we turn this call into an expression */
758  }
759 
762 
763  if( !ENDP(statement_block(new_statements(p))) ) /* something happens on the way to heaven */
764  {
765  if(get_bool_property("INLINING_COMMENT_ORIGIN")) {
766  char *the_comment;
767  asprintf(&the_comment,"inlined by pips from ``%s''\n", entity_user_name(inlined_module(p)));
769  free(the_comment);
770  }
771 
773  if( ! type_void_p(t) )
774  {
775  //pips_assert("inlining instruction modification is ok", instruction_consistent_p(sti));
777  }
779  {
780  list iter=statement_block(stmt);
781  for(stmt=STATEMENT(CAR(iter));continue_statement_p(stmt);POP(iter))
782  stmt=STATEMENT(CAR(iter));
783  }
784 
785  if(cprev!=NULL){
788  make_test(
790  new_statements(p),
792  )
793  );
794  }
796  ifdebug(2) {
797  pips_debug(2,"updated statement instruction\n");
799  }
800  //pips_assert("inlining statement generation is ok",statement_consistent_p(stmt));
801  }
803 }
instruction copy_instruction(instruction p)
INSTRUCTION.
Definition: ri.c:1115
instruction make_instruction_expression(expression _field_)
Definition: ri.c:1196
test make_test(expression a1, statement a2, statement a3)
Definition: ri.c:2607
instruction make_instruction_test(test _field_)
Definition: ri.c:1172
call copy_call(call p)
CALL.
Definition: ri.c:233
statement make_block_statement(list)
Make a block statement from a list of statement.
Definition: statement.c:616
gen_chunk * gen_get_ancestor(int, const void *)
return the first ancestor object found of the given type.
Definition: genClib.c:3560
list statement_block(statement)
Get the list of block statements of a statement sequence.
Definition: statement.c:1338
void insert_comments_to_statement(statement, const char *)
Insert a comment string (if non empty) at the beginning of the comments of a statement.
Definition: statement.c:1916
bool continue_statement_p(statement)
Test if a statement is a CONTINUE, that is the FORTRAN nop, the ";" in C or the "pass" in Python....
Definition: statement.c:203
static void inline_expression(expression expr, inlining_parameters p)
recursievly inline an expression if needed
Definition: inlining.c:705
struct _newgen_struct_control_ * control
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define control_domain
newgen_controlmap_domain_defined
Definition: ri.h:98
#define instruction_call_p(x)
Definition: ri.h:1527
#define instruction_call(x)
Definition: ri.h:1529
Definition: statement.c:54

References asprintf, call_to_expression(), CAR, continue_statement_p(), control_domain, copy_call(), copy_instruction(), ENDP, entity_type, entity_user_name(), expression_domain, free(), functional_result, gen_context_recurse, gen_get_ancestor(), gen_true2(), get_bool_property(), ifdebug, inline_expression(), inline_has_inlinable_calls(), inlined_module, insert_comments_to_statement(), insert_statement(), instruction_call, instruction_call_p, instruction_to_statement(), int_to_expression(), make_block_statement(), make_instruction_expression(), make_instruction_test(), make_test(), new_statements, NIL, pips_debug, POP, print_statement(), STATEMENT, statement_block(), statement_block_p, statement_consistent_p(), statement_instruction, type_functional, type_void_p, and update_statement_instruction().

Referenced by inline_calls().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inlining()

bool inlining ( const char *  module_name)

perform inlining using effects

Parameters
module_namename of the module to inline
Returns
Parameters
module_nameodule_name

Definition at line 957 of file inlining.c.

958 {
959  iparam p =IPARAM_INIT;
960  use_effects(&p)=true;
961  return do_inlining(&p,module_name);
962 }
#define IPARAM_INIT
Definition: inlining.c:84
static bool do_inlining(inlining_parameters p, const char *module_name)
this should inline all calls to module ‘module_name’ in calling modules, if possible ....
Definition: inlining.c:885

References do_inlining(), IPARAM_INIT, module_name(), and use_effects.

+ Here is the call graph for this function:

◆ inlining_regenerate_labels()

static void inlining_regenerate_labels ( statement  s,
entity  new_module 
)
static

regenerate the label of each statement with a label.

it avoid duplications due to copy_statement

Definition at line 236 of file inlining.c.

237 {
238  entity lbl = statement_label(s);
239  if(!entity_empty_label_p(lbl))
240  {
242  {
243  statement_label(s)=lbl=make_new_label(new_module);
244  }
245  else
247  if( statement_loop_p(s) )
248  loop_label(statement_loop(s))=lbl;
249  }
250  else if( statement_loop_p(s) ) {
252  loop_label(statement_loop(s))=make_new_label(new_module);
253  }
254 }
loop statement_loop(statement)
Get the loop of a statement.
Definition: statement.c:1374
bool statement_loop_p(statement)
Definition: statement.c:349
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
bool entity_empty_label_p(entity e)
Definition: entity.c:666
const char * label_local_name(entity e)
END_EOLE.
Definition: entity.c:604
entity find_label_entity(const char *, const char *)
util.c
Definition: util.c:43
#define statement_label(x)
Definition: ri.h:2450
#define loop_label(x)
Definition: ri.h:1646

References entity_empty_label_p(), entity_local_name(), entity_undefined_p, find_label_entity(), FindOrCreateEntity(), label_local_name(), loop_label, make_new_label(), module_local_name(), statement_label, statement_loop(), and statement_loop_p().

Referenced by inline_expression_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ inlining_simple()

bool inlining_simple ( const char *  module_name)

perform inlining without using effects

Parameters
module_namename of the module to inline
Returns
Parameters
module_nameodule_name

Definition at line 971 of file inlining.c.

972 {
973  iparam p =IPARAM_INIT;
974  use_effects(&p)=false;
975  return do_inlining(&p,module_name);
976 }

References do_inlining(), IPARAM_INIT, module_name(), and use_effects.

+ Here is the call graph for this function:

◆ make_temporary_scalar_entity()

static entity make_temporary_scalar_entity ( expression  from,
statement assign 
)
static

create a scalar similar to ‘efrom’ initialized with expression ‘from’

create the scalar

set intial

Definition at line 216 of file inlining.c.

217 {
218  pips_assert("expression is valid",expression_consistent_p(from)&&!expression_undefined_p(from));
219  /* create the scalar */
222  some_basic_of_any_expression(from,false,false)
223  );
224  /* set intial */
225  if(!expression_undefined_p(from))
226  {
228  }
229  return new;
230 }
bool expression_consistent_p(expression p)
Definition: ri.c:859
entity make_new_scalar_variable(entity, basic)
Definition: variable.c:741
basic some_basic_of_any_expression(expression, bool, bool)
basic basic_of_any_expression(expression exp, bool apply_p): Makes a basic of the same basic as the e...
Definition: type.c:1258
#define expression_undefined_p(x)
Definition: ri.h:1224

References copy_expression(), entity_to_expression(), expression_consistent_p(), expression_undefined_p, get_current_module_entity(), make_assign_statement(), make_new_scalar_variable(), pips_assert, and some_basic_of_any_expression().

Referenced by inline_expression_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ run_inlining()

static bool run_inlining ( string  caller_name,
const char *  module_name,
inlining_parameters  p 
)
static

get ressources for the call to inline and call apropriate inlining function

Parameters
caller_namecalling module name
module_namecalled module name

Get the module ressource

check them

inline call

Definition at line 992 of file inlining.c.

993 {
994  /* Get the module ressource */
997  (statement) db_get_memory_resource(DBR_CODE, module_name, true);
998 
1001  {
1002  pips_user_warning("not inlining empty function %s, "
1003  "this should be a generated skeleton ...\n",
1004  module_name);
1005  return false;
1006  }
1007  else {
1009 
1010  /* check them */
1012  pips_assert("statements found", !statement_undefined_p(inlined_module_statement(p)) );
1013 
1014  /* inline call */
1015  inline_calls( p, caller_name );
1017  return true;
1018  }
1019 }

References caller_name, db_get_memory_resource(), ENDP, entity_function_p(), entity_subroutine_p(), inline_calls(), inlined_module, inlined_module_statement, module_name(), module_name_to_entity(), pips_assert, pips_user_warning, reset_cumulated_rw_effects(), set_cumulated_rw_effects(), statement_block(), statement_block_p, statement_undefined_p, and use_effects.

Referenced by do_unfolding().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ slightly_rename_entities()

static void slightly_rename_entities ( statement  s)
static

sg: this is another inlining mostruosity it ensures all entities in s have new pointer and different name (is it usefull ?) it takes care of dependant types

Definition at line 298 of file inlining.c.

298  {
301  HASH_FOREACH(entity,old,entity,new,old_new)
302  replace_entities(new,old_new);
303  replace_entities(s,old_new);
304 
305  hash_table_free(old_new);
306 }
void replace_entities(void *s, hash_table ht)
Recursively substitute a set of entities in a statement.
Definition: replace.c:91
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
static void do_slightly_rename_entities(statement s, hash_table old_new)
Definition: inlining.c:262
@ hash_pointer
Definition: newgen_hash.h:32
#define HASH_FOREACH(key_type, k, value_type, v, ht)
Definition: newgen_hash.h:71
#define HASH_DEFAULT_SIZE
Definition: newgen_hash.h:26

References do_slightly_rename_entities(), gen_context_recurse, gen_true2(), HASH_DEFAULT_SIZE, HASH_FOREACH, hash_pointer, hash_table_free(), hash_table_make(), replace_entities(), and statement_domain.

Referenced by inline_expression_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ solve_name_clashes()

static void solve_name_clashes ( statement  s,
entity  new 
)
static

look for entity locally named has ‘new’ in statements ‘s’ when found, find a new name and perform substitution

Definition at line 163 of file inlining.c.

164 {
165  if(!implicit_c_variable_p(new)) {
168  for(;!ENDP(l);POP(l))
169  {
170  entity decl_ent = ENTITY(CAR(l));
171  if( same_string_p(entity_user_name(decl_ent), entity_user_name(new)))
172  {
173  entity solve_clash = copy_entity(decl_ent);
174  string ename = strdup(entity_name(solve_clash));
175  do {
176  string tmp;
177  asprintf(&tmp,"%s_",ename);
178  free(ename);
179  ename=tmp;
180  entity_name(solve_clash)=ename;
181  } while( has_similar_entity(solve_clash,re));
182  CAR(l).p = (void*)solve_clash;
183  replace_entity(expanded,decl_ent,solve_clash);
184  gen_recurse_stop(0);
185  }
186  }
187  set_free(re);
188  }
189 }
static bool has_similar_entity(entity e, set se)
Definition: inlining.c:148

References asprintf, CAR, copy_entity(), ENDP, ENTITY, entity_name, entity_user_name(), expanded, free(), gen_recurse_stop(), get_referenced_entities(), has_similar_entity(), implicit_c_variable_p(), POP, replace_entity(), same_string_p, set_free(), statement_declarations, and strdup().

Referenced by inline_expression_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ statement_with_static_declarations_p()

static void statement_with_static_declarations_p ( statement  s,
inlining_parameters  p 
)
static

return true if an entity declared in the statement ‘s’ from ‘p->inlined_module’

Definition at line 208 of file inlining.c.

References has_static_declaration, inline_has_static_declaration(), and statement_declarations.

Referenced by inline_expression_call().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ unfolding()

bool unfolding ( char *  module_name)

perform unfolding using effect

Parameters
module_namename of the module to unfold
Returns
Parameters
module_nameodule_name

Definition at line 1118 of file inlining.c.

1119 {
1120  iparam p = IPARAM_INIT;
1121  use_effects(&p)=true;
1122  return do_unfolding(&p,module_name);
1123 }
static bool do_unfolding(inlining_parameters p, char *module_name)
this should inline all call in module ‘module_name’ it does not works recursievly,...
Definition: inlining.c:1032

References do_unfolding(), IPARAM_INIT, module_name(), and use_effects.

+ Here is the call graph for this function:

◆ unfolding_simple()

bool unfolding_simple ( char *  module_name)

perform unfolding without using effects

Parameters
module_namename of the module to unfold
Returns
true upon success
Parameters
module_nameodule_name

Definition at line 1133 of file inlining.c.

1134 {
1135  iparam p = IPARAM_INIT;
1136  use_effects(&p)=false;
1137  return do_unfolding(&p,module_name);
1138 }

References do_unfolding(), IPARAM_INIT, module_name(), and use_effects.

+ Here is the call graph for this function:

Variable Documentation

◆ expanded