PIPS
hwac.h File Reference
+ Include dependency graph for hwac.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool freia_spoc_compiler (const string)
 Warning! Do not modify this file that is automatically generated! More...
 
bool freia_terapix_compiler (const string)
 
bool freia_aipo_compiler (const string)
 
bool freia_opencl_compiler (const string)
 
bool freia_sigmac_compiler (const string)
 
bool freia_mppa_compiler (const string)
 
bool freia_some_effects_on_images (statement)
 freia.c More...
 
expression freia_transpose_kernel (const expression)
 Transpose a structuring element expression. More...
 
bool freia_is_transpose_call (statement)
 Detect a call to a se transposition function and transpose the arguments. More...
 
string freia_compile (string, statement, string)
 freia_compile: compile freia module & statement for target More...
 
list freia_spoc_compile_calls (string, dag, sequence, list, const hash_table, hash_table, const set, FILE *, set, int)
 freia_spoc.c More...
 
list freia_trpx_compile_calls (string, dag, sequence, list, const hash_table, hash_table, const set, FILE *, set, int)
 freia_terapix.c More...
 
list freia_opencl_compile_calls (string, dag, sequence, list, const hash_table, hash_table, const set, FILE *, set, int, hash_table)
 freia_opencl.c More...
 
list freia_aipo_compile_calls (string, dag, list, const hash_table, hash_table, int)
 freia_aipo.c More...
 
list freia_sigmac_compile_calls (string, dag, sequence, list, const hash_table, hash_table, const set, FILE *, set, int, int)
 freia_sigmac.c More...
 
list freia_mppa_compile_calls (string, dag, sequence, list, const hash_table, hash_table, const set, FILE *, set, int)
 freia_mppa.c More...
 
string dagvtx_to_string (const dagvtx)
 dag-utils.c More...
 
statement dagvtx_statement (const dagvtx)
 return statement if any, or NULL (for input nodes). More...
 
void dag_statements (set, const dag)
 build the set of actual statements in d More...
 
bool dagvtx_other_stuff_p (const dagvtx)
 a vertex with a non AIPO or image related statement. More...
 
entity dagvtx_image (const dagvtx)
 return the produced image or NULL More...
 
_int dagvtx_number (const dagvtx)
 returns the vertex number, i.e. More...
 
string dagvtx_number_str (const dagvtx)
 
_int dagvtx_optype (const dagvtx)
 
_int dagvtx_opid (const dagvtx)
 
string dagvtx_function_name (const dagvtx)
 
string dagvtx_operation (const dagvtx)
 
string dagvtx_compact_operation (const dagvtx)
 
int dagvtx_ordering (const dagvtx *, const dagvtx *)
 
dagvtx dagvtx_get_producer (const dag, const dagvtx, const entity, _int)
 return (last) producer of image e for vertex sink, or NULL if none found. More...
 
void dagvtx_nb_dump (FILE *, const string, const list)
 
void dagvtx_dump (FILE *, const string, const dagvtx)
 for dag debug. More...
 
void dag_dump (FILE *, const string, const dag)
 for dag debug More...
 
void dag_dot (FILE *, const string, const dag, const list, const list)
 output dag in dot format, for debug or show More...
 
void dag_dot_dump (const string, const string, const dag, const list, const list)
 generate a "dot" format from a dag to a file. More...
 
void dag_dot_dump_prefix (const string, const string, int, const dag, const list, const list)
 
void dag_consistency_asserts (dag)
 do some consistency checking... More...
 
void dag_remove_vertex (dag, const dagvtx)
 remove vertex v from dag d. More...
 
dagvtx copy_dagvtx_norec (dagvtx)
 copy a vertex, but without its successors. More...
 
bool dagvtx_is_measurement_p (const dagvtx)
 returns whether the vertex is an image measurement operation. More...
 
void dag_append_vertex (dag, dagvtx)
 append new vertex nv to dag d. More...
 
int dag_computation_count (const dag)
 return the number of actual operations in dag d. More...
 
list dag_vertex_preds (const dag, const dagvtx)
 return target predecessor vertices as a list. More...
 
void freia_dag_optimize (dag, hash_table, list *, list *)
 remove dead image operations. More...
 
void dag_compute_outputs (dag, const hash_table, const set, const list, bool)
 (re)compute the list of GLOBAL input & output images for this dag ??? BUG the output is rather an approximation should rely on used defs or out effects for the underlying sequence. More...
 
void freia_hack_fix_global_ins_outs (dag, dag)
 catch some cases of missing outs between splits... More...
 
void dag_cleanup_other_statements (dag)
 remove unneeded statements? you must know they are really un-needed! More...
 
bool single_image_assignement_p (dag)
 ??? I'm unsure about what happens to dead code in the pipeline... More...
 
list dag_computable_vertices (dag, const set, const set, const set)
 return the vertices which may be computed from the list of available images, excluding vertices in exclude. More...
 
void set_append_vertex_statements (set, list)
 
dag freia_build_dag (string, list, int, const hash_table, const set, const list, bool)
 build a full dag from list of statements ls. More...
 
bool dag_no_image_operation (dag)
 tell whether we have something to do with images ??? hmmm... More...
 
statement freia_memory_management_statement (entity, const hash_table, bool)
 
void freia_switch_image_in_statement (statement, entity, entity, bool)
 switch read or written image in statement if this is an AIPO call, only substitute output or input depending on write otherwise all occurrences are substituted More...
 
list dag_fix_image_reuse (dag, hash_table, const hash_table)
 fix intermediate image reuse in dag More...
 
list dag_split_on_scalars (const dag, bool(*)(const dagvtx), dagvtx(*)(const list, bool), gen_cmp_func_t, void(*)(const dag), const set)
 split a dag on scalar dependencies only, with a greedy heuristics. More...
 
list dag_connected_component (dag, list *, bool(*)(const dagvtx, const set, const dag))
 extract a sublist of lv which is a connected component. More...
 
list dag_split_connected_components (dag, set)
 build connected components More...
 
const freia_api_thwac_freia_api (const char *)
 freia-utils.c More...
 
int hwac_freia_api_index (const string)
 returns the index of the description of an AIPO function More...
 
const freia_api_tget_freia_api (int)
 
const freia_api_tget_freia_api_vtx (dagvtx)
 
string what_operation (const _int type)
 
string what_operation_shape (const _int type)
 SPoC: set shape depending on hardware component used by vertex. More...
 
void freia_spoc_set_operation (const freia_api_t *, _int *, _int *)
 ??? beurk: I keep the operation as two ints for code regeneration. More...
 
list freia_get_params (const freia_api_t *, list)
 get freia further parameters, skipping image ones More...
 
list freia_get_vertex_params (const dagvtx)
 
expression freia_get_nth_scalar_param (const dagvtx, int)
 
int freia_max_pixel_value (void)
 
list freia_extract_params (const int, list, string_buffer, string_buffer, hash_table, int *)
 returns an allocated expression list of the parameters only (i.e. More...
 
call freia_ok (void)
 build all is well freia constant More...
 
bool freia_assignment_p (const entity)
 tell whether it is an assignment to ignore? More...
 
statement freia_copy_image (const entity, const entity)
 
void hwac_replace_statement (statement, call, bool)
 replace statement contents with call to c, or continue if kill More...
 
void hwac_kill_statement (statement)
 remove contents of statement s. More...
 
bool freia_image_variable_p (const entity)
 rather approximative? More...
 
bool entity_freia_api_p (const entity)
 returns whether the entity is a freia API (AIPO) function. More...
 
bool freia_statement_aipo_call_p (const statement)
 returns whether the statement is a FREIA call. More...
 
void freia_init_dep_cache (void)
 
void freia_close_dep_cache (void)
 
bool freia_scalar_rw_dep (const statement, const statement, list *)
 
call freia_statement_to_call (const statement)
 return the actual function call from a statement, dealing with assign and returns... More...
 
bool is_freia_alloc (const statement)
 
bool is_freia_dealloc (const statement)
 
bool same_constant_parameters (const dagvtx, const dagvtx)
 tell whether v1 and v2 point to statements with the same parameters. More...
 
entity freia_create_helper_function (const string, list)
 
int freia_substitute_by_helper_call (dag, set, set, list, const string, list, set, int)
 substitute those statement in ls that are in dag d and accelerated by a call to function_name(lparams) also update sets of remainings and global_remainings More...
 
void freia_insert_added_stats (list, list, bool)
 insert statements to actual code sequence in "ls" BEWARE that ls is assumed to be in reverse order... More...
 
void freia_add_image_arguments (list, list *)
 prepend limg images in front of the argument list limg is consummed by the operation. More...
 
hash_table freia_build_image_occurrences (statement, set, hash_table, const hash_table)
 
void freia_clean_image_occurrences (hash_table)
 cleanup occurrence data structure More...
 
bool freia_aipo_spoc_implemented (const freia_api_t *)
 whether api available with SPoC More...
 
bool freia_aipo_terapix_implemented (const freia_api_t *)
 whether api available with Ter@pix More...
 
bool freia_convolution_p (dagvtx)
 is it the convolution special case? More...
 
bool freia_convolution_width_height (dagvtx, _int *, _int *, bool)
 get width & height of convolution More...
 
list freia_allocate_new_images_if_needed (list, list, const hash_table, const hash_table, const hash_table)
 insert image allocation if needed, for intermediate image inserted before if an image is used only twice, then it is switched back to the initial one More...
 
int freia_aipo_count (dag, int *, int *)
 
set freia_compute_output_images (entity, statement)
 
set freia_compute_current_output_images (void)
 
void freia_migrate_statements (sequence, const set, const set)
 
bool freia_extract_kernel_vtx (dagvtx, bool, intptr_t *, intptr_t *, intptr_t *, intptr_t *, intptr_t *, intptr_t *, intptr_t *, intptr_t *, intptr_t *)
 vertex-based version More...
 
string helper_file_name (string, string)
 return malloc'ed "foo.database/Src/%{module}_helper_functions.c" should it depend on the target? no, because we could mix targets? More...
 
bool freia_unroll_while (const string)
 freia_transformations.c More...
 
bool freia_remove_scalar_ww_deps (const string)
 
bool remove_simple_scalar_pointers (const string)
 
void freia_shuffle_move_forward (statement)
 

Function Documentation

◆ copy_dagvtx_norec()

dagvtx copy_dagvtx_norec ( dagvtx  v)

copy a vertex, but without its successors.

Definition at line 611 of file dag-utils.c.

612 {
613  list lsave = dagvtx_succs(v);
614  // temporary cut costs
615  dagvtx_succs(v) = NIL;
616  dagvtx copy = copy_dagvtx(v);
617  dagvtx_succs(v) = lsave;
618  return copy;
619 }
dagvtx copy_dagvtx(dagvtx p)
DAGVTX.
#define dagvtx_succs(x)
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References copy_dagvtx(), dagvtx_succs, and NIL.

Referenced by compile_this_list(), dag_split_connected_components(), dag_split_on_scalars(), and opencl_generate_special_kernel_ops().

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

◆ dag_append_vertex()

void dag_append_vertex ( dag  d,
dagvtx  nv 
)

append new vertex nv to dag d.

Parameters
nvv

Definition at line 632 of file dag-utils.c.

633 {
634  pips_assert("not in dag", !gen_in_list_p(nv, dag_vertices(d)));
635  pips_assert("no successors", dagvtx_succs(nv) == NIL);
636 
637  // pips_assert("dag d ok 1", dag_consistent_p(d));
638  // pips_assert("nv is ok", dagvtx_consistent_p(nv));
639 
641  {
642  pips_assert("e is defined", e!=entity_undefined);
643  dagvtx pv = dagvtx_get_producer(d, NULL, e, dagvtx_number(nv));
644  if (!pv)
645  {
646  // side effect, create an input node of type 0 (not a computation)
647  pv = make_dagvtx
649 
650  dag_inputs(d) = CONS(dagvtx, pv, dag_inputs(d));
652  dag_vertices(d) = CONS(dagvtx, pv, dag_vertices(d));
653  }
654  // a vertex may have several time the same successor: b = a + a
655  dagvtx_succs(pv) = CONS(dagvtx, nv, dagvtx_succs(pv));
656  }
657  dag_vertices(d) = CONS(dagvtx, nv, dag_vertices(d));
658 
659  // ??? what about scalar deps?
660 }
pstatement make_pstatement_empty(void)
dagvtx make_dagvtx(vtxcontent a1, list a2)
vtxcontent make_vtxcontent(intptr_t a1, intptr_t a2, pstatement a3, list a4, entity a5)
_int dagvtx_number(const dagvtx v)
returns the vertex number, i.e.
Definition: dag-utils.c:98
dagvtx dagvtx_get_producer(const dag d, const dagvtx sink, const entity e, _int before_number)
return (last) producer of image e for vertex sink, or NULL if none found.
Definition: dag-utils.c:156
static void vertex_list_sorted_by_entities(list l)
Definition: dag-utils.c:524
#define dagvtx_content(x)
#define dag_inputs(x)
#define vtxcontent_inputs(x)
#define dag_vertices(x)
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734
#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
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define entity_undefined
Definition: ri.h:2761

References CONS, dag_inputs, dag_vertices, dagvtx_content, dagvtx_get_producer(), dagvtx_number(), dagvtx_succs, entity_undefined, FOREACH, gen_in_list_p(), make_dagvtx(), make_pstatement_empty(), make_vtxcontent(), NIL, pips_assert, vertex_list_sorted_by_entities(), and vtxcontent_inputs.

Referenced by compile_this_list(), dag_append_freia_call(), dag_split_connected_components(), dag_split_on_scalars(), and opencl_generate_special_kernel_ops().

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

◆ dag_cleanup_other_statements()

void dag_cleanup_other_statements ( dag  d)

remove unneeded statements? you must know they are really un-needed!

Definition at line 2191 of file dag-utils.c.

2192 {
2193  set toremove = set_make(set_pointer);
2194 
2195  FOREACH(dagvtx, v, dag_vertices(d))
2196  if (dagvtx_other_stuff_p(v))
2197  set_add_element(toremove, toremove, v);
2198 
2199  SET_FOREACH(dagvtx, vr, toremove)
2200  dag_remove_vertex(d, vr);
2201 }
bool dagvtx_other_stuff_p(const dagvtx v)
a vertex with a non AIPO or image related statement.
Definition: dag-utils.c:76
void dag_remove_vertex(dag d, const dagvtx v)
remove vertex v from dag d.
Definition: dag-utils.c:570
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
@ set_pointer
Definition: newgen_set.h:44
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
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59

References dag_remove_vertex(), dag_vertices, dagvtx_other_stuff_p(), FOREACH, set_add_element(), SET_FOREACH, set_make(), and set_pointer.

Referenced by compile_this_list(), dag_split_connected_components(), dag_split_on_scalars(), and mppa_dag_split().

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

◆ dag_computable_vertices()

list dag_computable_vertices ( dag  d,
const set  computed,
const set  maybe,
const set  currents 
)

return the vertices which may be computed from the list of available images, excluding vertices in exclude.

return a list for determinism.

Parameters
dis the considered full dag
computedholds all previously computed vertices
currentsholds those in the current pipeline @params maybe holds vertices with live images of dagvtx
Parameters
computedomputed
maybeaybe
currentsurrents

Definition at line 2306 of file dag-utils.c.

2308 {
2309  list computable = NIL;
2310  set local_currents = set_make(set_pointer);
2311  set not_computed = set_make(set_pointer);
2312  set not_computed_before = set_make(set_pointer);
2313 
2314  set_assign(local_currents, currents);
2315 
2316  FOREACH(dagvtx, v, dag_vertices(d))
2317  if (!set_belong_p(computed, v))
2318  set_add_element(not_computed, not_computed, v);
2319 
2320  // hmmm... should reverse the list to handle implicit dependencies?
2321  // where, there is an assert() to check that it does not happen.
2323 
2324  FOREACH(dagvtx, v, lv)
2325  {
2326  if (set_belong_p(computed, v))
2327  continue;
2328 
2329  if (dagvtx_other_stuff_p(v))
2330  {
2331  // a vertex with other stuff is assimilated to the pipeline
2332  // as soon as its dependences are fullfilled.
2333  // I have a problem here... I really need use_defs?
2334  if (all_previous_stats_with_deps_are_computed(d, computed, v))
2335  {
2336  computable = CONS(dagvtx, v, computable);
2337  set_add_element(local_currents, local_currents, v);
2338  set_del_element(not_computed, not_computed, v);
2339  }
2340  }
2341  else // we have an image computation
2342  {
2343  list preds = dag_vertex_preds(d, v);
2344  pips_debug(8, "%d predecessors to %" _intFMT "\n",
2345  (int) gen_length(preds), dagvtx_number(v));
2346 
2347  // build subset of "not computed" which should occur before v
2348  // from the initial sequence point of view
2349  set_clear(not_computed_before);
2350  SET_FOREACH(dagvtx, vnc, not_computed)
2351  {
2352  if (dagvtx_number(vnc)<dagvtx_number(v))
2353  set_add_element(not_computed_before, not_computed_before, vnc);
2354  }
2355 
2356  if(// no scalar dependencies in the current pipeline
2357  !any_scalar_dep(v, local_currents) &&
2358  // or in the future of the graph
2359  !any_scalar_dep(v, not_computed_before) &&
2360  // and image dependencies are fulfilled.
2361  list_in_set_p(preds, maybe))
2362  {
2363  computable = CONS(dagvtx, v, computable);
2364  // we do not want deps with other currents considered!
2365  set_add_element(local_currents, local_currents, v);
2366  set_del_element(not_computed, not_computed, v);
2367  }
2368 
2369  gen_free_list(preds), preds = NIL;
2370  }
2371 
2372  // update availables: not needed under assert for no img reuse.
2373  // if (vtxcontent_out(c)!=entity_undefined)
2374  // set_del_element(avails, avails, vtxcontent_out(c));
2375  }
2376 
2377  // cleanup
2378  set_free(local_currents);
2379  set_free(not_computed);
2380  set_free(not_computed_before);
2381  gen_free_list(lv);
2382  return computable;
2383 }
list dag_vertex_preds(const dag d, const dagvtx target)
return target predecessor vertices as a list.
Definition: dag-utils.c:680
static bool any_scalar_dep(dagvtx v, set vs)
returns whether there is a scalar RW dependency from any vs to v
Definition: dag-utils.c:2239
static bool all_previous_stats_with_deps_are_computed(dag d, const set computed, dagvtx v)
check scalar dependency from computed to v.
Definition: dag-utils.c:2274
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
size_t gen_length(const list l)
Definition: list.c:150
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
set set_del_element(set, const set, const void *)
Definition: set.c:265
bool list_in_set_p(const list, const set)
Definition: set.c:201
set set_assign(set, const set)
Assign a set with the content of another set.
Definition: set.c:129
void set_free(set)
Definition: set.c:332
set set_clear(set)
Assign the empty set to s s := {}.
Definition: set.c:326
bool set_belong_p(const set, const void *)
Definition: set.c:194
#define _intFMT
Definition: newgen_types.h:57

References _intFMT, all_previous_stats_with_deps_are_computed(), any_scalar_dep(), CONS, dag_vertex_preds(), dag_vertices, dagvtx_number(), dagvtx_other_stuff_p(), FOREACH, gen_copy_seq(), gen_free_list(), gen_length(), gen_nreverse(), list_in_set_p(), NIL, pips_debug, set_add_element(), set_assign(), set_belong_p(), set_clear(), set_del_element(), SET_FOREACH, set_free(), set_make(), and set_pointer.

Referenced by dag_split_on_scalars(), dag_terapix_measures(), and opencl_merge_and_compile().

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

◆ dag_computation_count()

int dag_computation_count ( const dag  d)

return the number of actual operations in dag d.

may be zero if only input vertices remain in the dag after optimizations.

Definition at line 665 of file dag-utils.c.

666 {
667  int count = 0;
668  FOREACH(dagvtx, v, dag_vertices(d))
669  if (dagvtx_number(v)!=0)
670  count++;
671  return count;
672 }
static int count
Definition: SDG.c:519

References count, dag_vertices, dagvtx_number(), and FOREACH.

Referenced by dag_split_on_scalars().

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

◆ dag_compute_outputs()

void dag_compute_outputs ( dag  d,
const hash_table  occs,
const set  output_images,
const list  ld,
bool  inloop 
)

(re)compute the list of GLOBAL input & output images for this dag ??? BUG the output is rather an approximation should rely on used defs or out effects for the underlying sequence.

however, the status of chains and effects on C does not allow it at the time. again after a look at DG (FC 08/08/2011)

Parameters
ddag to consider
occsstatement image occurences, may be NULL
output_imagesimages that are output, may be NULL
ldlist of some other dags, possibly NIL
Parameters
occsccs
output_imagesutput_images
ldd
inloopnloop

Definition at line 2073 of file dag-utils.c.

2076 {
2077  pips_debug(4, "inloop=%s\n", bool_to_string(inloop));
2078 
2079  set outvars = set_make(set_pointer);
2080  set outs = set_make(set_pointer);
2081  set toremove = set_make(set_pointer);
2082  set stats = dag_stats(d);
2083 
2084  FOREACH(dagvtx, v, dag_vertices(d))
2085  {
2086  pips_debug(8, "considering vertex %" _intFMT "\n", dagvtx_number(v));
2087  vtxcontent c = dagvtx_content(v);
2088  // skip special input nodes...
2089  if (dagvtx_number(v)!=0)
2090  {
2091  // get entity produced by vertex
2092  entity out = vtxcontent_out(c);
2093 
2094  pips_debug(8, "entity is %s\n", safe_entity_name(out));
2095 
2096  if (// we have an image
2097  out!=entity_undefined &&
2098  // it is not already an output
2099  !set_belong_p(outvars, out) &&
2100  // and either...
2101  (// this image is used as output (typically a tx call)
2102  (output_images && set_belong_p(output_images, out)) ||
2103  // no successors to this vertex BUT it is used somewhere (else?)
2104  (!dagvtx_succs(v) && other_significant_uses(out, occs, stats)) ||
2105  // all non-empty successors are measures?!
2106  (dagvtx_succs(v) && all_mesures_p(dagvtx_succs(v))) ||
2107  // new function parameter not yet an output
2108  (formal_parameter_p(out) && !set_belong_p(outvars, out)) ||
2109  // hmmm... yet another hack for freia_61
2111  // an output image is only reused by this dag within a loop?
2112  (inloop && dag_image_is_an_input(d, out))))
2113  {
2114  pips_debug(7, "appending %" _intFMT "\n", dagvtx_number(v));
2115  set_add_element(outvars, outvars, out);
2116  set_add_element(outs, outs, v);
2117  }
2118  }
2119  else
2120  {
2121  // ??? this aborts with terapix...
2122  // pips_assert("is an input vertex", gen_in_list_p(v, dag_inputs(d)));
2123  if (!dagvtx_succs(v))
2124  set_add_element(toremove, toremove, v);
2125  }
2126  }
2127 
2128  ifdebug(8)
2129  {
2130  dag_dump(stderr, "dag_compute_outputs", d);
2131  set_fprint(stderr, "new outs", outs, (gen_string_func_t) dagvtx_number_str);
2132  }
2133 
2134  // cleanup unused node inputs
2135  SET_FOREACH(dagvtx, vr, toremove)
2136  dag_remove_vertex(d, vr);
2137 
2140 
2141  // cleanup
2142  set_free(stats);
2143  set_free(outs);
2144  set_free(outvars);
2145  set_free(toremove);
2146 }
static FILE * out
Definition: alias_check.c:128
static bool variable_used_as_later_input(entity img, list ld)
hmmm...
Definition: dag-utils.c:2026
static bool dag_image_is_an_input(dag d, entity img)
Definition: dag-utils.c:2045
int dagvtx_ordering(const dagvtx *v1, const dagvtx *v2)
Definition: dag-utils.c:148
static bool other_significant_uses(entity e, const hash_table occs, const set stats)
Definition: dag-utils.c:2010
string dagvtx_number_str(const dagvtx v)
Definition: dag-utils.c:111
static bool all_mesures_p(list lv)
return whether all vertices in list are mesures...
Definition: dag-utils.c:1957
void dag_dump(FILE *out, const string what, const dag d)
for dag debug
Definition: dag-utils.c:212
static set dag_stats(dag d)
Definition: dag-utils.c:1973
#define dag_outputs(x)
#define vtxcontent_out(x)
string bool_to_string(bool)
Definition: string.c:243
list set_to_sorted_list(const set, gen_cmp_func_t)
Definition: set.c:447
void set_fprint(FILE *, string, const set, gen_string_func_t)
print set s to file stream out.
Definition: set.c:524
string(* gen_string_func_t)(const void *)
Definition: newgen_types.h:111
int(* gen_cmp_func_t)(const void *, const void *)
Definition: newgen_types.h:114
string safe_entity_name(entity e)
predicates and functions for entities
Definition: entity.c:433
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define ifdebug(n)
Definition: sg.c:47

References _intFMT, all_mesures_p(), bool_to_string(), dag_dump(), dag_image_is_an_input(), dag_outputs, dag_remove_vertex(), dag_stats(), dag_vertices, dagvtx_content, dagvtx_number(), dagvtx_number_str(), dagvtx_ordering(), dagvtx_succs, entity_undefined, FOREACH, formal_parameter_p(), gen_free_list(), ifdebug, other_significant_uses(), out, pips_debug, safe_entity_name(), set_add_element(), set_belong_p(), SET_FOREACH, set_fprint(), set_free(), set_make(), set_pointer, set_to_sorted_list(), variable_used_as_later_input(), and vtxcontent_out.

Referenced by compile_this_list(), dag_split_connected_components(), dag_split_on_scalars(), freia_build_dag(), and freia_spoc_pipeline().

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

◆ dag_connected_component()

list dag_connected_component ( dag  d,
list plv,
bool(*)(const dagvtx, const set, const dag compat 
)

extract a sublist of lv which is a connected component.

update lv so that the extracted vertices are not there. the extracted list must keep the order of the initial list!

Parameters
plvlv

Definition at line 2939 of file dag-utils.c.

2941 {
2942  ifdebug(7) {
2943  pips_debug(7, "entering\n");
2944  gen_fprint(stderr, "initial list", *plv, dagvtx_nb);
2945  }
2946 
2947  set connected = set_make(set_pointer);
2948  set extracted = set_make(set_pointer);
2949 
2950  // boostrap.
2951  dagvtx first = DAGVTX(CAR(*plv));
2952  set_add_element(extracted, extracted, first);
2953  set_add_element(connected, connected, first);
2954  set_append_list(connected, dagvtx_succs(first));
2955 
2956  bool stable = false;
2957  while (!stable)
2958  {
2959  stable = true;
2960 
2961  // expand thru common dag inputs
2962  FOREACH(dagvtx, i, dag_inputs(d))
2963  {
2964  bool merge = false;
2965  FOREACH(dagvtx, v, dagvtx_succs(i)) {
2966  if (set_belong_p(extracted, v)) {
2967  merge = true;
2968  break;
2969  }
2970  }
2971  if (merge)
2972  set_append_list(connected, dagvtx_succs(i));
2973  }
2974 
2975  // expand with new vertices from the list
2976  FOREACH(dagvtx, v, *plv)
2977  {
2978  if (!set_belong_p(extracted, v) && (!compat || compat(v, extracted, d)))
2979  {
2980  // do we need to extract v?
2981  bool connect = set_belong_p(connected, v);
2982  if (!connect) {
2983  FOREACH(dagvtx, s, dagvtx_succs(v))
2984  if (set_belong_p(extracted, s)) {
2985  connect = true;
2986  break;
2987  }
2988  }
2989  if (connect) {
2990  stable = false;
2991  set_add_element(extracted, extracted, v);
2992  set_add_element(connected, connected, v);
2993  set_append_list(connected, dagvtx_succs(v));
2994  }
2995  }
2996  }
2997  }
2998 
2999  // split initial list
3000  list lnew = NIL, lold = NIL;
3001  FOREACH(dagvtx, v, *plv)
3002  {
3003  if (set_belong_p(extracted, v))
3004  lnew = CONS(dagvtx, v, lnew);
3005  else
3006  lold = CONS(dagvtx, v, lold);
3007  }
3008  lnew = gen_nreverse(lnew);
3009  gen_free_list(*plv);
3010  *plv = gen_nreverse(lold);
3011 
3012  set_free(connected);
3013  set_free(extracted);
3014 
3015  ifdebug(7) {
3016  pips_debug(7, "exiting\n");
3017  gen_fprint(stderr, "final list", *plv, dagvtx_nb);
3018  gen_fprint(stderr, "returned", lnew, dagvtx_nb);
3019  }
3020 
3021  return lnew;
3022 }
static string dagvtx_nb(const void *s)
Definition: dag-utils.c:2931
#define DAGVTX(x)
DAGVTX.
void gen_fprint(FILE *out, string name, const list l, gen_string_func_t item_name)
Definition: list.c:873
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
set set_append_list(set, const list)
add list l items to set s, which is returned.
Definition: set.c:460

References CAR, CONS, dag_inputs, DAGVTX, dagvtx_nb(), dagvtx_succs, FOREACH, gen_fprint(), gen_free_list(), gen_nreverse(), ifdebug, NIL, pips_debug, set_add_element(), set_append_list(), set_belong_p(), set_free(), set_make(), and set_pointer.

Referenced by dag_split_connected_components(), and opencl_merge_and_compile().

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

◆ dag_consistency_asserts()

void dag_consistency_asserts ( dag  d)

do some consistency checking...

Definition at line 531 of file dag-utils.c.

532 {
533  FOREACH(dagvtx, v, dag_inputs(d))
534  pips_assert("vertex once in inputs", gen_occurences(v, dag_inputs(d))==1);
535 
536  set variable_seen = set_make(set_pointer);
537  FOREACH(dagvtx, v, dag_inputs(d))
538  {
540  // fprintf(stdout, " - image %s\n", entity_name(image));
541  pips_assert("image is defined", image!=entity_undefined);
542  pips_assert("variable only once in inputs",
543  !set_belong_p(variable_seen, image));
544  set_add_element(variable_seen, variable_seen, image);
545  }
546  set_free(variable_seen);
547 }
entity dagvtx_image(const dagvtx v)
return the produced image or NULL
Definition: dag-utils.c:82
int gen_occurences(const void *vo, const list l)
count occurences of vo in l
Definition: list.c:746
code taken from http://fast-edge.googlecode.com and adapted to c99
Definition: erode_dilate.c:33

References dag_inputs, dagvtx_image(), entity_undefined, FOREACH, gen_occurences(), pips_assert, set_add_element(), set_belong_p(), set_free(), set_make(), and set_pointer.

Referenced by freia_trpx_compile_one_dag().

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

◆ dag_dot()

void dag_dot ( FILE *  out,
const string  what,
const dag  d,
const list  lb,
const list  la 
)

output dag in dot format, for debug or show

Parameters
out,appendto this file
what,nameof dag
d,dagto output
Parameters
outut
whathat
lbb
laa

Definition at line 409 of file dag-utils.c.

411 {
412  // compute and show dag statistics
413  // count image, copy, scalar operations
414  int niops = 0, ncops = 0, nsops = 0;
415  FOREACH(dagvtx, op, dag_vertices(d))
416  {
417  if (dagvtx_is_copy_p(op)) ncops++;
418  else if (!gen_in_list_p(op, dag_inputs(d))) {
419  if (dagvtx_other_stuff_p(op)) nsops++;
420  else niops++;
421  }
422  }
423 
424  fprintf(out, "// DAG \"%s\": "
425  // input, output, computation, scalar vertices
426  "#i=%d #o=%d #c=%d #s=%d "
427  // copies: internal, before, after
428  "#I=%d #B=%d #A=%d\n",
429  what,
430  (int) gen_length(dag_inputs(d)), (int) gen_length(dag_outputs(d)),
431  niops, nsops, ncops, (int) gen_length(lb), (int) gen_length(la));
432 
433  // start graph
434  fprintf(out, "digraph \"%s\" {\n", what);
435 
436  // collect set of input images
437  set inputs = set_make(set_pointer);
438  FOREACH(dagvtx, i, dag_inputs(d))
439  {
440  entity img = dagvtx_image(i);
441  if (img && img!=entity_undefined)
442  set_add_element(inputs, inputs, img);
443  }
444 
445  // first, declare inputs and outputs as circles
446  dagvtx_list_dot(out, "inputs", dag_inputs(d), NULL);
447  dagvtx_list_dot(out, "outputs", dag_outputs(d), inputs);
448 
449  // second, show computations
450  fprintf(out, " // computation vertices\n");
451  FOREACH(dagvtx, vx, dag_vertices(d))
452  {
453  dagvtx_dot(out, d, vx);
454  vtxcontent c = dagvtx_content(vx);
455 
456  // outputs arcs for vx when the result is extracted
457  if (gen_in_list_p(vx, dag_outputs(d)))
458  {
459  entity img = vtxcontent_out(c);
460  dagvtx_dot_node(out, " ", vx);
461  fprintf(out, " -> \"%s%s\";\n",
462  entity_dot_name(img), set_belong_p(inputs, img)? "'": "");
463  }
464  }
465 
466  // handle external copies after the computation
467  if (lb)
468  {
469  fprintf(out, "\n // external before copies: %d\n", (int) gen_length(lb));
470  dagvtx_copy_list_dot(out, lb, inputs);
471  }
472 
473  if (la)
474  {
475  fprintf(out, "\n // external after copies: %d\n", (int) gen_length(la));
476  dagvtx_copy_list_dot(out, la, inputs);
477  }
478 
479  fprintf(out, "}\n");
480 
481  set_free(inputs);
482 }
static const char * entity_dot_name(entity e)
Definition: dag-utils.c:233
static void dagvtx_dot_node(FILE *out, const string prefix, const dagvtx v)
Definition: dag-utils.c:238
static void dagvtx_dot(FILE *out, const dag d, const dagvtx vtx)
Definition: dag-utils.c:252
static void dagvtx_copy_list_dot(FILE *out, const list ls, const set inputs)
Definition: dag-utils.c:350
static bool dagvtx_is_copy_p(const dagvtx v)
returns whether the vertex is an image copy operation.
Definition: dag-utils.c:399
static void dagvtx_list_dot(FILE *out, const string comment, const list l, const set used)
Definition: dag-utils.c:376
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

References dag_inputs, dag_outputs, dag_vertices, dagvtx_content, dagvtx_copy_list_dot(), dagvtx_dot(), dagvtx_dot_node(), dagvtx_image(), dagvtx_is_copy_p(), dagvtx_list_dot(), dagvtx_other_stuff_p(), entity_dot_name(), entity_undefined, FOREACH, fprintf(), gen_in_list_p(), gen_length(), out, set_add_element(), set_belong_p(), set_free(), set_make(), set_pointer, and vtxcontent_out.

Referenced by dag_dot_dump().

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

◆ dag_dot_dump()

void dag_dot_dump ( const  string,
const  string,
const  dag,
const  list,
const  list 
)

generate a "dot" format from a dag to a file.

Parameters
stringodule
stringame
listb
lista

Definition at line 488 of file dag-utils.c.

490 {
491  // build file name
492  string src_dir = db_get_directory_name_for_module(module);
493  string fn = strdup(cat(src_dir, "/", name, DOT_SUFFIX, NULL));
494  free(src_dir);
495 
496  FILE * out = safe_fopen(fn, "w");
497  fprintf(out, "// graph for dag \"%s\" of module \"%s\" in dot format\n",
498  name, module);
499  dag_dot(out, name, d, lb, la);
500  safe_fclose(out, fn);
501  free(fn);
502 }
#define DOT_SUFFIX
Definition: dag-utils.c:484
void dag_dot(FILE *out, const string what, const dag d, const list lb, const list la)
output dag in dot format, for debug or show
Definition: dag-utils.c:409
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
#define cat(args...)
Definition: freia.h:41
void free(void *)
string db_get_directory_name_for_module(const char *name)
returns the allocated and mkdir'ed directory for module name
Definition: lowlevel.c:150
static char * module
Definition: pips.c:74
char * strdup()

References cat, dag_dot(), db_get_directory_name_for_module(), DOT_SUFFIX, fprintf(), free(), module, out, safe_fclose(), safe_fopen(), and strdup().

Referenced by dag_dot_dump_prefix(), freia_trpx_compile_one_dag(), opencl_compile_mergeable_dag(), and opencl_merge_and_compile().

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

◆ dag_dot_dump_prefix()

void dag_dot_dump_prefix ( const  string,
const  string,
int  number,
const  dag,
const  list,
const  list 
)
Parameters
stringodule
stringrefix
numberumber
listb
lista

Definition at line 504 of file dag-utils.c.

506 {
507  string name = strdup(cat(prefix, i2a(number), NULL));
508  dag_dot_dump(module, name, d, lb, la);
509  free(name);
510 }
void dag_dot_dump(const string module, const string name, const dag d, const list lb, const list la)
generate a "dot" format from a dag to a file.
Definition: dag-utils.c:488
char * i2a(int)
I2A (Integer TO Ascii) yields a string for a given Integer.
Definition: string.c:121
static const char * prefix

References cat, dag_dot_dump(), free(), i2a(), module, prefix, and strdup().

Referenced by freia_aipo_compile_calls(), freia_build_dag(), freia_mppa_compile_calls(), freia_opencl_compile_calls(), and sc_delimiter().

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

◆ dag_dump()

void dag_dump ( FILE *  out,
const  string,
const  dag 
)

for dag debug

Parameters
outut
stringhat

Definition at line 212 of file dag-utils.c.

213 {
214  fprintf(out, "dag '%s' (%p) %"_intFMT" vertices:\n",
215  what, d, gen_length(dag_vertices(d)));
216 
217  dagvtx_nb_dump(out, "inputs", dag_inputs(d));
218  dagvtx_nb_dump(out, "outputs", dag_outputs(d));
219  fprintf(out, "\n");
220 
221  FOREACH(dagvtx, vx, dag_vertices(d)) {
222  dagvtx_dump(out, NULL, vx);
223  fprintf(out, "\n");
224  }
225 
226  fprintf(out, "\n");
227 }
void dagvtx_nb_dump(FILE *out, const string what, const list l)
Definition: dag-utils.c:176
void dagvtx_dump(FILE *out, const string name, const dagvtx v)
for dag debug.
Definition: dag-utils.c:186

References _intFMT, dag_inputs, dag_outputs, dag_vertices, dagvtx_dump(), dagvtx_nb_dump(), FOREACH, fprintf(), gen_length(), and out.

Referenced by dag_compute_outputs(), dag_split_on_scalars(), freia_build_dag(), freia_dag_optimize(), freia_trpx_compile_one_dag(), mppa_compile_dag(), opencl_compile_mergeable_dag(), and sc_delimiter().

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

◆ dag_fix_image_reuse()

list dag_fix_image_reuse ( dag  d,
hash_table  init,
const hash_table  occs 
)

fix intermediate image reuse in dag

Returns
new image entities to be added to declarations
Parameters
initnit
occsccs

Definition at line 2779 of file dag-utils.c.

2780 {
2781  list images = NIL;
2783 
2784  // dag vertices are assumed to be in reverse statement order,
2785  // so that last write is seen first and is kept by default
2786  FOREACH(dagvtx, v, dag_vertices(d))
2787  {
2788  entity img = dagvtx_image(v);
2789  if (!img || img==entity_undefined)
2790  continue;
2791 
2792  if (set_belong_p(seen, img) &&
2793  // but take care of image reuse, we must keep input images!
2794  !gen_in_list_p(v, dag_inputs(d)))
2795  {
2796  entity new_img = new_local_image_variable(img, occs);
2797  switch_image_variable(v, img, new_img);
2798  images = CONS(entity, new_img, images);
2799  // keep track of new->old image mapping, to reverse it latter eventually
2800  hash_put(init, new_img, img);
2801  }
2802  set_add_element(seen, seen, img);
2803  }
2804 
2805  set_free(seen);
2806  return images;
2807 }
static hash_table seen
static function to store whether a module has been seen during the recursive generation of the daVinc...
Definition: graph.c:85
static void switch_image_variable(dagvtx v, entity old, entity img)
switch to new image variable in v & its direct successors
Definition: dag-utils.c:2758
static entity new_local_image_variable(entity model, const hash_table occs)
Definition: dag-utils.c:2626
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
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320

References CONS, dag_inputs, dag_vertices, dagvtx_image(), entity_undefined, FOREACH, gen_in_list_p(), hash_put(), init, new_local_image_variable(), NIL, seen, set_add_element(), set_belong_p(), set_free(), set_make(), set_pointer, and switch_image_variable().

Referenced by freia_aipo_compile_calls(), freia_mppa_compile_calls(), freia_opencl_compile_calls(), and sc_delimiter().

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

◆ dag_no_image_operation()

bool dag_no_image_operation ( dag  d)

tell whether we have something to do with images ??? hmmm...

what about vol(cst_img()) ?

Definition at line 2500 of file dag-utils.c.

2501 {
2502  return !dag_inputs(d) && !dag_outputs(d);
2503 }

References dag_inputs, and dag_outputs.

Referenced by freia_mppa_compile_calls(), freia_opencl_compile_calls(), and sc_delimiter().

+ Here is the caller graph for this function:

◆ dag_remove_vertex()

void dag_remove_vertex ( dag  d,
const dagvtx  v 
)

remove vertex v from dag d.

if v isx a used computation vertex, it is substituted by an input vertex.

Definition at line 570 of file dag-utils.c.

571 {
572  // hmmm...
573  // pips_assert("vertex is in dag", gen_in_list_p(v, dag_vertices(d)));
574  if (!gen_in_list_p(v, dag_vertices(d)))
575  // already done???
576  return;
577 
578  if (dagvtx_succs(v))
579  {
580  // the ouput of the removed operation becomes an input to the dag
582  pips_assert("some variable", var!=entity_undefined);
583  dagvtx input =
589  }
590 
591  // remove from all vertex lists
592  gen_remove(&dag_vertices(d), v);
593  gen_remove(&dag_inputs(d), v);
594  gen_remove(&dag_outputs(d), v);
595 
596  // remove from successors of any ???
597  FOREACH(dagvtx, dv, dag_vertices(d))
598  gen_remove(&dagvtx_succs(dv), v);
599 
600  // cleanup input list
602 
603  // unlink vertex itself
605 
607 }
static void check_removed(const dagvtx v, const dagvtx removed)
Definition: dag-utils.c:513
static void dag_remove_unused_inputs(dag d)
remove unused inputs
Definition: dag-utils.c:551
#define dagvtx_domain
newgen_dag_domain_defined
#define gen_context_recurse(start, ctxt, domain_number, flt, rwt)
Definition: genC.h:285
static int input(void)
bool gen_true2(__attribute__((unused)) gen_chunk *u1, __attribute__((unused)) void *u2)
Definition: genClib.c:2785
void gen_remove(list *cpp, const void *o)
remove all occurences of item o from list *cpp, which is thus modified.
Definition: list.c:685

References check_removed(), CONS, dag_inputs, dag_outputs, dag_remove_unused_inputs(), dag_vertices, dagvtx_content, dagvtx_domain, dagvtx_succs, entity_undefined, FOREACH, gen_context_recurse, gen_copy_seq(), gen_free_list(), gen_in_list_p(), gen_remove(), gen_true2(), ifdebug, input(), make_dagvtx(), make_pstatement_empty(), make_vtxcontent(), NIL, pips_assert, vertex_list_sorted_by_entities(), and vtxcontent_out.

Referenced by dag_cleanup_other_statements(), dag_compute_outputs(), dag_split_connected_components(), dag_split_on_scalars(), freia_dag_optimize(), freia_spoc_pipeline(), freia_terapix_call(), and opencl_merge_and_compile().

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

◆ dag_split_connected_components()

list dag_split_connected_components ( dag  d,
set  output_images 
)

build connected components

Parameters
output_imagesutput_images

Definition at line 3035 of file dag-utils.c.

3036 {
3037  list lnd = NIL;
3038  list vertices = copy_vertices(dag_vertices(d));
3039 
3040  pips_debug(3, "considering %"_intFMT" vertices\n", gen_length(vertices));
3041  ifdebug(3)
3042  gen_fprint(stderr, "vertices", vertices, dagvtx_nb);
3043 
3044  while (vertices)
3045  {
3046  list cv = dag_connected_component(d, &vertices, NULL);
3047  pips_assert("some connected vertices", cv);
3048  if (!vertices) { // take remaining dag in full
3049  lnd = CONS(dag, d, lnd);
3050  break;
3051  }
3052 
3053  ifdebug(3) gen_fprint(stderr, "connected component", cv, dagvtx_nb);
3054 
3055  // else there seems to be an actual split...
3056  dag nd = make_dag(NIL, NIL, NIL);
3057  cv = gen_nreverse(cv); // ??? they must be introduced in reverse order?
3058  FOREACH(dagvtx, v, cv)
3060  dag_compute_outputs(nd, NULL, output_images, NIL, false);
3062  // ???
3064  lnd = CONS(dag, nd, lnd);
3065 
3066  // cleanup other dag for next round
3067  FOREACH(dagvtx, v, cv)
3068  dag_remove_vertex(d, v);
3069  dag_compute_outputs(d, NULL, output_images, NIL, false);
3071  }
3072 
3073  pips_debug(3, "found %"_intFMT" connected components\n", gen_length(lnd));
3074  return gen_nreverse(lnd);
3075 }
dag make_dag(list a1, list a2, list a3)
void dag_cleanup_other_statements(dag d)
remove unneeded statements? you must know they are really un-needed!
Definition: dag-utils.c:2191
static list copy_vertices(list lv)
Definition: dag-utils.c:3024
void freia_hack_fix_global_ins_outs(dag dfull, dag d)
catch some cases of missing outs between splits...
Definition: dag-utils.c:2166
dagvtx copy_dagvtx_norec(dagvtx v)
copy a vertex, but without its successors.
Definition: dag-utils.c:611
list dag_connected_component(dag d, list *plv, bool(*compat)(const dagvtx, const set, const dag))
extract a sublist of lv which is a connected component.
Definition: dag-utils.c:2939
void dag_compute_outputs(dag d, const hash_table occs, const set output_images, const list ld, bool inloop)
(re)compute the list of GLOBAL input & output images for this dag ??? BUG the output is rather an app...
Definition: dag-utils.c:2073
void dag_append_vertex(dag d, dagvtx nv)
append new vertex nv to dag d.
Definition: dag-utils.c:632
#define false
Definition: newgen_types.h:80
return(s1)

References _intFMT, CONS, copy_dagvtx_norec(), copy_vertices(), dag_append_vertex(), dag_cleanup_other_statements(), dag_compute_outputs(), dag_connected_component(), dag_remove_vertex(), dag_vertices, dagvtx_nb(), FOREACH, freia_hack_fix_global_ins_outs(), gen_fprint(), gen_length(), gen_nreverse(), ifdebug, make_dag(), NIL, pips_assert, and pips_debug.

+ Here is the call graph for this function:

◆ dag_split_on_scalars()

list dag_split_on_scalars ( const dag  initial,
bool(*)(const dagvtx alone_only,
dagvtx(*)(const list, bool choose_vertex,
gen_cmp_func_t  priority,
void(*)(const dag priority_update,
const set  output_images 
)

split a dag on scalar dependencies only, with a greedy heuristics.

Parameters
initialdag to split
alone_onlywhether to keep it alone (for non implemented cases)
choose_vertexchose a vertex from computable ones, may be NULL
priorityhow to prioritize computable vertices
priority_updatestuff to help prioritization
Returns
a list of sub-dags, some of which may contain no image operations For terapix, this pass also decides the schedule of image operations, with the aim or reducing the number of necessary imagelets, so as to maximise imagelet size.
Parameters
initialnitial
priorityriority
output_imagesutput_images

Definition at line 2823 of file dag-utils.c.

2829 {
2830  if (!single_image_assignement_p(initial))
2831  // well, it should work most of the time, so only a warning
2832  pips_user_warning("still some image reuse...\n");
2833 
2834  // ifdebug(1) pips_assert("initial dag ok", dag_consistent_p(initial));
2835  // if everything was removed by optimizations, there is nothing to do.
2836  if (dag_computation_count(initial)==0) return NIL;
2837 
2838  // work on a copy of the dag.
2839  dag dall = copy_dag(initial);
2840  list ld = NIL;
2841  set
2842  // current set of vertices to group
2844  // all vertices which are considered computed
2845  computed = set_make(set_pointer);
2846 
2847  do
2848  {
2849  list lcurrent = NIL, computables;
2850  set_clear(current);
2851  set_clear(computed);
2852  set_assign_list(computed, dag_inputs(dall));
2853 
2854  // GLOBAL for sorting
2855  if (priority_update) priority_update(dall);
2856 
2857  // transitive closure
2858  while ((computables =
2859  dag_computable_vertices(dall, computed, computed, current)))
2860  {
2861  ifdebug(7) {
2862  FOREACH(dagvtx, v, computables)
2863  dagvtx_dump(stderr, "computable", v);
2864  }
2865 
2866  // sort, mostly for determinism
2867  gen_sort_list(computables, priority);
2868 
2869  // choose one while building the schedule?
2870  dagvtx choice = choose_vertex?
2871  choose_vertex(computables, lcurrent? true: false):
2872  DAGVTX(CAR(computables));
2873  gen_free_list(computables), computables = NIL;
2874 
2875  ifdebug(7)
2876  dagvtx_dump(stderr, "choice", choice);
2877 
2878  // do not add if not alone
2879  if (alone_only && alone_only(choice) && lcurrent)
2880  break;
2881 
2883  set_add_element(computed, computed, choice);
2884  lcurrent = gen_nconc(lcurrent, CONS(dagvtx, choice, NIL));
2885 
2886  // getout if was alone
2887  if (alone_only && alone_only(choice))
2888  break;
2889  }
2890 
2891  // is there something?
2892  if (lcurrent)
2893  {
2894  // build extracted dag
2895  dag nd = make_dag(NIL, NIL, NIL);
2896  FOREACH(dagvtx, v, lcurrent)
2897  {
2898  pips_debug(7, "extracting node %" _intFMT "\n", dagvtx_number(v));
2900  }
2901  dag_compute_outputs(nd, NULL, output_images, NIL, false);
2903 
2904  ifdebug(7) {
2905  // dag_dump(stderr, "updated dall", dall);
2906  dag_dump(stderr, "pushed dag", nd);
2907  }
2908 
2909  // ??? hmmm... should not be needed?
2910  freia_hack_fix_global_ins_outs(initial, nd);
2911 
2912  // update global list of dags to return.
2913  ld = CONS(dag, nd, ld);
2914 
2915  // cleanup full dag for next round
2916  FOREACH(dagvtx, w, lcurrent)
2917  dag_remove_vertex(dall, w);
2918 
2919  gen_free_list(lcurrent), lcurrent = NIL;
2920  }
2921  }
2922  while (set_size(current));
2923 
2924  free_dag(dall);
2925  return gen_nreverse(ld);
2926 }
void free_dag(dag p)
dag copy_dag(dag p)
DAG.
int dag_computation_count(const dag d)
return the number of actual operations in dag d.
Definition: dag-utils.c:665
list dag_computable_vertices(dag d, const set computed, const set maybe, const set currents)
return the vertices which may be computed from the list of available images, excluding vertices in ex...
Definition: dag-utils.c:2307
bool single_image_assignement_p(dag d)
??? I'm unsure about what happens to dead code in the pipeline...
Definition: dag-utils.c:2217
if(!(yy_init))
Definition: genread_lex.c:1029
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
void gen_sort_list(list l, gen_cmp_func_t compare)
Sorts a list of gen_chunks in place, to avoid allocations...
Definition: list.c:796
#define pips_user_warning
Definition: misc-local.h:146
set set_assign_list(set, const list)
assigns a list contents to a set all duplicated elements are lost
Definition: set.c:474
int set_size(const set)
returns the number of items in s.
Definition: set.c:359
static size_t current
Definition: string.c:115
static Panel_item choice
Definition: xv_schoose2.c:54

References _intFMT, CAR, choice, CONS, copy_dag(), copy_dagvtx_norec(), current, dag_append_vertex(), dag_cleanup_other_statements(), dag_computable_vertices(), dag_computation_count(), dag_compute_outputs(), dag_dump(), dag_inputs, dag_remove_vertex(), DAGVTX, dagvtx_dump(), dagvtx_number(), FOREACH, free_dag(), freia_hack_fix_global_ins_outs(), gen_free_list(), gen_nconc(), gen_nreverse(), gen_sort_list(), ifdebug, make_dag(), NIL, pips_debug, pips_user_warning, set_add_element(), set_assign_list(), set_clear(), set_make(), set_pointer, set_size(), and single_image_assignement_p().

Referenced by freia_mppa_compile_calls(), freia_opencl_compile_calls(), and sc_delimiter().

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

◆ dag_statements()

void dag_statements ( set  stats,
const  dag 
)

build the set of actual statements in d

Parameters
statstats

Definition at line 64 of file dag-utils.c.

65 {
66  set_clear(stats);
68  {
70  if (s) set_add_element(stats, stats, s);
71  }
72 }
statement dagvtx_statement(const dagvtx v)
return statement if any, or NULL (for input nodes).
Definition: dag-utils.c:56

References dag_vertices, dagvtx_statement(), FOREACH, set_add_element(), and set_clear().

Referenced by freia_mppa_compile_calls(), freia_opencl_compile_calls(), and sc_delimiter().

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

◆ dag_vertex_preds()

list dag_vertex_preds ( const dag  d,
const dagvtx  target 
)

return target predecessor vertices as a list.

the same predecessor appears twice in b = a+a build them in call order! ??? maybe I should build a cache for performance, but I would have to keep track of when dags are modified...

Parameters
targetarget

Definition at line 680 of file dag-utils.c.

681 {
682  pips_debug(8, "building predecessors of %"_intFMT"\n", dagvtx_number(target));
683  list inputs = vtxcontent_inputs(dagvtx_content(target));
684  int nins = (int) gen_length(inputs);
685  entity first_img = NULL, second_img = NULL;
686  if (nins>=1) first_img = ENTITY(CAR(inputs));
687  if (nins==2) second_img = ENTITY(CAR(CDR(inputs)));
688  dagvtx first_v = NULL, second_v = NULL;
689 
690  FOREACH(dagvtx, v, dag_vertices(d))
691  {
692  if (v!=target && gen_in_list_p(target, dagvtx_succs(v)))
693  {
694  if (dagvtx_image(v)==first_img)
695  first_v = v;
696  if (dagvtx_image(v)==second_img)
697  second_v = v;
698  }
699  }
700 
701  list preds = NIL;
702  if (second_v) preds = CONS(dagvtx, second_v, NIL);
703  if (first_v) preds = CONS(dagvtx, first_v, preds);
704  return preds;
705 }
void const char const char const int
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755

References _intFMT, CAR, CDR, CONS, dag_vertices, dagvtx_content, dagvtx_image(), dagvtx_number(), dagvtx_succs, ENTITY, FOREACH, gen_in_list_p(), gen_length(), int, NIL, pips_debug, and vtxcontent_inputs.

Referenced by compute_dead_vertices(), dag_computable_vertices(), dag_simplify(), freia_dag_optimize(), image_is_needed(), mppa_compile_dag(), mppa_dag_split(), opencl_compile_mergeable_dag(), opencl_merge_and_compile(), sc_delimiter(), sc_get_port_id(), update_erosions(), and vertex_mergeable_p().

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

◆ dagvtx_compact_operation()

string dagvtx_compact_operation ( const  dagvtx)

Definition at line 140 of file dag-utils.c.

141 {
142  if (v==NULL) return "null";
143  int index = vtxcontent_opid(dagvtx_content(v));
144  const freia_api_t * api = get_freia_api(index);
145  return api->compact_name;
146 }
const freia_api_t * get_freia_api(int index)
Definition: freia-utils.c:477
#define vtxcontent_opid(x)
FREIA API function name -> SPoC hardware description (and others?)
Definition: freia.h:71
string compact_name
Definition: freia.h:75

References freia_api_t::compact_name, dagvtx_content, get_freia_api(), and vtxcontent_opid.

Referenced by compatible_reduction_operation(), dagvtx_dot(), dagvtx_dot_node(), and dagvtx_dot_node_sb().

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

◆ dagvtx_dump()

void dagvtx_dump ( FILE *  out,
const  string,
const  dagvtx 
)

for dag debug.

Parameters
outut
stringame

Definition at line 186 of file dag-utils.c.

187 {
188  if (!v) {
189  fprintf(out, "vertex %s is NULL\n", name? name: "");
190  return;
191  }
192  fprintf(out, "vertex %s %" _intFMT " %s (%p)\n",
193  name? name: "", dagvtx_number(v), dagvtx_operation(v), v);
194  dagvtx_nb_dump(out, " succs", dagvtx_succs(v));
195  vtxcontent c = dagvtx_content(v);
197  fprintf(out,
198  " optype: %s\n"
199  " opid: %" _intFMT "\n"
200  " source: %" _intFMT "/%" _intFMT "\n",
202  vtxcontent_opid(c),
203  s? statement_number(s): 0,
204  s? statement_ordering(s): 0);
205  entity_list_dump(out, " inputs", vtxcontent_inputs(c));
206  fprintf(out, " output: %s\n", safe_entity_name(vtxcontent_out(c)));
207  // to be continued...
208 }
static void entity_list_dump(FILE *out, const string what, const list l)
Definition: dag-utils.c:88
string dagvtx_operation(const dagvtx v)
Definition: dag-utils.c:134
string what_operation(const _int type)
Definition: freia-utils.c:499
#define vtxcontent_optype(x)
#define statement_ordering(x)
Definition: ri.h:2454
#define statement_number(x)
Definition: ri.h:2452

References _intFMT, dagvtx_content, dagvtx_nb_dump(), dagvtx_number(), dagvtx_operation(), dagvtx_statement(), dagvtx_succs, entity_list_dump(), fprintf(), out, safe_entity_name(), statement_number, statement_ordering, vtxcontent_inputs, vtxcontent_opid, vtxcontent_optype, vtxcontent_out, and what_operation().

Referenced by dag_dump(), dag_split_on_scalars(), dagvtx_terapix_priority(), and switch_vertex_to_a_copy().

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

◆ dagvtx_function_name()

string dagvtx_function_name ( const  dagvtx)

Definition at line 126 of file dag-utils.c.

127 {
128  if (v==NULL) return "null";
129  int index = vtxcontent_opid(dagvtx_content(v));
130  const freia_api_t * api = get_freia_api(index);
131  return api->function_name;
132 }
string function_name
Definition: freia.h:73

References dagvtx_content, freia_api_t::function_name, get_freia_api(), and vtxcontent_opid.

Referenced by dagvtx_operation(), and freia_aipo_count().

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

◆ dagvtx_get_producer()

dagvtx dagvtx_get_producer ( const dag  d,
const dagvtx  sink,
const entity  e,
_int  before_number 
)

return (last) producer of image e for vertex sink, or NULL if none found.

this is one of the two predecessors of sink.

Parameters
sinkink
before_numberefore_number

Definition at line 156 of file dag-utils.c.

158 {
159  pips_assert("some image", e!=entity_undefined);
160  FOREACH(dagvtx, v, dag_vertices(d))
161  {
162  vtxcontent c = dagvtx_content(v);
163  pips_debug(8, "%"_intFMT" pred of %"_intFMT"?\n",
164  dagvtx_number(v), dagvtx_number(sink));
165  // they may have been reversed ordered when used to append a vertex
166  if (before_number>0 && dagvtx_number(v)>0 && dagvtx_number(v)>before_number)
167  continue;
168  // the image may be kept within a pipe
169  if (vtxcontent_out(c)==e &&
170  (sink==NULL || gen_in_list_p(sink, dagvtx_succs(v))))
171  return v;
172  }
173  return NULL; // it is an external parameter?
174 }

References _intFMT, dag_vertices, dagvtx_content, dagvtx_number(), dagvtx_succs, entity_undefined, FOREACH, gen_in_list_p(), pips_assert, pips_debug, and vtxcontent_out.

Referenced by dag_append_vertex(), dag_vertex_pred_imagelets(), freia_dag_optimize(), and unlink_copy_vertex().

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

◆ dagvtx_image()

entity dagvtx_image ( const  dagvtx)

◆ dagvtx_is_measurement_p()

bool dagvtx_is_measurement_p ( const  dagvtx)

returns whether the vertex is an image measurement operation.

Definition at line 623 of file dag-utils.c.

624 {
625  vtxcontent c = dagvtx_content(v);
626  const freia_api_t * api = get_freia_api(vtxcontent_opid(c));
627  return strncmp(api->function_name, AIPO "global_", strlen(AIPO "global_"))==0;
628 }
#define AIPO
Definition: freia.h:51

References AIPO, dagvtx_content, freia_api_t::function_name, get_freia_api(), and vtxcontent_opid.

Referenced by all_vertices_are_copies_or_measures_p(), freia_dag_optimize(), mppa_compile_dag(), mppa_helper_args_params(), opencl_merge_and_compile(), sc_delimiter(), sigmac_params_decl(), and vertex_mergeable_p().

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

◆ dagvtx_nb_dump()

void dagvtx_nb_dump ( FILE *  out,
const  string,
const  list 
)
Parameters
outut
stringhat

Definition at line 176 of file dag-utils.c.

177 {
178  fprintf(out, "%s: ", what);
179  FOREACH(dagvtx, v, l)
180  fprintf(out, " %" _intFMT ",", dagvtx_number(v));
181  fprintf(out, "\n");
182 }

References _intFMT, dagvtx_number(), FOREACH, fprintf(), and out.

Referenced by dag_dump(), dagvtx_dump(), and sc_delimiter().

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

◆ dagvtx_number()

_int dagvtx_number ( const dagvtx  v)

returns the vertex number, i.e.

the underlying statement number.

Definition at line 98 of file dag-utils.c.

99 {
100  if (v==NULL) return 0;
102  if (pstatement_statement_p(source))
103  {
104  statement s = pstatement_statement(source);
105  return s? statement_number(s): 0;
106  }
107  else
108  return 0;
109 }
#define pstatement_statement_p(x)
#define pstatement_statement(x)
#define vtxcontent_source(x)

References dagvtx_content, pstatement_statement, pstatement_statement_p, statement_number, and vtxcontent_source.

Referenced by all_previous_stats_with_deps_are_computed(), any_scalar_dep(), comment(), copy_vertices(), dag_append_vertex(), dag_computable_vertices(), dag_computation_count(), dag_compute_outputs(), dag_split_on_scalars(), dag_vertex_preds(), dagvtx_dot(), dagvtx_dot_node(), dagvtx_dot_node_sb(), dagvtx_dump(), dagvtx_get_producer(), dagvtx_nb(), dagvtx_nb_dump(), dagvtx_number_str(), dagvtx_opencl_priority(), dagvtx_ordering(), dagvtx_spoc_priority(), dagvtx_terapix_priority(), dagvtx_to_string(), find_twin_vertex(), freia_dag_optimize(), freia_hack_fix_global_ins_outs(), freia_spoc_pipeline(), generate_wiring(), image_is_needed(), is_consummed_by_vertex(), mppa_compile_dag(), opencl_compile_mergeable_dag(), opencl_generate_special_kernel_ops(), opencl_merge_and_compile(), opencl_mergeable_p(), pixel_name(), print_op_schedule(), sc_delimiter(), substitute_image_in_statement(), switch_vertex_to_a_copy(), switch_vertex_to_assign(), unlink_copy_vertex(), and where_to_perform_operation().

+ Here is the caller graph for this function:

◆ dagvtx_number_str()

string dagvtx_number_str ( const  dagvtx)

Definition at line 111 of file dag-utils.c.

112 {
113  return i2a(dagvtx_number(v));
114 }

References dagvtx_number(), and i2a().

Referenced by any_scalar_dep(), dag_compute_outputs(), and opencl_merge_and_compile().

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

◆ dagvtx_operation()

string dagvtx_operation ( const  dagvtx)

Definition at line 134 of file dag-utils.c.

135 {
136  string op = dagvtx_function_name(v);
137  return strncmp(op, AIPO, strlen(AIPO))==0? op + strlen(AIPO): op;
138 }
string dagvtx_function_name(const dagvtx v)
Definition: dag-utils.c:126

References AIPO, and dagvtx_function_name().

Referenced by comment(), dagvtx_dump(), dagvtx_spoc_priority(), dagvtx_terapix_priority(), freia_convolution_p(), generate_wiring(), mppa_compile_dag(), print_op_schedule(), sc_delimiter(), and where_to_perform_operation().

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

◆ dagvtx_opid()

_int dagvtx_opid ( const  dagvtx)

◆ dagvtx_optype()

◆ dagvtx_ordering()

int dagvtx_ordering ( const dagvtx v1,
const dagvtx v2 
)
Parameters
v11
v22

Definition at line 148 of file dag-utils.c.

149 {
150  return dagvtx_number(*v1) - dagvtx_number(*v2);
151 }

References dagvtx_number().

Referenced by dag_compute_outputs(), and freia_mppa_compile_calls().

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

◆ dagvtx_other_stuff_p()

bool dagvtx_other_stuff_p ( const  dagvtx)

a vertex with a non AIPO or image related statement.

Definition at line 76 of file dag-utils.c.

77 {
79 }
@ spoc_type_oth
Definition: freia_spoc.h:173

References dagvtx_content, spoc_type_oth, and vtxcontent_optype.

Referenced by choose_opencl_vertex(), dag_cleanup_other_statements(), dag_computable_vertices(), dag_dot(), dagvtx_dot(), freia_opencl_compile_calls(), and freia_terapix_call().

+ Here is the caller graph for this function:

◆ dagvtx_statement()

◆ dagvtx_to_string()

string dagvtx_to_string ( const  dagvtx)

dag-utils.c

Definition at line 49 of file dag-utils.c.

50 {
51  return i2a(dagvtx_number(v));
52 }

References dagvtx_number(), and i2a().

+ Here is the call graph for this function:

◆ entity_freia_api_p()

bool entity_freia_api_p ( const  entity)

returns whether the entity is a freia API (AIPO) function.

Definition at line 806 of file freia-utils.c.

807 {
808  // very partial...
809  return strncmp(entity_local_name(f), AIPO, strlen(AIPO))==0;
810 }
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
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

References AIPO, entity_local_name(), and f().

Referenced by dag_append_freia_call(), fcs_call_flt(), and freia_statement_aipo_call_p().

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

◆ freia_add_image_arguments()

void freia_add_image_arguments ( list  limg,
list lparams 
)

prepend limg images in front of the argument list limg is consummed by the operation.

Parameters
limgimg
lparamsparams

Definition at line 1233 of file freia-utils.c.

1236 {
1237  list largs = NIL;
1238  limg = gen_nreverse(limg);
1239  FOREACH(entity, e, limg)
1240  largs = CONS(expression, entity_to_expression(e), largs);
1241  gen_free_list(limg), limg = NIL;
1242  *lparams = gen_nconc(largs, *lparams);
1243 }
list lparams
Array bounds.
Definition: reindexing.c:111
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165

References CONS, entity_to_expression(), FOREACH, gen_free_list(), gen_nconc(), gen_nreverse(), lparams, and NIL.

Referenced by freia_spoc_pipeline(), freia_terapix_call(), and opencl_compile_mergeable_dag().

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

◆ freia_aipo_compile_calls()

list freia_aipo_compile_calls ( string  module,
dag  fulld,
list  ls,
const  hash_table,
hash_table  exchanges,
int  number 
)

freia_aipo.c

Parameters
moduleodule
fulldulld
lss
hash_tableccs
exchangesxchanges
numberumber

Definition at line 48 of file freia_aipo.c.

55 {
56  pips_debug(3, "considering %d statements\n", (int) gen_length(ls));
57  pips_assert("some statements", ls);
58 
59  // about aipo statistics: no helper file to put them...
60 
61  // handle intermediate images
63  list new_images = dag_fix_image_reuse(fulld, init, occs);
64 
65  // optimize dag
66  list added_before = NIL, added_after = NIL;
67  freia_dag_optimize(fulld, exchanges, &added_before, &added_after);
68 
69  // dump final optimised dag
70  dag_dot_dump_prefix(module, "dag_cleaned_", number, fulld,
71  added_before, added_after);
72 
73  // now may put actual allocations, which messes up statement numbers
74  list reals =
75  freia_allocate_new_images_if_needed(ls, new_images, occs, init, NULL);
76 
77  // ??? should it be NIL because it is not useful in AIPO->AIPO?
78  freia_insert_added_stats(ls, added_before, true);
79  added_before = NIL;
80  freia_insert_added_stats(ls, added_after, false);
81  added_after = NIL;
82 
83  // cleanup
84  gen_free_list(new_images);
86 
87  return reals;
88 }
list dag_fix_image_reuse(dag d, hash_table init, const hash_table occs)
fix intermediate image reuse in dag
Definition: dag-utils.c:2779
void freia_dag_optimize(dag d, hash_table exchanges, list *lbefore, list *lafter)
remove dead image operations.
Definition: dag-utils.c:1416
void dag_dot_dump_prefix(const string module, const string prefix, int number, const dag d, const list lb, const list la)
Definition: dag-utils.c:504
list freia_allocate_new_images_if_needed(list ls, list images, const hash_table occs, const hash_table init, const hash_table signatures)
insert image allocation if needed, for intermediate image inserted before if an image is used only tw...
Definition: freia-utils.c:1650
void freia_insert_added_stats(list ls, list stats, bool before)
insert statements to actual code sequence in "ls" BEWARE that ls is assumed to be in reverse order....
Definition: freia-utils.c:1185
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
@ hash_pointer
Definition: newgen_hash.h:32

References dag_dot_dump_prefix(), dag_fix_image_reuse(), freia_allocate_new_images_if_needed(), freia_dag_optimize(), freia_insert_added_stats(), gen_free_list(), gen_length(), hash_pointer, hash_table_free(), hash_table_make(), init, module, NIL, pips_assert, and pips_debug.

Referenced by freia_compile().

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

◆ freia_aipo_compiler()

bool freia_aipo_compiler ( const  string)
Parameters
stringodule

Definition at line 134 of file hardware_accelerator.c.

135 {
136  return freia_compiler(module, "aipo");
137 }
static bool freia_compiler(const string module, const string hardware)
compile FREIA calls for some target.

References freia_compiler(), and module.

+ Here is the call graph for this function:

◆ freia_aipo_count()

int freia_aipo_count ( dag  d,
int pa,
int pc 
)
Returns
the number for FREIA AIPO ops in dag
Parameters
paa
pcc

Definition at line 1823 of file freia-utils.c.

1824 {
1825  int aipos = 0, copies = 0;
1826  FOREACH(dagvtx, v, dag_vertices(d))
1827  {
1828  string op = dagvtx_function_name(v);
1829  if (strncmp(op, AIPO, strlen(AIPO))==0) aipos++;
1830  // handle exceptions afterwards
1831  if (same_string_p(op, AIPO "copy")) copies++, aipos--;
1832  else if (same_string_p(op, AIPO "cast")) copies++, aipos--;
1833  else if (same_string_p(op, AIPO "scalar_copy")) aipos--;
1834  }
1835  *pa = aipos, *pc = copies;
1836  return aipos+copies;
1837 }
#define same_string_p(s1, s2)

References AIPO, dag_vertices, dagvtx_function_name(), FOREACH, and same_string_p.

Referenced by freia_opencl_compile_calls().

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

◆ freia_aipo_spoc_implemented()

bool freia_aipo_spoc_implemented ( const freia_api_t api)

whether api available with SPoC

Parameters
apipi

Definition at line 1418 of file freia-utils.c.

1419 {
1420  pips_assert("some api", api!=NULL);
1421  return api->spoc.used!=spoc_not_implemented;
1422 }
@ spoc_not_implemented
Definition: freia_spoc.h:58
spoc_hw_t spoc
Definition: freia.h:89
uint32_t used
Definition: freia_spoc.h:162

References pips_assert, freia_api_t::spoc, spoc_not_implemented, and spoc_hw_t::used.

◆ freia_aipo_terapix_implemented()

bool freia_aipo_terapix_implemented ( const freia_api_t api)

whether api available with Ter@pix

Parameters
apipi

Definition at line 1426 of file freia-utils.c.

1427 {
1428  pips_assert("some api", api!=NULL);
1429  // some special cases are handled manually
1430  if (same_string_p(api->function_name, "undefined") ||
1431  // this one is inserted to deal with replicated measures
1432  same_string_p(api->function_name, AIPO "scalar_copy"))
1433  return true;
1434  return api->terapix.cost!=-1;
1435 }
terapix_hw_t terapix
Definition: freia.h:90

References AIPO, terapix_hw_t::cost, freia_api_t::function_name, pips_assert, same_string_p, and freia_api_t::terapix.

Referenced by dagvtx_terapix_priority().

+ Here is the caller graph for this function:

◆ freia_allocate_new_images_if_needed()

list freia_allocate_new_images_if_needed ( list  ls,
list  images,
const hash_table  occs,
const hash_table  init,
const hash_table  signatures 
)

insert image allocation if needed, for intermediate image inserted before if an image is used only twice, then it is switched back to the initial one

This could/should be improved:

  • temporary images kept could be reused if possible, instead of new ones
  • not sure about the condition to move back to the initial image
Parameters
lslist of statements to consider
imageslist of entities to check and maybe allocate
initnew image -> initial image
signatureshelper -> _int # written args ahead (may be NULL)
Returns
list of actually allocated images
Parameters
lss
imagesmages
occsccs
initnit
signaturesignatures

Definition at line 1650 of file freia-utils.c.

1659 {
1660  // check for used images
1661  set img_stats = set_make(set_pointer);
1662  hash_table image_stats_detailed = hash_table_make(hash_pointer, 0);
1663  sequence sq = make_sequence(ls);
1664  hash_table newoccs =
1665  freia_build_image_occurrences((statement) sq, img_stats,
1666  image_stats_detailed, signatures);
1667  sequence_statements(sq) = NIL;
1668  free_sequence(sq);
1669 
1670  list allocated = NIL;
1671  FOREACH(entity, v, images)
1672  {
1673  if (!hash_defined_p(newoccs, v))
1674  // no written occurences, the image is not kept
1675  continue;
1676 
1677  if (get_bool_property("FREIA_REUSE_INITIAL_IMAGES"))
1678  {
1679  set where_write = (set) hash_get(newoccs, E_WRITE(v));
1680  set where_read = (set) hash_get(newoccs, E_READ(v));
1681  int nw = set_size(where_write), nr = set_size(where_read);
1682 
1683  pips_debug(6, "image %s used %d+%d statements\n", entity_name(v), nw, nr);
1684 
1685  // ??? should be used once only in the statement if written!
1686  // how to I know about W/R for helper functions?
1687  // its siblings should also be take into account
1688 
1689  // n>1 ??
1690  // if used only twice, substitude back to initial variable???
1691  // well, it may depends whether the the initial variable is used?
1692  // there is possibly something intelligent to do here, but it should
1693  // be checked carefully...
1694  if (nw==1 && nr>=1 && hash_defined_p(init, v))
1695  {
1696  entity old = (entity) hash_get(init, v);
1697 
1698  // get statements
1699  list l1 = set_to_list(where_write), l2 = set_to_list(where_read);
1700  statement s1 = STATEMENT(CAR(l1));
1701  gen_free_list(l1), l1 = NIL;
1702 
1703  // does not interact with possibly used old
1704  // if we could differentiate read & write, we could do better,
1705  // but the information is not currently available.
1706  bool skip = false;
1707  if (hash_defined_p(newoccs, old))
1708  {
1709  set old_write = (set) hash_get(newoccs, E_WRITE(old));
1710  set old_read = (set) hash_get(newoccs, E_READ(old));
1711  if (set_belong_p(old_write, s1))
1712  skip = true;
1713  else
1714  {
1715  FOREACH(statement, s2, l2)
1716  if (set_belong_p(old_read, s2))
1717  skip = true;
1718  }
1719  // note that we can handle a read in s1 and a write in s2
1720  }
1721 
1722  pips_debug(7, "testing for %s -> %s: %s\n",
1724  skip?"skip":"ok");
1725 
1726  // do we want to switch back?
1727  if (!skip &&
1728  only_minor_statements_in_between(v, init, image_stats_detailed,
1729  ls, s1, l2, img_stats))
1730  {
1731  // yes, they are successive, just remove?? Am I that sure???
1732  // ??? hmmm, maybe we could have :
1733  // X = stuff(...)
1734  // X_1 = stuff(...)
1735  // ... = stuff(X_1, ...)
1736  // ... = stuff(X...)
1737  // where X_1 -> X is just a bad idea because it overwrites X?
1738  // I'm not sure this can happen with AIPO, as X would be X_2
1739  // and will not be changed?
1740  pips_debug(7, "substituting back %s by %s\n",
1742 
1743  // we can perform any substitution here
1744  // note that it may be generated helper functions
1745  freia_switch_image_in_statement(s1, v, old, true);
1746  FOREACH(statement, s2, l2)
1747  freia_switch_image_in_statement(s2, v, old, false);
1748 
1749  // create/update uses of "old" to avoid interactions
1750  if (!hash_defined_p(newoccs, old))
1751  {
1752  hash_put(newoccs, E_WRITE(old), set_make(set_pointer));
1753  hash_put(newoccs, E_READ(old), set_make(set_pointer));
1754  }
1755  set old_write = (set) hash_get(newoccs, E_WRITE(old));
1756  set_add_element(old_write, old_write, s1);
1757  set old_read = (set) hash_get(newoccs, E_READ(old));
1758  FOREACH(statement, s2, l2)
1759  set_add_element(old_read, old_read, s2);
1760  }
1761  else
1762  allocated = CONS(entity, v, allocated);
1763  }
1764  else
1765  allocated = CONS(entity, v, allocated);
1766  }
1767  else
1768  allocated = CONS(entity, v, allocated);
1769  }
1770 
1771  clean_stats_to_image(image_stats_detailed);
1773  set_free(img_stats);
1774 
1775  // allocate those which are finally used
1776  if (allocated)
1777  {
1778  pips_assert("some statements", ls!=NIL);
1779  statement first = STATEMENT(CAR(ls));
1780  statement last = STATEMENT(CAR(gen_last(ls)));
1781  pips_assert("at least two statements", first!=last);
1782 
1783  // insert free_image(v)...
1784  // should insert image allocation statement as the same time
1785  // currently the allocation/deallocation may not be in the same scope!!!
1786  FOREACH(entity, v, images)
1787  {
1788  pips_debug(7, "allocating image %s\n", entity_name(v));
1789  // add_declaration_statement(first, v); // NO, returned
1790  // insert_statement(first, image_alloc(v), true); // NO, init
1791  // ??? deallocation should be at end of allocation block...
1792  entity model = (entity) hash_get(init, v);
1793  bool before = false;
1794  // find free_image(model) in the code
1795  statement fs = freia_memory_management_statement(model, occs, false);
1796  if (!fs)
1797  {
1798  pips_user_warning("not quite sure where to put %s deallocation\n",
1799  entity_name(v));
1800  // hmmm... try at the program level
1802  if (statement_sequence_p(ms))
1803  {
1804  fs = STATEMENT(
1806  // hmmm... does not seem to work properly
1807  //if (statement_call_p(s) &&
1808  // ENTITY_C_RETURN_P(call_function(statement_call(s))))
1809  before = true;
1810  }
1811  }
1812  insert_statement(fs? fs: last, image_free(v), before);
1813  }
1814  }
1815 
1816  return allocated;
1817 }
sequence make_sequence(list a)
Definition: ri.c:2125
void free_sequence(sequence p)
Definition: ri.c:2092
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
statement freia_memory_management_statement(entity image, const hash_table occs, bool alloc)
Definition: dag-utils.c:2587
void freia_switch_image_in_statement(statement s, entity old, entity img, bool write)
switch read or written image in statement if this is an AIPO call, only substitute output or input de...
Definition: dag-utils.c:2746
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
static void clean_stats_to_image(hash_table s2i)
Definition: freia-utils.c:1463
#define E_WRITE(v)
Definition: freia-utils.c:1247
hash_table freia_build_image_occurrences(statement s, set image_occs_stats, hash_table image_stats, const hash_table signatures)
Definition: freia-utils.c:1388
static statement image_free(entity v)
generate statement: "freia_free(v);"
Definition: freia-utils.c:1484
static bool only_minor_statements_in_between(entity image, hash_table new_images, hash_table image_stats, list ls, statement s1, list l2, set image_occurences)
tell whether there is no image processing statements between s1 and l2
Definition: freia-utils.c:1572
#define E_READ(v)
Definition: freia-utils.c:1248
void freia_clean_image_occurrences(hash_table occs)
cleanup occurrence data structure
Definition: freia-utils.c:1407
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
list gen_last(list l)
Return the last element of a list.
Definition: list.c:578
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
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
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
struct _set_chunk * set
Definition: newgen_set.h:38
list set_to_list(const set)
create a list from a set the set is not freed
Definition: set.c:436
#define entity_name(x)
Definition: ri.h:2790
#define sequence_statements(x)
Definition: ri.h:2360
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
s1
Definition: set.c:247

References CAR, clean_stats_to_image(), CONS, E_READ, E_WRITE, entity_local_name(), entity_name, FOREACH, free_sequence(), freia_build_image_occurrences(), freia_clean_image_occurrences(), freia_memory_management_statement(), freia_switch_image_in_statement(), gen_free_list(), gen_last(), get_bool_property(), get_current_module_statement(), hash_defined_p(), hash_get(), hash_pointer, hash_put(), hash_table_make(), image_free(), init, insert_statement(), make_sequence(), NIL, only_minor_statements_in_between(), pips_assert, pips_debug, pips_user_warning, s1, sequence_statements, set_add_element(), set_belong_p(), set_free(), set_make(), set_pointer, set_size(), set_to_list(), STATEMENT, statement_sequence(), and statement_sequence_p().

Referenced by freia_aipo_compile_calls(), freia_mppa_compile_calls(), freia_opencl_compile_calls(), and sc_delimiter().

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

◆ freia_assignment_p()

bool freia_assignment_p ( const  entity)

tell whether it is an assignment to ignore?

Definition at line 703 of file freia-utils.c.

704 {
706 }
#define ENTITY_ASSIGN_P(e)
#define ENTITY_BITWISE_OR_UPDATE_P(e)

References ENTITY_ASSIGN_P, and ENTITY_BITWISE_OR_UPDATE_P.

Referenced by fcs_call_flt(), freia_statement_aipo_call_p(), freia_statement_to_call(), get_assigned_variable(), and hwac_replace_statement().

+ Here is the caller graph for this function:

◆ freia_build_dag()

dag freia_build_dag ( string  module,
list  ls,
int  number,
const hash_table  occurrences,
const set  output_images,
const list  ld,
bool  inloop 
)

build a full dag from list of statements ls.

Parameters
module
listof statements in sequence
numberdag identifier in function
occurrencesentity -> set of statements where they appear
output_imagesset of images that are output
ldlist of other dags... (???)
inloopwhether we might be in a loop
Parameters
moduleodule
lss
numberumber
occurrencesccurrences
output_imagesutput_images
ldd
inloopnloop

Definition at line 2476 of file dag-utils.c.

2480 {
2481  // build full dag
2482  dag fulld = make_dag(NIL, NIL, NIL);
2483 
2484  FOREACH(statement, s, ls)
2485  dag_append_freia_call(fulld, s);
2486 
2487  dag_compute_outputs(fulld, occurrences, output_images, ld, inloop);
2488 
2489  ifdebug(3) dag_dump(stderr, "fulld", fulld);
2490 
2491  // dump resulting dag
2492  dag_dot_dump_prefix(module, "dag_", number, fulld, NIL, NIL);
2493 
2494  return fulld;
2495 }
static void dag_append_freia_call(dag d, statement s)
append statement s to dag d
Definition: dag-utils.c:2427

References dag_append_freia_call(), dag_compute_outputs(), dag_dot_dump_prefix(), dag_dump(), FOREACH, ifdebug, make_dag(), module, and NIL.

Referenced by freia_compile().

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

◆ freia_build_image_occurrences()

hash_table freia_build_image_occurrences ( statement  s,
set  image_occs_stats,
hash_table  image_stats,
const hash_table  signatures 
)
Parameters
image_occs_statsset of statements with image occurences (may be NULL)
signatureshelper entity -> (_int) # out args
Returns
build occurrence hash table: { entity -> set of statements }
Parameters
image_occs_statsmage_occs_stats
image_statsmage_stats
signaturesignatures

Definition at line 1388 of file freia-utils.c.

1393 {
1394  pips_debug(7, "entering\n");
1395  occs_ctx ctx = { hash_table_make(hash_pointer, 0), NULL,
1396  image_occs_stats, image_stats, signatures };
1397  gen_context_multi_recurse(s, &ctx,
1400  NULL);
1401  pips_debug(7, "done\n");
1402  return ctx.occs;
1403 }
static bool check_stmt(statement s, occs_ctx *ctx)
Definition: freia-utils.c:1367
static bool check_ref(reference r, occs_ctx *ctx)
hack to help replace use-def chains which did not work initially with C.
Definition: freia-utils.c:1328
void gen_context_multi_recurse(void *o, void *context,...)
Multi-recursion with context function visitor.
Definition: genClib.c:3373
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
hash_table occs
Definition: freia-utils.c:1309

References check_ref(), check_stmt(), gen_context_multi_recurse(), gen_null(), hash_pointer, hash_table_make(), occs_ctx::occs, pips_debug, reference_domain, and statement_domain.

Referenced by freia_allocate_new_images_if_needed(), and freia_compile().

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

◆ freia_clean_image_occurrences()

void freia_clean_image_occurrences ( hash_table  occs)

cleanup occurrence data structure

Parameters
occsccs

Definition at line 1407 of file freia-utils.c.

1408 {
1409  HASH_FOREACH(entity, v, set, s, occs)
1410  set_free(s);
1411  hash_table_free(occs);
1412 }
#define HASH_FOREACH(key_type, k, value_type, v, ht)
Definition: newgen_hash.h:71

References HASH_FOREACH, hash_table_free(), and set_free().

Referenced by freia_allocate_new_images_if_needed(), and freia_compile().

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

◆ freia_close_dep_cache()

void freia_close_dep_cache ( void  )

Definition at line 915 of file freia-utils.c.

916 {
917  pips_assert("dep_cache is not NULL", dep_cache);
918 
920  HASH_FOREACH(statement, s2, list, l, h)
921  if (l) gen_free_list(l);
922  hash_table_free(h);
923  }
924 
926 }
static hash_table dep_cache
Definition: freia-utils.c:907

References dep_cache, gen_free_list(), HASH_FOREACH, hash_table_free(), pips_assert, and s1.

Referenced by freia_compile().

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

◆ freia_compile()

string freia_compile ( string  module,
statement  mod_stat,
string  target 
)

freia_compile: compile freia module & statement for target

  • do some cleanup on sequences
  • collect sequences of freia operations
  • create file for generated functions
  • call hardware-specific code generation for each sequence
Parameters
moduleodule
mod_statod_stat
targetarget

Definition at line 785 of file freia.c.

786 {
787  pips_assert("we need some dependable effects for our purpose",
788  !get_bool_property("CONSTANT_PATH_EFFECTS"));
789 
790  if (!freia_valid_target_p(target))
791  pips_internal_error("unexpected target %s", target);
792 
793  // deal with some simple image shuff cases by forward substitution
795 
796  // check for remaining image shuffles...
797  set shuffled = set_make(set_pointer);
798  if (freia_image_shuffle(mod_stat, shuffled))
799  {
800  if (get_bool_property("FREIA_ALLOW_IMAGE_SHUFFLE"))
801  pips_user_warning("image shuffle found in %s, "
802  "freia compilation may result in wrong code!\n",
803  module);
804  else
805  pips_user_error("image shuffle found in %s, "
806  "see FREIA_ALLOW_IMAGE_SHUFFLE property to continue.\n",
807  module);
808  }
809 
810  // freia_aipo_cast -> freia_aipo_copy before further compilation
811  if (get_bool_property("FREIA_CAST_IS_COPY"))
813 
814  freia_info fsi =
817 
818  // collect freia api functions...
820  // collect sequences
823  // just count potential enclosing loops...
828  NULL);
829 
830  // check safe return
831  pips_assert("loop count back to zero", fsi.enclosing_loops==0);
832 
833  // sort sequences by increasing statement numbers
834  fsi_sort(fsi.seqs);
835 
836  // output file if any
837  string file = NULL;
838  set helpers = NULL;
839  FILE * helper = NULL;
840  if (freia_spoc_p(target) || freia_terapix_p(target) ||
841  freia_opencl_p(target) || freia_sigmac_p(target) || freia_mppa_p(target))
842  {
843  file = helper_file_name(module, "c");
844  if (file_readable_p(file))
845  pips_user_error("file '%s' already exists: "
846  "cannot reapply transformation\n", file);
847  helper = safe_fopen(file, "w");
848  pips_debug(1, "generating file '%s'\n", file);
849 
850  // we will also record created helpers
851  helpers = set_make(set_pointer);
852  }
853 
854  // headers
855  if (freia_spoc_p(target))
856  fprintf(helper, "%s", FREIA_SPOC_INCLUDES);
857  else if (freia_terapix_p(target))
858  fprintf(helper, "%s", FREIA_TRPX_INCLUDES);
859  else if (freia_opencl_p(target))
860  fprintf(helper, "%s", FREIA_OPENCL_INCLUDES);
861  else if (freia_sigmac_p(target))
862  fprintf(helper, "%s", FREIA_SIGMAC_INCLUDES);
863  else if (freia_mppa_p(target))
864  fprintf(helper, "%s", FREIA_MPPA_INCLUDES);
865 
866  // hmmm... should rely on use-defs
867  hash_table occs = freia_build_image_occurrences(mod_stat, NULL, NULL, NULL);
868  set output_images = freia_compute_current_output_images();
869  // hmmm... panic mode
870  set_union(output_images, output_images, shuffled);
871 
872  // first explicitely build and fix the list of dags,
873  // with some reverse order hocus-pocus for outputs computations...
874  list lsi = gen_nreverse(gen_copy_seq(fsi.seqs));
875  list ldags = NIL;
876  int n_dags = gen_length(fsi.seqs);
877  FOREACH(list, ls, lsi)
878  {
879  dag d = freia_build_dag(module, ls, --n_dags, occs, output_images, ldags,
880  set_belong_p(fsi.in_loops, ls));
881  ldags = CONS(dag, d, ldags);
882  }
883  gen_free_list(lsi), lsi = NIL;
884 
885  list lcurrent = ldags;
886  // signatures definition must be cross-dag because of
887  // dilate/erode helper reuse with OpenCL
888  hash_table signatures = hash_table_make(hash_pointer, 0);
889  n_dags = 0;
890  bool compile_lone = get_bool_property("FREIA_COMPILE_LONE_OPERATIONS");
891  FOREACH(list, ls, fsi.seqs)
892  {
893  // get corresponding dag, which should be destroyed by the called compiler
894  dag d = DAG(CAR(lcurrent));
895  lcurrent = CDR(lcurrent);
896 
897  // maybe skip lone operations
898  if (!compile_lone && gen_length(ls)==1)
899  {
900  n_dags++;
901  gen_free_list(ls);
902  continue;
903  }
904 
905  list allocated = NIL;
906  hash_table exchanges = NULL;
907  sequence sq = NULL;
908  if (hash_defined_p(fsi.sequence, ls))
909  {
910  exchanges = hash_table_make(hash_pointer, 0);
911  sq = hash_get(fsi.sequence, ls);
912  }
913 
914  if (freia_spoc_p(target))
915  allocated = freia_spoc_compile_calls(module, d, sq, ls, occs, exchanges,
916  output_images, helper, helpers, n_dags);
917  else if (freia_terapix_p(target))
918  allocated = freia_trpx_compile_calls(module, d, sq, ls, occs, exchanges,
919  output_images, helper, helpers, n_dags);
920  else if (freia_opencl_p(target))
921  allocated = freia_opencl_compile_calls(module, d, sq, ls, occs, exchanges,
922  output_images, helper, helpers, n_dags, signatures);
923  else if (freia_sigmac_p(target))
924  allocated = freia_sigmac_compile_calls(module, d, sq, ls, occs, exchanges,
925  output_images, helper, helpers, n_dags, gen_length(fsi.seqs));
926  else if (freia_mppa_p(target))
927  allocated =
928  freia_mppa_compile_calls(module, d, sq, ls, occs, exchanges,
929  output_images, helper, helpers, n_dags);
930  else if (freia_aipo_p(target))
931  allocated = freia_aipo_compile_calls(module, d, ls, occs, exchanges,
932  n_dags);
933 
934  if (exchanges)
935  {
937  HASH_FOREACH(dagvtx, v1, dagvtx, v2, exchanges)
939  }
940 
941  if (allocated)
942  {
943  FOREACH(entity, img, allocated)
945  gen_free_list(allocated);
946  }
947 
948  n_dags++;
949 
950  // cleanup list contents on the fly
951  gen_free_list(ls);
952  free_dag(d);
953  if (exchanges) hash_table_free(exchanges);
954  }
955 
956  // some code cleanup
958 
959  // some more code cleanup
960  if (get_bool_property("FREIA_CLEANUP_STATUS"))
961  // remove err = or err |= freia & helper functions
962  freia_cleanup_status(mod_stat, helpers);
963 
964  // cleanup
967  set_free(output_images), output_images = NULL;
968  set_free(shuffled), shuffled = NULL;
969  if (helpers) set_free(helpers), helpers = NULL;
970  gen_free_list(fsi.seqs);
971  set_free(fsi.in_loops);
973  hash_table_free(signatures);
974  gen_free_list(ldags);
975  if (helper) safe_fclose(helper, file);
976 
977  return file;
978 }
dag freia_build_dag(string module, list ls, int number, const hash_table occurrences, const set output_images, const list ld, bool inloop)
build a full dag from list of statements ls.
Definition: dag-utils.c:2476
bool file_readable_p(char *name)
Definition: file.c:428
string helper_file_name(string func_name, string suffix)
return malloc'ed "foo.database/Src/%{module}_helper_functions.c" should it depend on the target?...
Definition: freia-utils.c:2029
void freia_close_dep_cache(void)
Definition: freia-utils.c:915
void freia_init_dep_cache(void)
Definition: freia-utils.c:909
set freia_compute_current_output_images(void)
Definition: freia-utils.c:1885
static bool freia_image_shuffle(statement s, set shuffled)
Definition: freia.c:169
static bool fsi_stmt_flt(statement s, freia_info *fsip)
detect one lone aipo statement out of a sequence...
Definition: freia.c:542
static bool fsi_seq_flt(sequence sq, freia_info *fsip)
consider a sequence
Definition: freia.c:559
static bool fsi_loop_flt(__attribute__((unused)) gen_chunk *o, freia_info *fsip)
Definition: freia.c:463
static void fsi_sort(list lls)
Definition: freia.c:687
static void switch_cast_to_copy(statement s)
switch all image casts to image copies in "s"
Definition: freia.c:190
static bool freia_cleanup_main_sequence(statement modstat)
Definition: freia.c:768
static void freia_cleanup_status(statement s, set helpers)
Definition: freia.c:120
static void fsi_loop_rwt(__attribute__((unused)) gen_chunk *o, freia_info *fsip)
Definition: freia.c:470
#define freia_opencl_p(s)
Definition: freia.h:61
#define freia_sigmac_p(s)
Definition: freia.h:62
#define freia_mppa_p(s)
Definition: freia.h:63
#define freia_aipo_p(s)
Definition: freia.h:58
#define freia_spoc_p(s)
Definition: freia.h:59
#define freia_terapix_p(s)
Definition: freia.h:60
#define freia_valid_target_p(s)
Definition: freia.h:65
list freia_aipo_compile_calls(string module, dag fulld, list ls, const hash_table occs, hash_table exchanges, int number)
freia_aipo.c
Definition: freia_aipo.c:49
list freia_mppa_compile_calls(string module, dag fulld, sequence sq, list ls, const hash_table occs, hash_table exchanges, const set output_images, FILE *helper_file, __attribute__((__unused__)) set helpers, int number)
Compile one dag with AIPO optimizations.
Definition: freia_mppa.c:711
#define FREIA_MPPA_INCLUDES
Definition: freia_mppa.h:26
list freia_opencl_compile_calls(string module, dag fulld, sequence sq, list ls, const hash_table occs, hash_table exchanges, const set output_images, FILE *helper_file, set helpers, int number, hash_table signatures)
freia_opencl.c
#define FREIA_OPENCL_INCLUDES
Definition: freia_opencl.h:40
static int n_dags
Definition: freia_sigmac.c:56
#define FREIA_SIGMAC_INCLUDES
Definition: freia_sigmac.h:41
list freia_spoc_compile_calls(string module, dag fulld, sequence sq, list ls, const hash_table occs, hash_table exchanges, const set output_images, FILE *helper_file, set helpers, int number)
generate helpers for statements in ls of module output resulting functions in helper,...
Definition: freia_spoc.c:2247
#define FREIA_SPOC_INCLUDES
Definition: freia_spoc.h:188
#define DAG(x)
newgen_vtxcontent_domain_defined
list freia_trpx_compile_calls(string module, dag fulld, sequence sq, list ls, const hash_table occs, hash_table exchanges, const set output_images, FILE *helper_file, set helpers, int number)
do compile a list of statements for terapix
#define FREIA_TRPX_INCLUDES
Definition: freia_terapix.h:54
void freia_shuffle_move_forward(statement s)
void gen_exchange_in_list(list l, const void *i1, const void *i2)
exchange items i1 & i2 in the list
Definition: list.c:651
statement add_declaration_statement(statement, entity)
Definition: statement.c:2790
list freia_sigmac_compile_calls(string, dag, sequence, list, const hash_table, hash_table, const set, FILE *, set, int, int)
freia_sigmac.c
static statement mod_stat
We want to keep track of the current statement inside the recurse.
Definition: impact_check.c:41
#define pips_internal_error
Definition: misc-local.h:149
#define pips_user_error
Definition: misc-local.h:147
set set_union(set, const set, const set)
Definition: set.c:211
#define forloop_domain
newgen_extensions_domain_defined
Definition: ri.h:178
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#define loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
list seqs
Definition: freia.c:453
hash_table sequence
Definition: freia.c:455
int enclosing_loops
Definition: freia.c:457
set in_loops
Definition: freia.c:460

References add_declaration_statement(), CAR, CDR, CONS, DAG, dagvtx_statement(), freia_info::enclosing_loops, file_readable_p(), FOREACH, forloop_domain, fprintf(), free_dag(), freia_aipo_compile_calls(), freia_aipo_p, freia_build_dag(), freia_build_image_occurrences(), freia_clean_image_occurrences(), freia_cleanup_main_sequence(), freia_cleanup_status(), freia_close_dep_cache(), freia_compute_current_output_images(), freia_image_shuffle(), freia_init_dep_cache(), freia_mppa_compile_calls(), FREIA_MPPA_INCLUDES, freia_mppa_p, freia_opencl_compile_calls(), FREIA_OPENCL_INCLUDES, freia_opencl_p, freia_shuffle_move_forward(), freia_sigmac_compile_calls(), FREIA_SIGMAC_INCLUDES, freia_sigmac_p, freia_spoc_compile_calls(), FREIA_SPOC_INCLUDES, freia_spoc_p, freia_terapix_p, freia_trpx_compile_calls(), FREIA_TRPX_INCLUDES, freia_valid_target_p, fsi_loop_flt(), fsi_loop_rwt(), fsi_seq_flt(), fsi_sort(), fsi_stmt_flt(), gen_context_multi_recurse(), gen_copy_seq(), gen_exchange_in_list(), gen_free_list(), gen_length(), gen_nreverse(), gen_null(), get_bool_property(), hash_defined_p(), HASH_FOREACH, hash_get(), hash_pointer, hash_table_free(), hash_table_make(), helper_file_name(), freia_info::in_loops, loop_domain, mod_stat, module, n_dags, NIL, pips_assert, pips_debug, pips_internal_error, pips_user_error, pips_user_warning, safe_fclose(), safe_fopen(), freia_info::seqs, freia_info::sequence, sequence_domain, sequence_statements, set_belong_p(), set_free(), set_make(), set_pointer, set_union(), statement_domain, switch_cast_to_copy(), unstructured_domain, and whileloop_domain.

Referenced by freia_compiler().

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

◆ freia_compute_current_output_images()

set freia_compute_current_output_images ( void  )

Definition at line 1885 of file freia-utils.c.

1886 {
1889 }
set freia_compute_output_images(entity module, statement s)
Definition: freia-utils.c:1866
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85

References freia_compute_output_images(), get_current_module_entity(), and get_current_module_statement().

Referenced by freia_compile().

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

◆ freia_compute_output_images()

set freia_compute_output_images ( entity  module,
statement  s 
)
Returns
the set of images which are output somehow this is a little bit simplistic... read output effects of statement?
Parameters
moduleodule

Definition at line 1866 of file freia-utils.c.

1867 {
1868  set images = set_make(set_pointer);
1869 
1870  // image formal parameters
1872  {
1873  if (freia_image_variable_p(var))
1874  set_add_element(images, images, var);
1875  }
1876 
1877  // some image uses in the code
1878  gen_context_multi_recurse(s, images,
1881  NULL);
1882  return images;
1883 }
bool freia_image_variable_p(const entity var)
rather approximative?
Definition: freia-utils.c:768
static void oi_call_rwt(call c, set images)
Definition: freia-utils.c:1841
static void oi_stmt_rwt(statement s, set images)
Definition: freia-utils.c:1855
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define module_functional_parameters(func)
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58

References call_domain, FOREACH, freia_image_variable_p(), gen_context_multi_recurse(), gen_true(), module, module_functional_parameters, oi_call_rwt(), oi_stmt_rwt(), set_add_element(), set_make(), set_pointer, and statement_domain.

Referenced by freia_compute_current_output_images().

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

◆ freia_convolution_p()

bool freia_convolution_p ( dagvtx  v)

is it the convolution special case?

Definition at line 1441 of file freia-utils.c.

1442 {
1443  return same_string_p(dagvtx_operation(v), "convolution");
1444 }

References dagvtx_operation(), and same_string_p.

Referenced by dag_terapix_measures(), sc_inst(), sigmac_params_decl(), terapix_gram_management(), terapix_macro_code(), and update_erosions().

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

◆ freia_convolution_width_height()

bool freia_convolution_width_height ( dagvtx  v,
_int pw,
_int ph,
bool  check 
)

get width & height of convolution

Returns
whether they could be extracted
Parameters
pww
phh
checkheck

Definition at line 1449 of file freia-utils.c.

1450 {
1451  // pips_assert("vertex is convolution", ...)
1452  list largs = freia_get_vertex_params(v);
1453  if (check) pips_assert("3 args to convolution", gen_length(largs)==3);
1454  bool bw = expression_integer_value(EXPRESSION(CAR(CDR(largs))), pw);
1455  if (check) pips_assert("constant convolution width", bw);
1456  if (check) pips_assert("odd convolution width", ((*pw)%2)==1);
1457  bool bh = expression_integer_value(EXPRESSION(CAR(CDR(CDR(largs)))), ph);
1458  if (check) pips_assert("constant convolution height", bh);
1459  if (check) pips_assert("odd convolution height", ((*ph)%2)==1);
1460  return bw && bh;
1461 }
list freia_get_vertex_params(const dagvtx v)
Definition: freia-utils.c:578
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217

References CAR, CDR, EXPRESSION, expression_integer_value(), freia_get_vertex_params(), gen_length(), and pips_assert.

Referenced by dag_terapix_measures(), terapix_gram_management(), terapix_macro_code(), and update_erosions().

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

◆ freia_copy_image()

statement freia_copy_image ( const entity  source,
const entity  target 
)
Returns
"freia_aipo_copy(target, source);"
Parameters
sourceource
targetarget

Definition at line 710 of file freia-utils.c.

711 {
712  return call_to_statement(
715  CONS(expression, entity_to_expression(source), NIL))));
716 }
call make_call(entity a1, list a2)
Definition: ri.c:269
#define call_to_statement(c)
entity local_name_to_top_level_entity(const char *n)
This function try to find a top-level entity from a local name.
Definition: entity.c:1450

References AIPO, call_to_statement, CONS, entity_to_expression(), local_name_to_top_level_entity(), make_call(), and NIL.

Referenced by freia_dag_optimize().

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

◆ freia_create_helper_function()

entity freia_create_helper_function ( const  string,
list  lparams 
)
Parameters
stringunction_name
lparamsparams

Definition at line 1030 of file freia-utils.c.

1031 {
1032  // build helper entity
1033  entity example = local_name_to_top_level_entity("freia_aipo_add");
1034  pips_assert("example is a function", entity_function_p(example));
1035  entity helper = make_empty_function(function_name,
1037  make_language_c());
1038 
1039  // update type of parameters
1040  list larg_params = NIL;
1042  {
1043  debug_on("RI_UTILS_DEBUG_LEVEL");
1045  debug_off();
1046  larg_params = CONS(parameter,
1047  make_parameter(t,
1048  make_mode_value(),
1049  make_dummy_unknown()),
1050  larg_params);
1051  }
1052  larg_params = gen_nreverse(larg_params);
1053  module_functional_parameters(helper) = larg_params;
1054 
1055  return helper;
1056 }
parameter make_parameter(type a1, mode a2, dummy a3)
Definition: ri.c:1495
type copy_type(type p)
TYPE.
Definition: ri.c:2655
language make_language_c(void)
Definition: ri.c:1253
dummy make_dummy_unknown(void)
Definition: ri.c:617
mode make_mode_value(void)
Definition: ri.c:1353
#define debug_on(env)
Definition: misc-local.h:157
#define debug_off()
Definition: misc-local.h:160
bool entity_function_p(entity e)
Definition: entity.c:724
entity make_empty_function(const char *name, type r, language l)
Definition: entity.c:283
type expression_to_user_type(expression)
Preserve typedef'ed types when possible.
Definition: type.c:2645
#define functional_result(x)
Definition: ri.h:1444
#define type_functional(x)
Definition: ri.h:2952
#define entity_type(x)
Definition: ri.h:2792

References CONS, copy_type(), debug_off, debug_on, entity_function_p(), entity_type, expression_to_user_type(), FOREACH, functional_result, gen_nreverse(), local_name_to_top_level_entity(), lparams, make_dummy_unknown(), make_empty_function(), make_language_c(), make_mode_value(), make_parameter(), module_functional_parameters, NIL, pips_assert, and type_functional.

Referenced by freia_substitute_by_helper_call(), mppa_call_helper(), opencl_generate_special_kernel_ops(), and sc_delimiter().

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

◆ freia_dag_optimize()

void freia_dag_optimize ( dag  d,
hash_table  exchanges,
list lbefore,
list lafter 
)

remove dead image operations.

remove AIPO copies detected as useless. remove identical operations. return list of statements to be managed outside (external copies)... ??? maybe there should be a transitive closure...

Parameters
exchangesxchanges
lbeforebefore
lafterafter

Definition at line 1416 of file dag-utils.c.

1419 {
1420  set remove = set_make(set_pointer);
1421  size_t dag_output_count = gen_length(dag_outputs(d));
1422 
1423  ifdebug(6) {
1424  pips_debug(6, "considering dag:\n");
1425  dag_dump(stderr, "input", d);
1426  }
1427 
1428  if (get_bool_property("FREIA_NORMALIZE_OPERATIONS"))
1429  {
1430  dag_normalize(d);
1431 
1432  ifdebug(8) {
1433  pips_debug(4, "after FREIA_NORMALIZE_OPERATIONS:\n");
1434  dag_dump(stderr, "normalized", d);
1435  }
1436  }
1437 
1438  // algebraic simplifications
1439  // currently constant images are detected and propagated and constant pixels
1440  if (get_bool_property("FREIA_SIMPLIFY_OPERATIONS"))
1441  {
1442  dag_simplify(d);
1443 
1444  ifdebug(8) {
1445  pips_debug(4, "after FREIA_SIMPLIFY_OPERATIONS (1):\n");
1446  dag_dump(stderr, "simplified_1", d);
1447  // dag_dot_dump_prefix("main", "simplified", 0, d);
1448  }
1449  }
1450 
1451  // look for identical image operations (same inputs, same params)
1452  // (that produce image, we do not care about measures for SPOC,
1453  // but we should for terapix!)
1454  // the second one is replaced by a copy.
1455  // also handle commutations.
1456  if (get_bool_property("FREIA_REMOVE_DUPLICATE_OPERATIONS"))
1457  {
1458  pips_debug(6, "removing duplicate operations\n");
1459 
1460  // all vertices in dependence order
1461  list vertices = gen_nreverse(gen_copy_seq(dag_vertices(d)));
1462 
1463  // for all already processed vertices, the list of their predecessors
1464  hash_table previous = hash_table_make(hash_pointer, 10);
1465 
1466  // subset of vertices to be investigated
1467  set candidates = set_make(set_pointer);
1468 
1469  // subset of vertices already encountered which do not have predecessors
1470  set sources = set_make(set_pointer);
1471 
1472  // already processed vertices
1473  set processed = set_make(set_pointer);
1474 
1475  // potential n^2 loop, optimized by comparing only to the already processed
1476  // successors of the vertex predecessors . See "candidates" computation.
1477  FOREACH(dagvtx, vr, vertices)
1478  {
1479  int op = (int) vtxcontent_optype(dagvtx_content(vr));
1480  pips_debug(7, "at vertex %"_intFMT" (op=%d)\n", dagvtx_number(vr), op);
1481 
1482  // skip no-operations
1483  if (op<spoc_type_poc || op>spoc_type_mes) continue;
1484 
1485  // skip already removed ops
1486  if (set_belong_p(remove, vr)) continue;
1487 
1488  // pips_debug(8, "investigating...\n");
1489  list preds = dag_vertex_preds(d, vr);
1490 
1491  // build only "interesting" vertices, which shared inputs
1492  set_clear(candidates);
1493 
1494  // successors of predecessors
1495  FOREACH(dagvtx, p, preds)
1496  set_append_list(candidates, dagvtx_succs(p));
1497 
1498  // keep only already processed vertices
1499  set_intersection(candidates, candidates, processed);
1500 
1501  // possibly add those without predecessors (is that only set_const?)
1502  if (!preds) set_union(candidates, candidates, sources);
1503 
1504  // whether the vertex was changed
1505  bool switched = false;
1506 
1507  // I do not need to sort them, they are all different, only one can match
1508  SET_FOREACH(dagvtx, p, candidates)
1509  {
1510  pips_debug(8, "comparing %"_intFMT" and %"_intFMT"\n",
1511  dagvtx_number(vr), dagvtx_number(p));
1512 
1513  list lp = hash_get(previous, p);
1514 
1515  // ??? maybe I should not remove all duplicates, because
1516  // recomputing them may be cheaper?
1518  {
1519  // special handling for measures, esp for terapix
1520  if (gen_list_equals_p(preds, lp))
1521  {
1522  if (same_operation_p(vr, p))
1523  {
1524  // min(A, px), min(A, py) => min(A, px) && *py = *px
1525  if (switch_vertex_to_assign(vr, p))
1526  set_add_element(remove, remove, vr);
1527  // only one can match!
1528  switched = true;
1529  break;
1530  }
1531  else
1532  {
1533  int n = compatible_reduction_operation(p, vr);
1534  if (n==2)
1535  {
1536  // exchange role of vr & p
1537  set_del_element(processed, processed, p);
1538  set_add_element(processed, processed, vr);
1539  hash_del(previous, p);
1540  hash_put(previous, vr, lp);
1541  dagvtx t = p; p = vr; vr = t;
1542  // also in the list of statements to fix dependencies!
1543  if (exchanges) hash_put(exchanges, p, vr);
1544  }
1545  if (n==1 || n==2)
1546  {
1547  // we keep p which is a !, and vr is a simple reduction
1548  if (switch_vertex_to_assign(vr, p))
1549  set_add_element(remove, remove, vr);
1550 
1551  // done
1552  switched = true;
1553  break;
1554  }
1555  }
1556  }
1557  }
1558  else if (same_operation_p(vr, p) &&
1559  gen_list_equals_p(preds, lp) &&
1560  same_constant_parameters(vr, p))
1561  {
1562  switch_vertex_to_a_copy(vr, p, preds);
1563  // only one can match!
1564  switched = true;
1565  break;
1566  }
1567  else if (commutative_operation_p(vr, p) &&
1568  list_commuted_p(preds, (list) lp))
1569  {
1570  switch_vertex_to_a_copy(vr, p, preds);
1571  // only one can match!
1572  switched = true;
1573  break;
1574  }
1575  }
1576 
1577  if (switched)
1578  gen_free_list(preds);
1579  else
1580  {
1581  // update map & sets
1582  hash_put(previous, vr, preds);
1583  set_add_element(processed, processed, vr);
1584  if (!preds) set_add_element(sources, sources, vr);
1585  }
1586  }
1587 
1588  // cleanup
1589  HASH_MAP(k, v, if (v) gen_free_list(v), previous);
1590  hash_table_free(previous), previous = NULL;
1591  gen_free_list(vertices), vertices = NULL;
1592  set_free(candidates);
1593  set_free(sources);
1594  set_free(processed);
1595 
1596  ifdebug(8) {
1597  pips_debug(4, "after FREIA_REMOVE_DUPLICATE_OPERATIONS:\n");
1598  dag_dump(stderr, "remove duplicate", d);
1599  // dag_dot_dump_prefix("main", "remove_duplicates", 0, d);
1600  }
1601  }
1602 
1603  // algebraic simplifications *AGAIN*
1604  // some duplicate operation removal may have enabled more simplifications
1605  // for instance -(a,b) & a=~b => -(a,a) => cst(0)
1606  // we may have a convergence loop on both duplicate/simplify
1607  if (get_bool_property("FREIA_SIMPLIFY_OPERATIONS"))
1608  {
1609  dag_simplify(d);
1610 
1611  ifdebug(8) {
1612  pips_debug(4, "after FREIA_SIMPLIFY_OPERATIONS (2):\n");
1613  dag_dump(stderr, "simplified_2", d);
1614  // dag_dot_dump_prefix("main", "simplified", 0, d);
1615  }
1616  }
1617 
1618  // remove dead image operations
1619  // ??? hmmm... measures are kept because of the implicit scalar dependency?
1620  if (get_bool_property("FREIA_REMOVE_DEAD_OPERATIONS"))
1621  {
1622  pips_debug(6, "removing dead code\n");
1623  list vertices = gen_copy_seq(dag_vertices(d));
1624  FOREACH(dagvtx, v, vertices)
1625  {
1626  // skip non-image operations
1627  if (!vtxcontent_inputs(dagvtx_content(v)) &&
1629  vtxcontent_out(dagvtx_content(v))==NULL))
1630  continue;
1631 
1632  if (// no successors or they are all removed
1633  (!dagvtx_succs(v) || list_in_set_p(dagvtx_succs(v), remove)) &&
1634  // but we keep output nodes...
1635  !gen_in_list_p(v, dag_outputs(d)) &&
1636  // and measures...
1638  {
1639  pips_debug(7, "vertex %"_intFMT" is dead\n", dagvtx_number(v));
1640  set_add_element(remove, remove, v);
1641  }
1642  else
1643  pips_debug(8, "vertex %"_intFMT" is alive\n", dagvtx_number(v));
1644  }
1645  gen_free_list(vertices), vertices = NULL;
1646 
1647  ifdebug(8) {
1648  pips_debug(4, "after FREIA_REMOVE_DEAD_OPERATIONS:\n");
1649  dag_dump(stderr, "remove dead", d);
1650  // dag_dot_dump_prefix("main", "remove_dead", 0, d);
1651  }
1652  }
1653 
1654  if (get_bool_property("FREIA_REMOVE_USELESS_COPIES"))
1655  {
1656  set forwards = set_make(set_pointer);
1657  bool changed = true;
1658 
1659  // I -copy-> X -> ... where I is an input is moved forward
1660  // beware that image identifiers should not be reused, otherwise it may
1661  // merge two arcs... (freia_82 & freia_83)
1662 
1663  // we iterate the hard way, it could be little more subtle
1664  // this is necessary, see copy_02
1665  while (changed)
1666  {
1667  changed = false;
1668 
1669  // first propagate input images through copies
1670  FOREACH(dagvtx, v, dag_inputs(d))
1671  {
1672  list append = NIL;
1674 
1675  FOREACH(dagvtx, s, dagvtx_succs(v))
1676  {
1678  if (dagvtx_is_copy_p(s))
1679  {
1680  // forward propagation in dag & statements
1681  FOREACH(dagvtx, s2, dagvtx_succs(s))
1682  {
1683  substitute_image_in_statement(s2, copy, in, true);
1685  copy, in);
1686  }
1687  // update succs
1689  dagvtx_succs(s) = NIL;
1690 
1691  set_add_element(forwards, forwards, s);
1692  }
1693  }
1694  if (append)
1695  {
1696  FOREACH(dagvtx, a, append)
1697  {
1698  if (!gen_in_list_p(a, dagvtx_succs(v)))
1699  {
1700  dagvtx_succs(v) = CONS(dagvtx, a, dagvtx_succs(v));
1701  changed = true;
1702  }
1703  }
1704  }
1705  }
1706  }
1707 
1708  // op -> X -copy-> A where A is an output is moved backwards
1709  FOREACH(dagvtx, v, dag_vertices(d))
1710  {
1711  // skip special input nodes
1712  if (dagvtx_number(v)==0) continue;
1713 
1714  // skip already removed ops
1715  if (set_belong_p(remove, v)) continue;
1716 
1717  // skip forward propagated inputs
1718  if (set_belong_p(forwards, v)) continue;
1719 
1720  if (dagvtx_is_copy_p(v))
1721  {
1722  list preds = dag_vertex_preds(d, v);
1723  vtxcontent c = dagvtx_content(v);
1724  entity res = vtxcontent_out(c);
1725  pips_assert("one output and one input to copy",
1726  res!=entity_undefined &&
1727  gen_length(preds)==1 &&
1728  gen_length(vtxcontent_inputs(c))==1);
1729 
1730  // first check for A->copy->A really useless copies, which are skipped
1731  entity inimg = ENTITY(CAR(vtxcontent_inputs(c)));
1732  if (inimg==res)
1733  {
1734  set_add_element(remove, remove, v);
1735  dagvtx pred = DAGVTX(CAR(preds));
1736  // update predecessor's successors
1737  gen_remove(&dagvtx_succs(pred), v);
1738  dagvtx_succs(pred) = gen_nconc(dagvtx_succs(pred), dagvtx_succs(v));
1739  // fix global output if necessary
1740  if (gen_in_list_p(v, dag_outputs(d)))
1741  gen_replace_in_list(dag_outputs(d), v, pred);
1742  }
1743  // check for internal-t -one-copy-and-others-> A (output)
1744  // could be improved by dealing with the first copy only?
1745  else if (gen_in_list_p(v, dag_outputs(d)))
1746  {
1747  pips_assert("one predecessor to used copy", gen_length(preds)==1);
1748  dagvtx pred = DAGVTX(CAR(preds));
1749 
1750  if (number_of_copies(dagvtx_succs(pred))==1 &&
1751  !gen_in_list_p(pred, dag_outputs(d)) &&
1752  dagvtx_number(pred)!=0)
1753  {
1754  // BACKWARD COPY PROPAGATION
1755  // that is we want to produce the result directly
1756 
1757  vtxcontent pc = dagvtx_content(pred);
1758  entity old = vtxcontent_out(pc);
1759 
1760  // fix statement, needed for AIPO target
1761  substitute_image_in_statement(pred, old, res, false);
1762 
1763  // fix vertex
1764  vtxcontent_out(pc) = res;
1765  gen_remove(& dagvtx_succs(pred), v);
1766  bool done = gen_replace_in_list(dag_outputs(d), v, pred);
1767  pips_assert("output node was replaced", done);
1768  set_add_element(remove, remove, v);
1769 
1770  // BACK-FORWARD COPY PROPAGATION
1771  FOREACH(dagvtx, s, dagvtx_succs(pred))
1772  {
1773  substitute_image_in_statement(s, old, res, true);
1775  old, res);
1776  }
1777  }
1778  gen_free_list(preds);
1779  }
1780  }
1781  }
1782 
1783  // only one pass is needed because we're going backwards?
1784  // op-> X -copy-> Y images copies are replaced by op-> X & Y
1785  FOREACH(dagvtx, v, dag_vertices(d))
1786  {
1787  // skip special input nodes
1788  if (dagvtx_number(v)==0) continue;
1789 
1790  // skip already removed ops
1791  if (set_belong_p(remove, v)) continue;
1792 
1793  if (dagvtx_is_copy_p(v))
1794  {
1795  vtxcontent c = dagvtx_content(v);
1796  entity target = vtxcontent_out(c);
1797  pips_assert("one output and one input to copy",
1798  target!=entity_undefined && gen_length(vtxcontent_inputs(c))==1);
1799 
1800  // FORWARD COPY PROPAGATION
1801  // replace by its source everywhere it is used
1802  entity source = ENTITY(CAR(vtxcontent_inputs(c)));
1803 
1804  // remove!
1805  unlink_copy_vertex(d, source, v);
1806 
1807  // whether to actually remove v
1808  if (!gen_in_list_p(v, dag_outputs(d)))
1809  set_add_element(remove, remove, v);
1810  }
1811  }
1812 
1813  set_free(forwards);
1814 
1815  ifdebug(8) {
1816  pips_debug(4, "after FREIA_REMOVE_USELESS_COPIES:\n");
1817  dag_dump(stderr, "remove useless copies", d);
1818  // dag_dot_dump_prefix("main", "useless_copies", 0, d);
1819  }
1820  }
1821 
1822  if (get_bool_property("FREIA_MOVE_DIRECT_COPIES"))
1823  {
1824  // A-copy->B where A is an input is removed from the dag and managed outside
1825  // idem A-copy->B where A is an output
1826 
1827  // if A-copy->X and A-copy->Y where A is not an input, the second copy
1828  // is replaced by an external X-copy->Y
1829 
1830  // ??? BUG: it should be moved after the computation
1831 
1832  // what copies are kept in the dag
1833  hash_table intra_pipe_copies = hash_table_make(hash_pointer, 10);
1834 
1835  FOREACH(dagvtx, w, dag_vertices(d))
1836  {
1837  // skip already to-remove nodes
1838  if (set_belong_p(remove, w))
1839  continue;
1840 
1841  if (dagvtx_is_copy_p(w))
1842  {
1843  vtxcontent c = dagvtx_content(w);
1844  entity target = vtxcontent_out(c);
1845  pips_assert("one output and one input to copy",
1846  target!=entity_undefined && gen_length(vtxcontent_inputs(c))==1);
1847 
1848  entity source = ENTITY(CAR(vtxcontent_inputs(c)));
1849  dagvtx prod = dagvtx_get_producer(d, w, source, 0);
1850 
1851  if (source==target)
1852  {
1853  // A->copy->A??? this should not happen?
1854  set_add_element(remove, remove, w);
1855  }
1856  else if (dagvtx_number(prod)==0)
1857  {
1858  // producer is an input
1859  // fprintf(stderr, "COPY 1 removing %"_intFMT"\n", dagvtx_number(w));
1860  unlink_copy_vertex(d, source, w);
1861  set_add_element(remove, remove, w);
1862  *lbefore =
1863  CONS(statement, freia_copy_image(source, target), *lbefore);
1864  }
1865  else if (gen_in_list_p(prod, dag_outputs(d)))
1866  {
1867  // the producer is an output, which can be copied outside...
1868  // well, it may happen that the copy could be performed by the
1869  // accelerator for free, eg for SPoC one output link would happen
1870  // to be available... so we may really add an operation when
1871  // extracting it. However, this should not be an accelerator call?
1872  unlink_copy_vertex(d, source, w);
1873  set_add_element(remove, remove, w);
1874  *lafter = CONS(statement, freia_copy_image(source, target), *lafter);
1875  }
1876  else // source not an input, but the result of an internal computation
1877  {
1879  {
1880  // ??? hmmm... there is an implicit assumption here that the
1881  // source of the copy will be an output...
1882  unlink_copy_vertex(d, source, w);
1883  set_add_element(remove, remove, w);
1884  *lafter =
1885  CONS(statement, freia_copy_image(source, target), *lafter);
1886  }
1887  else if (hash_defined_p(intra_pipe_copies, source))
1888  {
1889  // the source is already copied
1890  unlink_copy_vertex(d, source, w);
1891  set_add_element(remove, remove, w);
1892  *lafter = CONS(statement,
1893  freia_copy_image((entity) hash_get(intra_pipe_copies, source),
1894  target), *lafter);
1895  }
1896  else // keep first copy
1897  hash_put(intra_pipe_copies, source, target);
1898  }
1899  }
1900  }
1901  hash_table_free(intra_pipe_copies);
1902 
1903  ifdebug(8) {
1904  pips_debug(4, "after FREIA_MOVE_DIRECT_COPIES:\n");
1905  dag_dump(stderr, "move direct copies", d);
1906  // dag_dot_dump_prefix("main", "direct_copies", 0, d);
1907  }
1908  }
1909 
1910  // cleanup dag (argh, beware that the order is not deterministic...)
1911  SET_FOREACH(dagvtx, r, remove)
1912  {
1913  pips_debug(7, "removing vertex %" _intFMT "\n", dagvtx_number(r));
1914 
1915  vtxcontent c = dagvtx_content(r);
1918  dag_remove_vertex(d, r);
1919 
1920  ifdebug(8)
1922 
1923  free_dagvtx(r);
1924  }
1925 
1926  set_free(remove);
1927 
1928  // further check for unused input nodes
1929  // this seems needed because some non determinism in the above cleanup.
1930  list vertices = gen_copy_seq(dag_vertices(d));
1931  FOREACH(dagvtx, v, vertices)
1932  {
1933  if (dagvtx_number(v)==0 && !dagvtx_succs(v))
1934  {
1935  dag_remove_vertex(d, v);
1936  free_dagvtx(v);
1937  }
1938  }
1939  gen_free_list(vertices);
1940 
1941  // show result
1942  ifdebug(6) {
1943  pips_debug(4, "resulting dag:\n");
1944  dag_dump(stderr, "cleaned", d);
1945  // dag_dot_dump_prefix("main", "cleaned", 0, d);
1946  }
1947 
1948  // former output images are either still computed or copies of computed
1949  size_t recount = gen_length(dag_outputs(d)) +
1950  gen_length(*lbefore) + gen_length(*lafter);
1951  pips_assert("right output count after dag optimizations",
1952  dag_output_count==recount);
1953 }
void free_dagvtx(dagvtx p)
#define append(s)
text text_region_no_action(effect reg) input : a region output : a text consisting of several lines o...
Definition: prettyprint.c:77
static bool switch_vertex_to_assign(dagvtx target, dagvtx source)
replace target measure to a copy of source result...
Definition: dag-utils.c:725
static void switch_vertex_to_a_copy(dagvtx target, dagvtx source, list tpreds)
replace target vertex by a copy of source results...
Definition: dag-utils.c:823
static bool list_commuted_p(const list l1, const list l2)
Definition: dag-utils.c:888
static bool dag_simplify(dag d)
apply basic algebraic simplification to dag
Definition: dag-utils.c:1302
static bool commutative_operation_p(const dagvtx v1, const dagvtx v2)
Definition: dag-utils.c:875
static int compatible_reduction_operation(const dagvtx v1, const dagvtx v2)
Definition: dag-utils.c:1395
bool dagvtx_is_measurement_p(const dagvtx v)
returns whether the vertex is an image measurement operation.
Definition: dag-utils.c:623
static void unlink_copy_vertex(dag d, const entity source, dagvtx copy)
"copy" copies "source" image in dag "d".
Definition: dag-utils.c:898
static bool same_operation_p(const dagvtx v1, const dagvtx v2)
Definition: dag-utils.c:866
static bool dag_normalize(dag d)
normalize, that is use less image operators only transformation is: sub_const(i, v) -> add_const(i,...
Definition: dag-utils.c:1351
static void substitute_image_in_statement(dagvtx v, entity source, entity target, bool used)
subtitute produced or used image in the statement of vertex v.
Definition: dag-utils.c:773
static int number_of_copies(list l)
Definition: dag-utils.c:941
static bool all_vertices_are_copies_or_measures_p(const list lv)
Definition: dag-utils.c:931
static bool gen_list_equals_p(const list l1, const list l2)
Definition: dag-utils.c:707
statement freia_copy_image(const entity source, const entity target)
Definition: freia-utils.c:710
void hwac_kill_statement(statement s)
remove contents of statement s.
Definition: freia-utils.c:761
bool same_constant_parameters(const dagvtx v1, const dagvtx v2)
tell whether v1 and v2 point to statements with the same parameters.
Definition: freia-utils.c:1014
@ spoc_type_mes
Definition: freia_spoc.h:179
bool gen_replace_in_list(list l, const void *s, const void *t)
substitute all item s by t in list l
Definition: list.c:634
void * hash_del(hash_table htp, const void *key)
this function removes from the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:439
#define HASH_MAP(k, v, code, ht)
Definition: newgen_hash.h:60
set set_intersection(set, const set, const set)
Definition: set.c:229

References _intFMT, all_vertices_are_copies_or_measures_p(), append, CAR, check_removed(), commutative_operation_p(), compatible_reduction_operation(), CONS, dag_dump(), dag_inputs, dag_normalize(), dag_outputs, dag_remove_vertex(), dag_simplify(), dag_vertex_preds(), dag_vertices, DAGVTX, dagvtx_content, dagvtx_domain, dagvtx_get_producer(), dagvtx_is_copy_p(), dagvtx_is_measurement_p(), dagvtx_number(), dagvtx_succs, ENTITY, entity_undefined, FOREACH, free_dagvtx(), freia_copy_image(), gen_context_recurse, gen_copy_seq(), gen_free_list(), gen_in_list_p(), gen_length(), gen_list_equals_p(), gen_nconc(), gen_nreverse(), gen_remove(), gen_replace_in_list(), gen_true2(), get_bool_property(), hash_defined_p(), hash_del(), hash_get(), HASH_MAP, hash_pointer, hash_put(), hash_table_free(), hash_table_make(), hwac_kill_statement(), ifdebug, int, list_commuted_p(), list_in_set_p(), NIL, number_of_copies(), pips_assert, pips_debug, pstatement_statement, pstatement_statement_p, same_constant_parameters(), same_operation_p(), set_add_element(), set_append_list(), set_belong_p(), set_clear(), set_del_element(), SET_FOREACH, set_free(), set_intersection(), set_make(), set_pointer, set_union(), spoc_type_mes, substitute_image_in_statement(), switch_vertex_to_a_copy(), switch_vertex_to_assign(), unlink_copy_vertex(), vtxcontent_inputs, vtxcontent_optype, vtxcontent_out, and vtxcontent_source.

Referenced by freia_aipo_compile_calls(), freia_mppa_compile_calls(), freia_opencl_compile_calls(), and sc_delimiter().

+ Here is the caller graph for this function:

◆ freia_extract_kernel_vtx()

bool freia_extract_kernel_vtx ( dagvtx  v,
bool  strict,
intptr_t k00,
intptr_t k10,
intptr_t k20,
intptr_t k01,
intptr_t k11,
intptr_t k21,
intptr_t k02,
intptr_t k12,
intptr_t k22 
)

vertex-based version

Parameters
stricttrict
k0000
k1010
k2020
k0101
k1111
k2121
k0202
k1212
k2222

Definition at line 2012 of file freia-utils.c.

2017 {
2018  list largs = freia_get_vertex_params(v);
2019  // for convolution there is one kernel & two args
2020  // pips_assert("one kernel", gen_length(largs)==1);
2021  expression e = EXPRESSION(CAR(largs));
2022  return freia_extract_kernel(e, strict, k00, k10, k20,
2023  k01, k11, k21, k02, k12, k22);
2024 }
static bool freia_extract_kernel(expression e, bool strict, intptr_t *k00, intptr_t *k10, intptr_t *k20, intptr_t *k01, intptr_t *k11, intptr_t *k21, intptr_t *k02, intptr_t *k12, intptr_t *k22)
extract values from a kernel definition return 9 values, expected to be 0/1 elsewhere....
Definition: freia-utils.c:1957

References CAR, EXPRESSION, freia_extract_kernel(), and freia_get_vertex_params().

Referenced by constant_image_p(), copy_image_p(), dagvtx_constant_kernel_p(), erosion_optimization(), mppa_compile_dag(), mppa_helper_args_params(), opencl_compile_mergeable_dag(), opencl_generate_special_kernel_ops(), opencl_merge_and_compile(), sc_kernel_compute_loop(), and sc_print_kernel().

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

◆ freia_extract_params()

list freia_extract_params ( const int  napi,
list  args,
string_buffer  head,
string_buffer  head2,
hash_table  params,
int nparams 
)

returns an allocated expression list of the parameters only (i.e.

do not include the input & output images). params maps variables (if so) to already present parameters names. the extraction function allocs new parameter names if necessary. of expression

Parameters
napiapi
argsrgs
headead
head2ead2
paramsarams
nparamsparams

Definition at line 612 of file freia-utils.c.

619 {
620  const freia_api_t * api = get_freia_api(napi);
621  args = freia_get_params(api, args);
622  list res = NIL;
623  bool merge = get_bool_property("FREIA_MERGE_ARGUMENTS");
624 
625  // important shortcut, taken when ops are switched to "copy" for
626  // some reason, then the next assert would not be consistent.
627  if (api->arg_misc_in==0 && api->arg_misc_out==0)
628  return NIL;
629 
630  pips_assert("number of arguments is okay",
631  gen_length(args)==api->arg_misc_in+api->arg_misc_out);
632 
633  for (unsigned int i = 0; i<api->arg_misc_in; i++)
634  {
635  expression e = EXPRESSION(CAR(args));
636  args = CDR(args);
637 
638  if (params)
639  {
640  // ??? if the expression is a constant,
641  // the parameter could be skipped as well?
642  entity var = expression_to_entity(e);
643  if (merge && !entity_undefined_p(var) && entity_variable_p(var))
644  {
645  if (!hash_defined_p(params, var))
646  {
647  // choose new name
648  string name = get_var("pi", nparams);
649  if (head) sb_cat(head, ",\n ", api->arg_in_types[i], " ", name);
650  if (head2) sb_cat(head2, ", ", api->arg_in_types[i], " ", name);
651  hash_put(params, e, name);
652  res = CONS(expression, copy_expression(e), res);
653  // keep record for the *variable* as well...
654  hash_put(params, var, name);
655  }
656  else
657  {
658  // skip argument, just record its where it is found
659  hash_put(params, e, hash_get(params, var));
660  }
661  }
662  else
663  {
664  // append and record new parameter
665  string name = get_var("pi", nparams);
666  if (head) sb_cat(head, ",\n ", api->arg_in_types[i], " ", name);
667  if (head2) sb_cat(head2, ", ", api->arg_in_types[i], " ", name);
668  hash_put(params, e, name);
669  res = CONS(expression, copy_expression(e), res);
670  }
671  }
672  else
673  res = CONS(expression, copy_expression(e), res);
674  }
675 
676  for (unsigned int i = 0; i<api->arg_misc_out; i++)
677  {
678  expression e = EXPRESSION(CAR(args));
679  args = CDR(args);
680  string name = get_var("po", nparams);
681  if (head) sb_cat(head, ",\n ", api->arg_out_types[i], " ", name);
682  if (head2) sb_cat(head2, ", ", api->arg_out_types[i], " ", name);
683  if (params)
684  hash_put(params, e, name);
685  else
686  free(name);
687  res = CONS(expression, copy_expression(e), res);
688  }
689 
690  return gen_nreverse(res);
691 }
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
struct paramStruct params
static string get_var(string prefix, int *params)
Definition: freia-utils.c:491
list freia_get_params(const freia_api_t *api, list args)
get freia further parameters, skipping image ones
Definition: freia-utils.c:569
#define sb_cat(args...)
Definition: freia.h:42
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140
#define entity_undefined_p(x)
Definition: ri.h:2762
unsigned int arg_misc_in
Definition: freia.h:83
string arg_out_types[3]
Definition: freia.h:85
string arg_in_types[3]
Definition: freia.h:86
unsigned int arg_misc_out
Definition: freia.h:82

References freia_api_t::arg_in_types, freia_api_t::arg_misc_in, freia_api_t::arg_misc_out, freia_api_t::arg_out_types, CAR, CDR, CONS, copy_expression(), entity_undefined_p, entity_variable_p, EXPRESSION, expression_to_entity(), free(), freia_get_params(), gen_length(), gen_nreverse(), get_bool_property(), get_freia_api(), get_var(), hash_defined_p(), hash_get(), hash_put(), NIL, params, pips_assert, and sb_cat.

Referenced by freia_spoc_pipeline(), freia_terapix_call(), opencl_compile_mergeable_dag(), same_constant_parameters(), and sc_get_params_values().

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

◆ freia_get_nth_scalar_param()

expression freia_get_nth_scalar_param ( const  dagvtx,
int  n 
)

Definition at line 589 of file freia-utils.c.

590 {
592 }
list gen_nthcdr(int n, const list lx)
caution: the first item is 0! was: return( (n<=0) ? l : gen_nthcdr( n-1, CDR( l ))) ; if n>gen_length...
Definition: list.c:700

References CAR, EXPRESSION, freia_get_vertex_params(), and gen_nthcdr().

Referenced by constant_image_p(), copy_image_p(), and propagate_constant_image().

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

◆ freia_get_params()

list freia_get_params ( const freia_api_t api,
list  args 
)

get freia further parameters, skipping image ones

Parameters
apipi
argsrgs

Definition at line 569 of file freia-utils.c.

570 {
571  int skip = api->arg_img_in + api->arg_img_out;
572  while (skip--) args = CDR(args);
573  pips_assert("number of scalar args is ok",
574  gen_length(args)==api->arg_misc_in+api->arg_misc_out);
575  return args;
576 }
unsigned int arg_img_out
Definition: freia.h:79
unsigned int arg_img_in
Definition: freia.h:80

References freia_api_t::arg_img_in, freia_api_t::arg_img_out, freia_api_t::arg_misc_in, freia_api_t::arg_misc_out, CDR, gen_length(), and pips_assert.

Referenced by freia_extract_params(), and freia_get_vertex_params().

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

◆ freia_get_vertex_params()

list freia_get_vertex_params ( const  dagvtx)

Definition at line 578 of file freia-utils.c.

579 {
580  const vtxcontent vc = dagvtx_content(v);
581  pips_assert("there is a statement",
584  const call c = freia_statement_to_call(s);
585  const freia_api_t * api = dagvtx_freia_api(v);
586  return freia_get_params(api, call_arguments(c));
587 }
call freia_statement_to_call(const statement s)
return the actual function call from a statement, dealing with assign and returns....
Definition: freia-utils.c:973
#define dagvtx_freia_api(v)
Definition: freia.h:97
#define call_arguments(x)
Definition: ri.h:711

References call_arguments, dagvtx_content, dagvtx_freia_api, freia_get_params(), freia_statement_to_call(), pips_assert, pstatement_statement, pstatement_statement_p, and vtxcontent_source.

Referenced by freia_convolution_width_height(), freia_extract_kernel_vtx(), freia_get_nth_scalar_param(), freia_terapix_call(), gram_param(), has_vtx_dynamic_params(), mppa_compile_dag(), mppa_helper_args_params(), sc_delimiter(), sc_inst(), sc_kernel_specific_agent(), sigmac_params_decl(), spoc_alu_conf(), spoc_measure_conf(), spoc_poc_conf(), spoc_th_conf(), and terapix_gram_management().

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

◆ freia_hack_fix_global_ins_outs()

void freia_hack_fix_global_ins_outs ( dag  dfull,
dag  d 
)

catch some cases of missing outs between splits...

for "freia_scalar_03"... I'm not that sure about the algorithm. This should rely be based on the CHAINS/DG, but the status still seems hopeless, as too many arcs currently kept (FC 08/08/2011)

Parameters
dfullfull dag
Parameters
dfullfull

Definition at line 2166 of file dag-utils.c.

2167 {
2168  // cleanup inputs?
2169  // cleanup outputs
2170  FOREACH(dagvtx, v, dag_vertices(d))
2171  {
2172  // skip input nodes
2173  if (dagvtx_number(v)==0)
2174  continue;
2175 
2176  dagvtx twin = find_twin_vertex(dfull, v);
2177  if (// the vertex was an output node in the full dag
2178  gen_in_list_p(twin, dag_outputs(dfull)) ||
2179  // OR there were more successors in the full dag
2181  {
2182  pips_debug(4, "adding %" _intFMT " as output\n", dagvtx_number(v));
2183  dag_outputs(d) = gen_once(v, dag_outputs(d));
2184  }
2185  }
2186 }
static dagvtx find_twin_vertex(dag d, dagvtx target)
Definition: dag-utils.c:2148
list gen_once(const void *vo, list l)
Prepend an item to a list only if it is not already in the list.
Definition: list.c:722

References _intFMT, dag_outputs, dag_vertices, dagvtx_number(), dagvtx_succs, find_twin_vertex(), FOREACH, gen_in_list_p(), gen_length(), gen_once(), and pips_debug.

Referenced by compile_this_list(), dag_split_connected_components(), dag_split_on_scalars(), and opencl_merge_and_compile().

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

◆ freia_image_variable_p()

bool freia_image_variable_p ( const  entity)

rather approximative?

Parameters
entityar

Definition at line 768 of file freia-utils.c.

769 {
770  bool is_image = false;
771  if (var && var!=entity_undefined &&
772  entity_variable_p(var) && entity_pointer_p(var))
773  {
774  type t = ultimate_type(entity_type(var));
776  if (basic_pointer_p(b))
777  {
778  t = basic_pointer(b);
780  is_image = basic_typedef_p(b) &&
782  "$" FREIA_IMAGE_TYPE);
783  }
784  }
785 
786  pips_debug(8, "%s is%s an image\n", entity_name(var), is_image? "": " not");
787  return is_image;
788 }
#define FREIA_IMAGE_TYPE
Definition: freia.h:46
bool entity_pointer_p(entity e)
Definition: entity.c:745
type ultimate_type(type)
Definition: type.c:3466
#define basic_pointer(x)
Definition: ri.h:637
#define basic_typedef_p(x)
Definition: ri.h:641
#define type_variable(x)
Definition: ri.h:2949
#define basic_pointer_p(x)
Definition: ri.h:635
#define basic_typedef(x)
Definition: ri.h:643
#define variable_basic(x)
Definition: ri.h:3120

References basic_pointer, basic_pointer_p, basic_typedef, basic_typedef_p, entity_local_name(), entity_name, entity_pointer_p(), entity_type, entity_undefined, entity_variable_p, FREIA_IMAGE_TYPE, pips_debug, same_string_p, type_variable, ultimate_type(), and variable_basic.

Referenced by check_ref(), collect_images(), fis_call_flt(), freia_compute_output_images(), freia_shuffle_move_forward(), freia_some_effects_on_images(), image_ref_flt(), oi_call_rwt(), ref_count_rwt(), seq_rwt(), and set_add_scalars().

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

◆ freia_init_dep_cache()

void freia_init_dep_cache ( void  )

Definition at line 909 of file freia-utils.c.

910 {
911  pips_assert("dep_cache is NULL", !dep_cache);
913 }

References dep_cache, hash_pointer, hash_table_make(), and pips_assert.

Referenced by freia_compile().

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

◆ freia_insert_added_stats()

void freia_insert_added_stats ( list  ls,
list  stats,
bool  before 
)

insert statements to actual code sequence in "ls" BEWARE that ls is assumed to be in reverse order...

Parameters
lss
statstats
beforeefore

Definition at line 1185 of file freia-utils.c.

1186 {
1187  if (stats)
1188  {
1189  statement sref = find_aipo_statement(ls, before);
1190  pips_debug(8, "sref for %s is %" _intFMT "\n",
1191  before? "before": "after", statement_number(sref));
1192  instruction iref = statement_instruction(sref);
1193  statement newstat = instruction_to_statement(iref);
1194  // transfer comments and some cleanup...
1195  statement_comments(newstat) = statement_comments(sref);
1198  // pretty ugly because return must be handled especially...
1199  // ??? not sure that it is ok if !before?
1200  if (instruction_call_p(iref) &&
1202  {
1203  call c = instruction_call(iref);
1205  {
1206  // must split return...
1207  pips_internal_error("return splitting not implemented yet...");
1208  }
1209  else
1210  {
1211  if (before)
1212  stats = gen_nconc(stats, CONS(statement, newstat, NIL));
1213  else
1214  // ???
1215  stats = CONS(statement, newstat, stats);
1216  }
1217  }
1218  else
1219  {
1220  if (before)
1221  stats = CONS(statement, newstat, stats);
1222  else
1223  stats = gen_nconc(stats, CONS(statement, newstat, NIL));
1224  }
1225  statement_instruction(sref) =
1227  }
1228 }
instruction make_instruction_sequence(sequence _field_)
Definition: ri.c:1169
static statement find_aipo_statement(list ls, bool before)
Definition: freia-utils.c:1147
statement instruction_to_statement(instruction)
Build a statement from a give instruction.
Definition: statement.c:597
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define string_undefined
Definition: newgen_types.h:40
#define STATEMENT_NUMBER_UNDEFINED
default values
#define ENTITY_C_RETURN_P(e)
#define call_function(x)
Definition: ri.h:709
#define instruction_call_p(x)
Definition: ri.h:1527
#define statement_instruction(x)
Definition: ri.h:2458
#define statement_comments(x)
Definition: ri.h:2456
#define instruction_call(x)
Definition: ri.h:1529

References _intFMT, call_arguments, call_function, CAR, CONS, ENTITY_C_RETURN_P, EXPRESSION, expression_constant_p(), find_aipo_statement(), gen_nconc(), instruction_call, instruction_call_p, instruction_to_statement(), make_instruction_sequence(), make_sequence(), NIL, pips_debug, pips_internal_error, statement_comments, statement_instruction, statement_number, STATEMENT_NUMBER_UNDEFINED, and string_undefined.

Referenced by freia_aipo_compile_calls(), freia_mppa_compile_calls(), freia_opencl_compile_calls(), and sc_delimiter().

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

◆ freia_is_transpose_call()

bool freia_is_transpose_call ( statement  s)

Detect a call to a se transposition function and transpose the arguments.

The expected function should have the following signature transpose_func(int kernelOut[9], const int kernelIn[9], ...)

Definition at line 499 of file freia.c.

499  {
500 
501  if (statement_call_p(s)) {
502  call c = statement_call(s);
503  if (c) {
504  entity called = call_function(c);
505 
506  // extract transposition calls
507  if (same_string_p(entity_local_name(called),
508  get_string_property("FREIA_TRANSPOSE_KERNEL_FUNC"))) {
509 
510  list args = call_arguments(c);
511  pips_assert("an expected transposition function should have at least "
512  "two arguments",
513  gen_length(args) >= 2);
514 
515  // get the argument entities
517  entity trse = expression_to_entity(EXPRESSION(CAR(args)));
518 
520  // get the expression value of the initial structuring element
522  // effectively transpose structuring element
523  expression trseval = freia_transpose_kernel(seval);
524 
525  // set the value of the transposed structuring element
526  set_entity_initial(trse, trseval);
527 
528  pips_debug(9, "%s: out %s, in %s\n", entity_local_name(called),
529  expression_to_string(trseval),
530  expression_to_string(seval));
531  }
532 
533  return true;
534  }
535  }
536  }
537  return false;
538 }
void set_entity_initial(entity, expression)
Be careful if the initial value has already been set.
Definition: util.c:3469
char * get_string_property(const char *)
expression freia_transpose_kernel(const expression se)
Transpose a structuring element expression.
Definition: freia.c:479
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
bool statement_call_p(statement)
Definition: statement.c:364
string expression_to_string(expression e)
Definition: expression.c:77
#define value_expression_p(x)
Definition: ri.h:3080
#define value_expression(x)
Definition: ri.h:3082
#define entity_initial(x)
Definition: ri.h:2796

References call_arguments, call_function, CAR, CDR, entity_initial, entity_local_name(), EXPRESSION, expression_to_entity(), expression_to_string(), freia_transpose_kernel(), gen_length(), get_string_property(), pips_assert, pips_debug, same_string_p, set_entity_initial(), statement_call(), statement_call_p(), value_expression, and value_expression_p.

Referenced by fsi_stmt_flt().

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

◆ freia_max_pixel_value()

int freia_max_pixel_value ( void  )

Definition at line 594 of file freia-utils.c.

595 {
596  int bpp = FREIA_DEFAULT_BPP;
597  switch (bpp)
598  {
599  case 8: return 0xff;
600  case 16: return 0xffff;
601  default:
602  pips_user_error("expecting 8 or 16 for pixel size, got %d", bpp);
603  return 0;
604  }
605 }
#define FREIA_DEFAULT_BPP
Definition: freia.h:53

References FREIA_DEFAULT_BPP, and pips_user_error.

Referenced by constant_image_p(), and copy_image_p().

+ Here is the caller graph for this function:

◆ freia_memory_management_statement()

statement freia_memory_management_statement ( entity  image,
const hash_table  occs,
bool  alloc 
)
Returns
statement where image is allocated/deallocated maybe I should build another hash_table for this purpose?
Parameters
imagemage
occsccs
alloclloc

Definition at line 2586 of file dag-utils.c.

2588 {
2589  pips_debug(8, "look for %s statement for %s\n",
2590  alloc? "allocation": "deallocation", entity_name(image));
2591 
2592  if (hash_defined_p(occs, image))
2593  {
2594  SET_FOREACH(statement, s, (set) hash_get(occs, image))
2595  {
2596  // it may already have been switched to a sequence by a prior insert...
2597  // ??? it is unclear why I encounter nested sequences
2598  while (statement_sequence_p(s))
2600 
2601  // fprintf(stderr, "statement %"_intFMT"?\n", statement_number(s));
2602  if (alloc && is_freia_alloc(s))
2603  {
2604  call c = statement_call(s);
2605  pips_assert("must be an assignment", ENTITY_ASSIGN_P(call_function(c)));
2606  entity var;
2609  if (var==image) return s;
2610  }
2611  else if (!alloc && is_freia_dealloc(s))
2612  {
2613  call c = statement_call(s);
2614  entity var;
2617  if (var==image) return s;
2618  }
2619  }
2620  }
2621  return NULL;
2622 }
char * alloc(int size)
ALLOC is an "iron-clad" version of malloc(3).
Definition: build.c:501
static bool image_ref_flt(reference r, entity *image)
Definition: dag-utils.c:2547
bool is_freia_dealloc(const statement s)
Definition: freia-utils.c:1007
bool is_freia_alloc(const statement s)
Definition: freia-utils.c:1002
void gen_null2(__attribute__((unused)) void *u1, __attribute__((unused)) void *u2)
idem with 2 args, to please overpeaky compiler checks
Definition: genClib.c:2758

References alloc(), call_arguments, call_function, CAR, ENTITY_ASSIGN_P, entity_name, EXPRESSION, gen_context_recurse, gen_null2(), hash_defined_p(), hash_get(), image_ref_flt(), is_freia_alloc(), is_freia_dealloc(), pips_assert, pips_debug, reference_domain, sequence_statements, SET_FOREACH, STATEMENT, statement_call(), statement_sequence(), and statement_sequence_p().

Referenced by freia_allocate_new_images_if_needed(), and new_local_image_variable().

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

◆ freia_migrate_statements()

void freia_migrate_statements ( sequence  sq,
const  set,
const  set 
)
Parameters
sqq
settats
setefore

Definition at line 1905 of file freia-utils.c.

1906 {
1907  ifdebug(4) {
1908  pips_debug(4, "migrating %d statements in %p\n", set_size(stats), sq);
1909  set_fprint(stderr, "stats", stats, (gen_string_func_t) stat_nb);
1910  set_fprint(stderr, "before", before, (gen_string_func_t) stat_nb);
1911  }
1912 
1913  // nothing to do
1914  if (sq==NULL)
1915  {
1916  pips_assert("nothing to migrate", set_size(stats)<=1);
1917  return;
1918  }
1919 
1920  // nothing to do either
1921  if (set_size(stats)==0)
1922  return;
1923 
1924  // build before/in/end statement lists in reverse order
1925  list lbefore = NIL, lin = NIL, lend = NIL;
1927  {
1928  if (set_belong_p(stats, s))
1929  lin = CONS(statement, s, lin);
1930  else
1931  {
1932  if (before && set_belong_p(before, s))
1933  lbefore = CONS(statement, s, lbefore);
1934  else
1935  {
1936  if (lin)
1937  lend = CONS(statement, s, lend);
1938  else
1939  lbefore = CONS(statement, s, lbefore);
1940  }
1941  }
1942  }
1943 
1944  // check consistency
1945  pips_assert("all statements seen", set_size(stats)==(int) gen_length(lin));
1946 
1947  // update sequence
1949  lin = gen_nconc(gen_nreverse(lin), gen_nreverse(lend));
1950  sequence_statements(sq) = gen_nconc(gen_nreverse(lbefore), lin);
1951 }
static string stat_nb(statement s)
Definition: freia-utils.c:1893
static int lend()
return 1 for 'end' alone on card (up to col.
Definition: split_file.c:242

References CONS, FOREACH, gen_free_list(), gen_length(), gen_nconc(), gen_nreverse(), ifdebug, lend(), NIL, pips_assert, pips_debug, sequence_statements, set_belong_p(), set_fprint(), set_size(), and stat_nb().

Referenced by freia_mppa_compile_calls(), freia_opencl_compile_calls(), migrate_statements(), and sc_delimiter().

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

◆ freia_mppa_compile_calls()

list freia_mppa_compile_calls ( string  ,
dag  ,
sequence  ,
list  ,
const  hash_table,
hash_table  ,
const  set,
FILE *  ,
set  ,
int   
)

freia_mppa.c

Parameters
hash_tableccs
setutput_images

◆ freia_mppa_compiler()

bool freia_mppa_compiler ( const  string)
Parameters
stringodule

Definition at line 149 of file hardware_accelerator.c.

149  {
150  return freia_compiler(module, "mppa");
151 }

References freia_compiler(), and module.

+ Here is the call graph for this function:

◆ freia_ok()

call freia_ok ( void  )

build all is well freia constant

Definition at line 695 of file freia-utils.c.

696 {
697  // how to build the "FREIA_OK" enum value constant?
699 }

References local_name_to_top_level_entity(), make_call(), and NIL.

Referenced by freia_cleanup_status(), hwac_kill_statement(), mppa_call_helper(), and sc_delimiter().

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

◆ freia_opencl_compile_calls()

list freia_opencl_compile_calls ( string  module,
dag  fulld,
sequence  sq,
list  ls,
const  hash_table,
hash_table  exchanges,
const  set,
FILE *  helper_file,
set  helpers,
int  number,
hash_table  signatures 
)

freia_opencl.c

Parameters
moduleodule
fulldulld
sqq
lss
hash_tableccs
exchangesxchanges
setutput_images
helper_fileelper_file
helperselpers
numberumber
signaturesignatures

Definition at line 1371 of file freia_opencl.c.

1383 {
1384  pips_debug(3, "considering %d statements\n", (int) gen_length(ls));
1385  pips_assert("some statements", ls);
1386 
1387  int n_op_init, n_op_init_copies;
1388  freia_aipo_count(fulld, &n_op_init, &n_op_init_copies);
1389 
1390  // must have distinct images in the graph for optimizations
1392  list new_images = dag_fix_image_reuse(fulld, init, occs);
1393 
1394  list added_before = NIL, added_after = NIL;
1395  freia_dag_optimize(fulld, exchanges, &added_before, &added_after);
1396 
1397  int n_op_opt, n_op_opt_copies;
1398  freia_aipo_count(fulld, &n_op_opt, &n_op_opt_copies);
1399 
1400  fprintf(helper_file,
1401  "\n"
1402  "// dag %d: %d ops and %d copies, "
1403  "optimized to %d ops and %d+%d+%d copies\n",
1404  number, n_op_init, n_op_init_copies,
1405  n_op_opt, n_op_opt_copies,
1406  (int) gen_length(added_before), (int) gen_length(added_after));
1407 
1408  // opencl file
1409  string opencl_file = get_opencl_file_name(module);
1410  FILE * opencl;
1411  if (file_readable_p(opencl_file))
1412  opencl = safe_fopen(opencl_file, "a");
1413  else
1414  {
1415  opencl = safe_fopen(opencl_file, "w");
1416  fprintf(opencl,
1418  "// generated OpenCL kernels for function %s\n", module);
1419  }
1420  fprintf(opencl, "\n" "// opencl for dag %d\n", number);
1421 
1422  // dump final optimised dag
1423  dag_dot_dump_prefix(module, "dag_cleaned_", number, fulld,
1424  added_before, added_after);
1425 
1426  string fname_fulldag = strdup(cat(module, "_opencl", HELPER, i2a(number)));
1427 
1428  list ld =
1431  NULL, output_images);
1432 
1433  pips_debug(3, "dag initial split in %d dags\n", (int) gen_length(ld));
1434 
1435  int n_split = 0;
1436 
1438  {
1439  set stats = set_make(set_pointer), dones = set_make(set_pointer);
1440  FOREACH(dag, d, ld)
1441  {
1442  if (dag_no_image_operation(d))
1443  continue;
1444 
1445  // fix statements connexity
1446  dag_statements(stats, d);
1447  freia_migrate_statements(sq, stats, dones);
1448  set_union(dones, dones, stats);
1449 
1450  opencl_merge_and_compile(module, sq, ls, d, fname_fulldag, n_split,
1451  fulld, output_images, helper_file, opencl,
1452  helpers, signatures);
1453 
1454  n_split++;
1455  }
1456  set_free(stats);
1457  set_free(dones);
1458  }
1459  // else, do nothing, this is basically like AIPO
1460 
1461  // now may put actual allocations, which messes up statement numbers
1462  list reals =
1463  freia_allocate_new_images_if_needed(ls, new_images, occs, init, signatures);
1464 
1465  // hmmm... is this too late?
1466  freia_insert_added_stats(ls, added_before, true);
1467  added_before = NIL;
1468  freia_insert_added_stats(ls, added_after, false);
1469  added_after = NIL;
1470 
1471  // cleanup
1472  gen_free_list(new_images);
1474  safe_fclose(opencl, opencl_file);
1475  free(opencl_file);
1476 
1477  return reals;
1478 }
bool dag_no_image_operation(dag d)
tell whether we have something to do with images ??? hmmm...
Definition: dag-utils.c:2500
list dag_split_on_scalars(const dag initial, bool(*alone_only)(const dagvtx), dagvtx(*choose_vertex)(const list, bool), gen_cmp_func_t priority, void(*priority_update)(const dag), const set output_images)
split a dag on scalar dependencies only, with a greedy heuristics.
Definition: dag-utils.c:2823
void dag_statements(set stats, const dag d)
build the set of actual statements in d
Definition: dag-utils.c:64
void freia_migrate_statements(sequence sq, const set stats, const set before)
Definition: freia-utils.c:1905
int freia_aipo_count(dag d, int *pa, int *pc)
Definition: freia-utils.c:1823
#define HELPER
Definition: freia.h:38
static string get_opencl_file_name(string func_name)
Definition: freia_opencl.c:47
static dagvtx choose_opencl_vertex(const list lv, bool started)
choose a vertex, avoiding other stuff if the list is started
Definition: freia_opencl.c:82
static int dagvtx_opencl_priority(const dagvtx *pv1, const dagvtx *pv2)
qsort helper: return -1 for v1 before v2
Definition: freia_opencl.c:68
static void opencl_merge_and_compile(string module, sequence sq, list ls, dag d, string fname_fulldag, int n_split, const dag fulld, const set output_images, FILE *helper_file, FILE *opencl, set helpers, hash_table signatures)
extract subdags of merged operations and compile them
#define opencl_merge_prop
Definition: freia_opencl.h:33
#define FREIA_OPENCL_CL_INCLUDES
Definition: freia_opencl.h:48

References cat, choose_opencl_vertex(), dag_dot_dump_prefix(), dag_fix_image_reuse(), dag_no_image_operation(), dag_split_on_scalars(), dag_statements(), dagvtx_opencl_priority(), dagvtx_other_stuff_p(), file_readable_p(), FOREACH, fprintf(), free(), freia_aipo_count(), freia_allocate_new_images_if_needed(), freia_dag_optimize(), freia_insert_added_stats(), freia_migrate_statements(), FREIA_OPENCL_CL_INCLUDES, gen_free_list(), gen_length(), get_bool_property(), get_opencl_file_name(), hash_pointer, hash_table_free(), hash_table_make(), HELPER, i2a(), init, module, NIL, opencl_merge_and_compile(), opencl_merge_prop, pips_assert, pips_debug, safe_fclose(), safe_fopen(), set_free(), set_make(), set_pointer, set_union(), and strdup().

Referenced by freia_compile().

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

◆ freia_opencl_compiler()

bool freia_opencl_compiler ( const  string)
Parameters
stringodule

Definition at line 139 of file hardware_accelerator.c.

140 {
141  return freia_compiler(module, "opencl");
142 }

References freia_compiler(), and module.

+ Here is the call graph for this function:

◆ freia_remove_scalar_ww_deps()

bool freia_remove_scalar_ww_deps ( const  string)
Parameters
stringodule

Definition at line 430 of file freia_transformations.c.

431 {
432  debug_on("PIPS_HWAC_DEBUG_LEVEL");
433  pips_debug(1, "considering module %s\n", module);
434 
435  // else do the stuff
437  (statement) db_get_memory_resource(DBR_CODE, module, true);
440 
441  // do the job
442  bool changed = false;
443  gen_context_recurse(mod_stat, &changed,
445 
446  // update database if changed
447  if (changed)
448  // stmt_renumber(mod_stat); module_reorder(mod_stat);
450 
453  debug_off();
454  return true;
455 }
struct _newgen_struct_statement_ * statement
Definition: cloning.h:21
static void sww_seq_rwt(const sequence sq, bool *changed)
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
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
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, gen_context_recurse, gen_true2(), mod_stat, module, module_name_to_entity(), pips_debug, reset_current_module_entity(), reset_current_module_statement(), sequence_domain, set_current_module_entity(), set_current_module_statement(), and sww_seq_rwt().

+ Here is the call graph for this function:

◆ freia_scalar_rw_dep()

bool freia_scalar_rw_dep ( const  statement,
const  statement,
list vars 
)
Parameters
varsars

Definition at line 929 of file freia-utils.c.

930 {
931  pips_assert("dep_cache is not NULL", dep_cache);
932 
933  // short circuit
934  if (s==t || !s || !t) return false;
935 
936  // first level
937  if (!hash_defined_p(dep_cache, s))
940 
941  // second level
942  if (!hash_defined_p(h, t)) {
943  list l = NIL;
944  real_freia_scalar_rw_dep(s, t, &l);
945  hash_put(h, t, l);
946  }
947 
948  list l = (list) hash_get(h, t);
949  if (vars) *vars = gen_copy_seq(l);
950  return l!=NIL;
951 }
static bool real_freia_scalar_rw_dep(const statement s, const statement t, list *vars)
is there a simple scalar (no image) rw dependency from s to t? WW deps are ignored....
Definition: freia-utils.c:881
struct __hash_table * hash_table
Define hash_table structure which is hidden.
Definition: newgen_hash.h:43
struct cons * list
Definition: newgen_types.h:106

References dep_cache, gen_copy_seq(), hash_defined_p(), hash_get(), hash_pointer, hash_put(), hash_table_make(), NIL, pips_assert, and real_freia_scalar_rw_dep().

Referenced by all_previous_stats_with_deps_are_computed(), any_scalar_dep(), and dagvtx_dot().

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

◆ freia_shuffle_move_forward()

void freia_shuffle_move_forward ( statement  s)

Definition at line 876 of file freia_transformations.c.

877 {
878  shuffle_context ctx = { 0, 0, NIL, NULL };
879  // forward substitude simple image assignments
881  // remove image assignments that are not used
882  // TODO ??? initializations...
883  // count image read references
884  hash_table reads = hash_table_make(hash_pointer, 100); // entity -> _int
885  gen_context_multi_recurse(s, reads,
888  NULL);
889  // cleanup assignments of unused images
890  FOREACH(statement, sa, ctx.assigns)
891  {
892  // be safe
893  pips_assert(statement_call_p(sa), "statement is a call");
894  call c = statement_call(sa);
895  pips_assert(ENTITY_ASSIGN_P(call_function(c)), "call is assign");
896  list args = call_arguments(c);
897  pips_assert(gen_length(args) == 2, "2 args to assign");
898  expression e1 = EXPRESSION(CAR(args));
899  pips_assert(expression_reference_p(e1), "expr is reference");
901  entity img = reference_variable(r);
902  pips_assert(reference_indices(r) == NIL, "no array reference");
903  pips_assert(freia_image_variable_p(img), "reference an image");
904 
905  // cleanup unused images
906  if (!hash_defined_p(reads, img))
907  {
908  // remove assignment of unused image pointer
911  // coldly cleanup corresponding effects... (free effects not needed?)
914  // ??? what about proper effects?
915  // stats
916  ctx.removed ++;
917  }
918  }
919  hash_table_free(reads), reads = NULL;
920 
921  // be verbose because I'm not sure of the pass
922  if (ctx.changed != 0 || ctx.removed != 0)
923  pips_user_warning("%d subsitution(s) and %d assignment(s) removed",
924  ctx.changed, ctx.removed);
925 
926  gen_free_list(ctx.assigns), ctx.assigns = NIL;
927 }
void free_instruction(instruction p)
Definition: ri.c:1118
effects delete_cumulated_rw_effects(statement)
void store_cumulated_rw_effects_list(statement, list)
static bool call_count_flt(call c, _UNUSED_ hash_table counts)
static void ref_count_rwt(reference r, hash_table counts)
static void seq_rwt(sequence sq, shuffle_context *ctx)
instruction make_continue_instruction()
Creates a CONTINUE instruction, that is the FORTRAN nop, the ";" in C or the "pass" in Python for exa...
Definition: instruction.c:79
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
#define reference_variable(x)
Definition: ri.h:2326
#define reference_indices(x)
Definition: ri.h:2328

References shuffle_context::assigns, call_arguments, call_count_flt(), call_domain, call_function, CAR, shuffle_context::changed, delete_cumulated_rw_effects(), ENTITY_ASSIGN_P, EXPRESSION, expression_reference(), expression_reference_p(), FOREACH, free_instruction(), freia_image_variable_p(), gen_context_multi_recurse(), gen_context_recurse, gen_free_list(), gen_length(), gen_null2(), gen_true2(), hash_defined_p(), hash_pointer, hash_table_free(), hash_table_make(), make_continue_instruction(), NIL, pips_assert, pips_user_warning, ref_count_rwt(), reference_domain, reference_indices, reference_variable, shuffle_context::removed, seq_rwt(), sequence_domain, statement_call(), statement_call_p(), statement_instruction, and store_cumulated_rw_effects_list().

Referenced by freia_compile().

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

◆ freia_sigmac_compile_calls()

list freia_sigmac_compile_calls ( string  ,
dag  ,
sequence  ,
list  ,
const  hash_table,
hash_table  ,
const  set,
FILE *  ,
set  ,
int  ,
int   
)

freia_sigmac.c

Parameters
hash_tableccs
setutput_images

Referenced by freia_compile(), and sc_delimiter().

+ Here is the caller graph for this function:

◆ freia_sigmac_compiler()

bool freia_sigmac_compiler ( const  string)
Parameters
stringodule

Definition at line 144 of file hardware_accelerator.c.

145 {
146  return freia_compiler(module, "sigmac");
147 }

References freia_compiler(), and module.

+ Here is the call graph for this function:

◆ freia_some_effects_on_images()

bool freia_some_effects_on_images ( statement  s)

freia.c

freia.c

if so, it may be included somehow in the pipeline and just skipped, provided stat scalar dependencies are taken care of.

Definition at line 402 of file freia.c.

403 {
404  int img_effect = false;
406  FOREACH(effect, e, cumu)
407  {
409  {
410  img_effect = true;
411  break;
412  }
413  }
414  return img_effect;
415 }
effects load_cumulated_rw_effects(statement)
#define effect_variable(e)
For COMPATIBILITY purpose only - DO NOT USE anymore.
#define effects_effects(x)
Definition: effects.h:710

References effect_variable, effects_effects, FOREACH, freia_image_variable_p(), and load_cumulated_rw_effects().

Referenced by fsi_seq_flt().

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

◆ freia_spoc_compile_calls()

list freia_spoc_compile_calls ( string  module,
dag  fulld,
sequence  sq,
list  ls,
const hash_table  occs,
hash_table  exchanges,
const set  output_images,
FILE *  helper_file,
set  helpers,
int  number 
)

freia_spoc.c

freia_spoc.c

Parameters
module
lslist of statements for the dag (in reverse order)
helperoutput file
helperscreated functions
numbercurrent helper dag count
Returns
list of intermediate images to allocate

of expression

Parameters
moduleodule
fulldulld
sqq
lsof statements
occsccs
exchangesxchanges
output_imagesutput_images
helper_fileelper_file
helperselpers
numberumber

Definition at line 2246 of file freia_spoc.c.

2257 {
2258  // build DAG for ls
2259  pips_debug(3, "considering %d statements\n", (int) gen_length(ls));
2260  pips_assert("some statements", ls);
2261 
2262  int n_op_init, n_op_init_copies;
2263  freia_aipo_count(fulld, &n_op_init, &n_op_init_copies);
2264 
2265  // must have distinct images...
2267  list new_images = dag_fix_image_reuse(fulld, init, occs);
2268 
2269  list added_before = NIL, added_after = NIL;
2270  freia_dag_optimize(fulld, exchanges, &added_before, &added_after);
2271 
2272  // remove copies and duplicates if possible...
2273  // ??? maybe there should be an underlying transitive closure? not sure.
2274  int n_op_opt, n_op_opt_copies;
2275  freia_aipo_count(fulld, &n_op_opt, &n_op_opt_copies);
2276 
2277  fprintf(helper_file,
2278  "\n"
2279  "// dag %d: %d ops and %d copies, "
2280  "optimized to %d ops and %d+%d+%d copies\n",
2281  number, n_op_init, n_op_init_copies,
2282  n_op_opt, n_op_opt_copies,
2283  (int) gen_length(added_before), (int) gen_length(added_after));
2284 
2285  // dump final dag
2286  dag_dot_dump_prefix(module, "dag_cleaned_", number, fulld,
2287  added_before, added_after);
2288 
2289  string fname_fulldag = strdup(cat(module, "_spoc", HELPER, i2a(number)));
2290 
2291  // split dag in one-pipe dags.
2292  list ld = split_dag(fulld, output_images);
2293 
2294  // nothing to do!
2295  // it would have been interesting not to create thehelper file in this case.
2296  // if (ld==NIL) return;
2297 
2298  FOREACH(dag, dfix, ld)
2299  freia_hack_fix_global_ins_outs(fulld, dfix);
2300 
2301  // globally remaining statements
2302  set global_remainings = set_make(set_pointer);
2303  set_assign_list(global_remainings, ls);
2304 
2306 
2307  int n_spoc_calls = 0;
2308  int n_pipes = 0;
2309  int stnb = -1;
2310 
2311  set stats = set_make(set_pointer), dones = set_make(set_pointer);
2312 
2313  FOREACH(dag, d, ld)
2314  {
2315  // skip non implemented stuff
2316  if (dag_spoc_not_implemented(d))
2317  continue;
2318 
2319  // fix connectivity
2320  dag_statements(stats, d);
2321  freia_migrate_statements(sq, stats, dones);
2322  set_union(dones, dones, stats);
2323 
2324  set remainings = set_make(set_pointer);
2326  // remove special inputs nodes
2327  // FOREACH(dagvtx, inp, dag_inputs(d))
2328  // set_del_element(remainings, remainings, inp);
2329 
2330  // generate a new helper function for dag d
2331  string fname_dag = strdup(cat(fname_fulldag, "_", i2a(n_pipes++)));
2332 
2333  ifdebug(4) dag_dump(stderr, "d", d);
2334  dag_dot_dump(module, fname_dag, d, NIL, NIL);
2335 
2336  // one logical pipeline may be split because of overflow
2337  // the dag is updated to reflect that as a code generation side effect
2338  int split = 0;
2339  while (dag_vertices(d))
2340  {
2341  // fix internal ins/outs, that are tempered with by split & overflows
2343 
2344  ifdebug(6) {
2345  pips_debug(4, "dag for split %d\n", split);
2346  dag_dump(stderr, "d", d);
2347  }
2348 
2349  string fname_split = strdup(cat(fname_dag, "_", i2a(split++)));
2350  list /* of expression */ lparams = NIL;
2351 
2352  _int nout = freia_spoc_pipeline(module, fname_split, code, d, &lparams,
2353  output_images);
2354  stnb = freia_substitute_by_helper_call(d, global_remainings, remainings,
2355  ls, fname_split, lparams, helpers, stnb);
2356  // record (simple) signature
2357  hash_put(init, local_name_to_top_level_entity(fname_split), (void*) nout);
2358  free(fname_split), fname_split = NULL;
2359  }
2360 
2361  n_spoc_calls += split;
2362  fprintf(helper_file, "// split %d: %d cut%s\n",
2363  n_pipes-1, split, split>1? "s": "");
2364 
2365  set_free(remainings), remainings = NULL;
2366  free(fname_dag), fname_dag = NULL;
2367  }
2368 
2369  set_free(stats);
2370  set_free(dones);
2371 
2372  fprintf(helper_file, "// # SPOC calls: %d\n", n_spoc_calls);
2373 
2374  freia_insert_added_stats(ls, added_before, true);
2375  added_before = NIL;
2376 
2377  freia_insert_added_stats(ls, added_after, false);
2378  added_after = NIL;
2379 
2380  string_buffer_to_file(code, helper_file);
2382 
2383  // cleanup
2384  set_free(global_remainings), global_remainings = NULL;
2385  free(fname_fulldag), fname_fulldag = NULL;
2386  FOREACH(dag, dc, ld)
2387  free_dag(dc);
2388  gen_free_list(ld);
2389 
2390  // deal with new images
2391  list real_new_images =
2392  freia_allocate_new_images_if_needed(ls, new_images, occs, init, init);
2393  gen_free_list(new_images);
2395  return real_new_images;
2396 }
void set_append_vertex_statements(set s, list lv)
Definition: dag-utils.c:2385
int freia_substitute_by_helper_call(dag d, set global_remainings, set remainings, list ls, const string function_name, list lparams, set helpers, int preceeding)
substitute those statement in ls that are in dag d and accelerated by a call to function_name(lparams...
Definition: freia-utils.c:1073
static _int freia_spoc_pipeline(string module, string helper, string_buffer code, dag dpipe, list *lparams, const set output_images)
generate a SPoC pipeline from a single DAG for module.
Definition: freia_spoc.c:1241
static bool dag_spoc_not_implemented(dag d)
does this dag contains a spoc non implemented operation?
Definition: freia_spoc.c:2005
static list split_dag(dag initial, const set output_images)
split dag dall into a list of pipelinable dags which must be processed in that order (?...
Definition: freia_spoc.c:2103
void string_buffer_to_file(const string_buffer, FILE *)
put string buffer into file.
void string_buffer_free(string_buffer *)
free string buffer structure, also free string contents according to the dup field
Definition: string_buffer.c:82
string_buffer string_buffer_make(bool dup)
allocate a new string buffer
Definition: string_buffer.c:58
intptr_t _int
_INT
Definition: newgen_types.h:53
internally defined structure.
Definition: string_buffer.c:47

Referenced by freia_compile().

+ Here is the caller graph for this function:

◆ freia_spoc_compiler()

bool freia_spoc_compiler ( const  string)

Warning! Do not modify this file that is automatically generated!

Modify src/Libs/hwac/hwac-local.h instead, to add your own modifications. header file built by cproto hwac-local.h cproto-generated files hardware_accelerator.c

Parameters
stringodule

Definition at line 124 of file hardware_accelerator.c.

125 {
126  return freia_compiler(module, "spoc");
127 }

References freia_compiler(), and module.

+ Here is the call graph for this function:

◆ freia_spoc_set_operation()

void freia_spoc_set_operation ( const freia_api_t api,
_int type,
_int id 
)

??? beurk: I keep the operation as two ints for code regeneration.

Parameters
apipi
typeype
idd

Definition at line 545 of file freia-utils.c.

546 {
547  pips_assert("no type set", *type == spoc_type_nop);
548 
549  // set type which is enough for staging?
550  if (api->spoc.used==spoc_not_implemented)
551  *type = spoc_type_sni;
552  else if (api->spoc.used & spoc_alu)
553  *type = spoc_type_alu;
554  else if (api->spoc.used & (spoc_poc_0|spoc_poc_1))
555  *type = spoc_type_poc;
556  else if (api->spoc.used & (spoc_th_0|spoc_th_1))
557  *type = spoc_type_thr;
558  else if (api->spoc.used & (spoc_measure_0|spoc_measure_1))
559  *type = spoc_type_mes;
560  else
561  *type = spoc_type_nop; // e.g. for copy? (...)
562 
563  // set details
565 }
int hwac_freia_api_index(const string function)
returns the index of the description of an AIPO function
Definition: freia-utils.c:471
@ spoc_measure_0
Definition: freia_spoc.h:50
@ spoc_th_0
Definition: freia_spoc.h:47
@ spoc_measure_1
Definition: freia_spoc.h:51
@ spoc_alu
Definition: freia_spoc.h:45
@ spoc_poc_1
Definition: freia_spoc.h:43
@ spoc_poc_0
Definition: freia_spoc.h:42
@ spoc_th_1
Definition: freia_spoc.h:48
@ spoc_type_sni
Definition: freia_spoc.h:172
@ spoc_type_nop
Definition: freia_spoc.h:174
@ spoc_type_thr
Definition: freia_spoc.h:178
@ spoc_type_alu
Definition: freia_spoc.h:177
@ spoc_type_poc
Definition: freia_spoc.h:176

References freia_api_t::function_name, hwac_freia_api_index(), pips_assert, freia_api_t::spoc, spoc_alu, spoc_measure_0, spoc_measure_1, spoc_not_implemented, spoc_poc_0, spoc_poc_1, spoc_th_0, spoc_th_1, spoc_type_alu, spoc_type_mes, spoc_type_nop, spoc_type_poc, spoc_type_sni, spoc_type_thr, and spoc_hw_t::used.

Referenced by dag_append_freia_call().

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

◆ freia_statement_aipo_call_p()

bool freia_statement_aipo_call_p ( const  statement)

returns whether the statement is a FREIA call.

Definition at line 814 of file freia-utils.c.

815 {
816  // very partial as well
818  if (instruction_call_p(i)) {
819  call c = instruction_call(i);
820  entity called = call_function(c);
821  if (entity_freia_api_p(called))
822  return true;
823  else if (freia_assignment_p(called))
824  {
825  list la = call_arguments(c);
826  pips_assert("2 arguments to assign", gen_length(la));
828  if (syntax_call_p(op2))
830  }
831  else if (ENTITY_C_RETURN_P(called))
832  {
833  list la = call_arguments(c);
834  if (gen_length(la)==1) {
836  if (syntax_call_p(op))
838  }
839  }
840  }
841  return false;
842 }
bool entity_freia_api_p(const entity f)
returns whether the entity is a freia API (AIPO) function.
Definition: freia-utils.c:806
bool freia_assignment_p(const entity e)
tell whether it is an assignment to ignore?
Definition: freia-utils.c:703
#define syntax_call_p(x)
Definition: ri.h:2734
#define syntax_call(x)
Definition: ri.h:2736
#define expression_syntax(x)
Definition: ri.h:1247

References call_arguments, call_function, CAR, CDR, ENTITY_C_RETURN_P, entity_freia_api_p(), EXPRESSION, expression_syntax, freia_assignment_p(), gen_length(), instruction_call, instruction_call_p, pips_assert, statement_instruction, syntax_call, and syntax_call_p.

Referenced by clean_list_head(), freia_cleanup_sequence_rec(), freia_reduction_variable(), fsi_seq_flt(), fsi_stmt_flt(), and set_add_scalars().

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

◆ freia_statement_to_call()

call freia_statement_to_call ( const statement  s)

return the actual function call from a statement, dealing with assign and returns...

return NULL if not a call.

Definition at line 973 of file freia-utils.c.

974 {
975  // sanity check, somehow redundant
977  call c = instruction_call_p(i)? instruction_call(i): NULL;
978  if (c && freia_assignment_p(call_function(c)))
979  {
980  list args = call_arguments(c);
981  pips_assert("2 args", gen_length(args) == 2);
982  syntax sy = expression_syntax(EXPRESSION(CAR(CDR(args))));
983  c = syntax_call_p(sy)? syntax_call(sy): NULL;
984  }
985  else if (c && ENTITY_C_RETURN_P(call_function(c)))
986  {
987  list args = call_arguments(c);
988  pips_assert("one arg", gen_length(args)==1);
989  syntax sy = expression_syntax(EXPRESSION(CAR(args)));
990  c = syntax_call_p(sy)? syntax_call(sy): NULL;
991  }
992  return c;
993 }

References call_arguments, call_function, CAR, CDR, ENTITY_C_RETURN_P, EXPRESSION, expression_syntax, freia_assignment_p(), gen_length(), instruction_call, instruction_call_p, pips_assert, statement_instruction, syntax_call, and syntax_call_p.

Referenced by any_use_statement(), dag_append_freia_call(), dag_normalize(), dagvtx_copy_list_dot(), fcs_count(), freia_alloc_stat_p(), freia_cleanup_sequence_rec(), freia_get_vertex_params(), freia_reduction_variable(), freia_spoc_pipeline(), freia_stmt_free_p(), freia_terapix_call(), get_upper_model(), is_freia_this_call(), maybe_unroll_while_rwt(), opencl_compile_mergeable_dag(), opencl_generate_special_kernel_ops(), same_constant_parameters(), sc_get_params_values(), set_aipo_call(), and substitute_image_in_statement().

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

◆ freia_substitute_by_helper_call()

int freia_substitute_by_helper_call ( dag  d,
set  global_remainings,
set  remainings,
list  ls,
const string  function_name,
list  lparams,
set  helpers,
int  preceeding 
)

substitute those statement in ls that are in dag d and accelerated by a call to function_name(lparams) also update sets of remainings and global_remainings

the function must chose one of the statements? the current implementation is a buggy mess. it should be fully re-thought from scratch.

what should be done, is to chose the FIRST statement after the LAST dependency of the compiled statements? at least it must exist beacause one of the dependent statement must appear after that, but is it enough for all possible graph? so maybe we should do a topological sort of all the statements and reshuffle everything instead of trying to preserver the initial code as much as possible?

Parameters
global_remainingslobal_remainings
remainingsemainings
lsof statement
function_nameunction_name
lparamsparams
helperselpers
preceedingreceeding

Definition at line 1073 of file freia-utils.c.

1083 {
1084  pips_debug(7, "%d statements, must come after statement %d\n",
1085  (int) gen_length(ls), preceeding);
1086 
1087  // buid the set of statements that are not yet computed
1088  set not_dones = set_make(set_pointer), dones = set_make(set_pointer);
1089  if (d)
1090  {
1091  FOREACH(dagvtx, vs, dag_vertices(d))
1092  {
1094  if (pstatement_statement_p(ps))
1095  set_add_element(not_dones, not_dones, pstatement_statement(ps));
1096  }
1097  }
1098  // dones: those statements which are handled by this helper
1099  set_difference(dones, remainings, not_dones);
1100  // now update remainings & global_remainings
1101  set_difference(remainings, remainings, dones);
1102  set_difference(global_remainings, global_remainings, dones);
1103 
1104  // replace first statement of dones in ls,
1105  // which comes after the preceeding ones.
1106  statement found = NULL, sos = NULL;
1107  FOREACH(statement, sc, ls)
1108  {
1109  pips_debug(5, "in statement %" _intFMT "\n", statement_number(sc));
1110  if (set_belong_p(dones, sc))
1111  {
1112  sos = sos? (statement_number(sc)<statement_number(sos)? sc: sos): sc;
1113  if (statement_number(sc)>preceeding)
1114  {
1115  pips_assert("statement is a call", statement_call_p(sc));
1116  found = found?
1117  (statement_number(sc)<statement_number(found)? sc: found): sc;
1118  }
1119  }
1120  }
1121 
1122  if (!found)
1123  {
1124  pips_user_warning("no statement found after preceeding insertion, "
1125  "using first statement as backup...\n");
1126  // use backup
1127  found = sos;
1128  }
1129 
1130  pips_assert("some statement found", found);
1131 
1132  // create and record helper function
1133  entity helper = freia_create_helper_function(function_name, lparams);
1134  set_add_element(helpers, helpers, helper);
1135 
1136  // substitute by call to helper
1137  call c = make_call(helper, lparams);
1138 
1139  hwac_replace_statement(found, c, false);
1140 
1141  set_free(not_dones);
1142  set_free(dones);
1143 
1144  return statement_number(found);
1145 }
entity freia_create_helper_function(const string function_name, list lparams)
Definition: freia-utils.c:1030
void hwac_replace_statement(statement s, call newc, bool kill)
replace statement contents with call to c, or continue if kill
Definition: freia-utils.c:720
set set_difference(set, const set, const set)
Definition: set.c:256

References _intFMT, dag_vertices, dagvtx_content, FOREACH, freia_create_helper_function(), gen_length(), hwac_replace_statement(), lparams, make_call(), pips_assert, pips_debug, pips_user_warning, pstatement_statement, pstatement_statement_p, set_add_element(), set_belong_p(), set_difference(), set_free(), set_make(), set_pointer, statement_call_p(), statement_number, and vtxcontent_source.

Referenced by freia_trpx_compile_one_dag(), and opencl_compile_mergeable_dag().

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

◆ freia_switch_image_in_statement()

void freia_switch_image_in_statement ( statement  s,
entity  old,
entity  img,
bool  write 
)

switch read or written image in statement if this is an AIPO call, only substitute output or input depending on write otherwise all occurrences are substituted

Parameters
oldld
imgmg
writerite

Definition at line 2746 of file dag-utils.c.

2748 {
2749  swis_ctx ctx = { old, img, write };
2750  gen_context_multi_recurse(s, &ctx,
2753  NULL);
2754 }
static bool swis_call_flt(call c, swis_ctx *ctx)
Definition: dag-utils.c:2707
static void swis_ref_rwt(reference r, swis_ctx *ctx)
Definition: dag-utils.c:2701

References call_domain, gen_context_multi_recurse(), gen_null(), gen_true(), reference_domain, swis_call_flt(), and swis_ref_rwt().

Referenced by freia_allocate_new_images_if_needed(), and switch_image_variable().

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

◆ freia_terapix_compiler()

bool freia_terapix_compiler ( const  string)
Parameters
stringodule

Definition at line 129 of file hardware_accelerator.c.

130 {
131  return freia_compiler(module, "terapix");
132 }

References freia_compiler(), and module.

+ Here is the call graph for this function:

◆ freia_transpose_kernel()

expression freia_transpose_kernel ( const  expression)

Transpose a structuring element expression.

Parameters
expressione

Definition at line 479 of file freia.c.

479  {
480  // get the structuring element array
483 
484  // reverse it...
485  list vals_rev = gen_nreverse(gen_full_copy_list(vals));
486 
487  // build the expression
488  return make_expression(make_syntax_call(make_call(fun, vals_rev)),
490 }
syntax make_syntax_call(call _field_)
Definition: ri.c:2500
expression make_expression(syntax a1, normalized a2)
Definition: ri.c:886
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
#define expression_normalized(x)
Definition: ri.h:1249

References call_arguments, call_function, expression_normalized, expression_syntax, gen_full_copy_list(), gen_nreverse(), make_call(), make_expression(), make_syntax_call(), and syntax_call.

Referenced by freia_is_transpose_call().

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

◆ freia_trpx_compile_calls()

list freia_trpx_compile_calls ( string  module,
dag  fulld,
sequence  sq,
list  ls,
const hash_table  occs,
hash_table  exchanges,
const set  output_images,
FILE *  helper_file,
set  helpers,
int  number 
)

freia_terapix.c

freia_terapix.c

Parameters
module,currentmodule (function) name
ls,listof statements taken from the sequence
occs,occurencesof images (image -> set of statements)
helper_file,fileto which code is to be generated
number,numberof this statement sequence in module
Returns
list of intermediate image to allocate
Parameters
moduleodule
fulldulld
sqq
lsof statements
occsccs
exchangesxchanges
output_imagesutput_images
helper_fileelper_file
helperselpers
numberumber

Definition at line 1808 of file freia_terapix.c.

1819 {
1820  bool reduce_cc =
1821  get_bool_property("HWAC_TERAPIX_REDUCE_TO_CONNECTED_COMPONENTS");
1822 
1823  // build DAG for ls
1824  pips_debug(3, "considering %d statements\n", (int) gen_length(ls));
1825  pips_assert("some statements", ls);
1826 
1827  int n_op_init, n_op_init_copies;
1828  freia_aipo_count(fulld, &n_op_init, &n_op_init_copies);
1829 
1830  // must have distinct images in the graph for optimizations
1832  list new_images = dag_fix_image_reuse(fulld, init, occs);
1833 
1834  list added_before = NIL, added_after = NIL;
1835  freia_dag_optimize(fulld, exchanges, &added_before, &added_after);
1836 
1837  int n_op_opt, n_op_opt_copies;
1838  freia_aipo_count(fulld, &n_op_opt, &n_op_opt_copies);
1839 
1840  fprintf(helper_file,
1841  "\n"
1842  "// dag %d: %d ops and %d copies, "
1843  "optimized to %d ops and %d+%d+%d copies\n",
1844  number, n_op_init, n_op_init_copies,
1845  n_op_opt, n_op_opt_copies,
1846  (int) gen_length(added_before), (int) gen_length(added_after));
1847 
1848  // dump final dag
1849  dag_dot_dump_prefix(module, "dag_cleaned_", number, fulld,
1850  added_before, added_after);
1851 
1852  string fname_fulldag = strdup(cat(module, "_terapix", HELPER, i2a(number)));
1853 
1854  // First, split only on scalar deps...
1855  // is it that simple? NO!
1856  // consider A -> B -> s -> C -> D
1857  // \-> E -> F />
1858  // then ABEF / CD is chosen
1859  // although ABE / FCD and AB / EFCD would be also possible..
1860 
1861  pips_assert("erosion is clean", erosion==NULL);
1863  list ld = dag_split_on_scalars(fulld,
1868  output_images);
1869  hash_table_free(erosion), erosion = NULL;
1870 
1871  // split ld dags by connected components
1872  if (reduce_cc)
1873  {
1874  list nld = NIL;
1875  FOREACH(dag, d, ld)
1876  nld = gen_nconc(nld, dag_split_connected_components(d, output_images));
1877  gen_free_list(ld), ld = nld, nld = NIL;
1878  }
1879 
1880  pips_debug(4, "dag initial split in %d dags\n", (int) gen_length(ld));
1881 
1882  const char* dag_cut = get_string_property(trpx_dag_cut);
1883  pips_assert("valid cutting strategy", trpx_dag_cut_is_valid(dag_cut));
1884 
1885  // globally remaining statements
1886  set global_remainings = set_make(set_pointer);
1887  set_assign_list(global_remainings, ls);
1888 
1889  int n_split = 0;
1890  int stnb = -1;
1891  set dones = set_make(set_pointer);
1892 
1893  FOREACH(dag, d, ld)
1894  {
1895  // ??? should migrate beforehand?
1896 
1897  // skip if something is not implemented
1898  if (terapix_not_implemented(d))
1899  continue;
1900 
1901  if (dag_no_image_operation(d))
1902  continue;
1903 
1904  if (trpx_dag_cut_none_p(dag_cut))
1905  {
1906  migrate_statements(sq, d, dones);
1907  // direct handling of the dag
1908  stnb = freia_trpx_compile_one_dag(module, ls, d, fname_fulldag, n_split,
1909  -1, global_remainings, helper_file, helpers, stnb, init);
1910  }
1911  else if (trpx_dag_cut_compute_p(dag_cut))
1912  {
1913  // try split dag into subdags with a rough computed strategy
1915  int cut, n_cut = 0;
1916 
1917  // what about another strategy?
1918  // I can try every possible cuts and chose the best one,
1919  // that is to stop as soon as computation cost > communication cost?
1920  // or when costs are quite balanced in all cuts?
1921  // dag cutting strategy prop = none/computed/optimized?
1922 
1923  while ((cut = cut_decision(d, erosion)))
1924  {
1925  dag dc = cut_perform(d, cut, erosion, fulld, output_images);
1926 
1927  // may separate by connected components...
1928  list ld;
1929  if (reduce_cc)
1930  ld = dag_split_connected_components(dc, output_images);
1931  else
1932  ld = CONS(dag, dc, NIL);
1933 
1934  FOREACH(dag, dci, ld)
1935  {
1936  migrate_statements(sq, dci, dones);
1937  // generate code for cut
1938  stnb =
1939  freia_trpx_compile_one_dag(module, ls, dci, fname_fulldag, n_split,
1940  n_cut++, global_remainings, helper_file, helpers, stnb, init);
1941  // cleanup
1942  free_dag(dci);
1943  }
1944 
1946  gen_free_list(ld);
1947  }
1948 
1949  if (dag_vertices(d)) {
1950  // should it *ALWAYS* HAPPEN?
1951  migrate_statements(sq, d, dones);
1952  stnb = freia_trpx_compile_one_dag(module, ls, d, fname_fulldag, n_split,
1953  n_cut++, global_remainings, helper_file, helpers, stnb, init);
1954  }
1955 
1957  }
1958  else if (trpx_dag_cut_enumerate_p(dag_cut))
1959  pips_internal_error("not implemented yet");
1960  else
1961  pips_internal_error("cannot get there");
1962 
1963  n_split++;
1964  }
1965 
1966  freia_insert_added_stats(ls, added_before, true);
1967  added_before = NIL;
1968  freia_insert_added_stats(ls, added_after, false);
1969  added_after = NIL;
1970 
1971  // full cleanup
1972  set_free(global_remainings), global_remainings = NULL;
1973  free(fname_fulldag), fname_fulldag = NULL;
1974  FOREACH(dag, dc, ld)
1975  free_dag(dc);
1976  gen_free_list(ld);
1977 
1978  // deal with new images
1979  list real_new_images =
1980  freia_allocate_new_images_if_needed(ls, new_images, occs, init, init);
1981  gen_free_list(new_images);
1983  return real_new_images;
1984 }
list dag_split_connected_components(dag d, set output_images)
build connected components
Definition: dag-utils.c:3035
static hash_table erosion
global variable used by the dagvtx_terapix_priority function, because qsort does not allow to pass so...
static void dag_terapix_reset_erosion(const dag d)
static int cut_decision(dag d, hash_table erosion)
would it seem interesting to split d?
static bool not_implemented(dagvtx v)
whether vertex is not implemented in terapix
static int freia_trpx_compile_one_dag(string module, list ls, dag d, string fname_fulldag, int n_split, int n_cut, set global_remainings, FILE *helper_file, set helpers, int stnb, hash_table signatures)
generate terapix code for this one dag, which should be already split.
static dag cut_perform(dag d, int cut, hash_table erodes, dag fulld, const set output_images)
cut dag "d", possibly a subdag of "fulld", at "erosion" "cut"
static bool terapix_not_implemented(dag d)
whether dag is not implemented in terapix
static int dagvtx_terapix_priority(const dagvtx *v1, const dagvtx *v2)
comparison function for sorting dagvtx in qsort, this is deep voodoo, because the priority has an imp...
static dagvtx choose_terapix_vertex(const list lv, bool started)
choose a vertex, avoiding non combinable stuff if the list is started
static void migrate_statements(sequence sq, dag d, set dones)
#define trpx_dag_cut_none_p(s)
Definition: freia_terapix.h:43
#define trpx_dag_cut_is_valid(s)
Definition: freia_terapix.h:46
#define trpx_dag_cut
Definition: freia_terapix.h:38
#define trpx_dag_cut_compute_p(s)
Definition: freia_terapix.h:44
#define trpx_dag_cut_enumerate_p(s)
Definition: freia_terapix.h:45
void hash_table_clear(hash_table htp)
Clears all entries of a hash table HTP.
Definition: hash.c:305

Referenced by freia_compile().

+ Here is the caller graph for this function:

◆ freia_unroll_while()

bool freia_unroll_while ( const  string)

freia_transformations.c

Parameters
stringodule

Definition at line 269 of file freia_transformations.c.

270 {
271  // sanity check
272  int factor = get_int_property(spoc_depth_prop);
273  if (factor<=1)
274  {
275  pips_user_warning("cannot unroll with factor=%d\n", factor);
276  return true;
277  }
278 
279  // else, do the job
280  debug_on("PIPS_HWAC_DEBUG_LEVEL");
281  pips_debug(1, "considering module %s\n", module);
282 
283  // else do the stuff
285  (statement) db_get_memory_resource(DBR_CODE, module, true);
288 
289  // do the job
290  bool changed = freia_unroll_while_for_spoc(mod_stat);
291 
292  // update if changed
293  if (changed)
294  {
298  }
299 
300  // cleanup
303  debug_off();
304  return true;
305 }
int get_int_property(const string)
#define spoc_depth_prop
Definition: freia_spoc.h:185
static bool freia_unroll_while_for_spoc(statement s)
static void stmt_renumber(statement s)
bool module_reorder(statement body)
Reorder a module and recompute order to statement if any.
Definition: reorder.c:244

References db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, freia_unroll_while_for_spoc(), get_int_property(), mod_stat, module, module_name_to_entity(), module_reorder(), pips_debug, pips_user_warning, reset_current_module_entity(), reset_current_module_statement(), set_current_module_entity(), set_current_module_statement(), spoc_depth_prop, and stmt_renumber().

+ Here is the call graph for this function:

◆ get_freia_api()

const freia_api_t* get_freia_api ( int  index)
Parameters
indexndex

Definition at line 477 of file freia-utils.c.

478 {
479  // pips_assert("index exists", index>=0 && index<(int) FREIA_AIPO_API_SIZE);
480  return &FREIA_AIPO_API[index];
481 }
static const freia_api_t FREIA_AIPO_API[]
!!! there are some underlying assumptions when using this structure: only one of ALU/POC/MES is used ...
Definition: freia-utils.c:99

References FREIA_AIPO_API.

Referenced by commutative_operation_p(), constant_image_p(), copy_image_p(), dagvtx_compact_operation(), dagvtx_function_name(), dagvtx_is_measurement_p(), dagvtx_is_operator_p(), freia_extract_params(), freia_spoc_pipeline(), freia_terapix_call(), get_freia_api_vtx(), opencl_compile_mergeable_dag(), and propagate_constant_image().

+ Here is the caller graph for this function:

◆ get_freia_api_vtx()

const freia_api_t* get_freia_api_vtx ( dagvtx  v)

Definition at line 483 of file freia-utils.c.

484 {
486 }

References dagvtx_content, get_freia_api(), and vtxcontent_opid.

Referenced by dagvtx_constant_kernel_p(), has_vtx_dynamic_params(), mppa_compile_dag(), opencl_generate_special_kernel_ops(), opencl_merge_and_compile(), sc_delimiter(), sc_inst(), sc_vtx_tostring(), sigmac_name_instances(), and sigmac_params_decl().

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

◆ helper_file_name()

string helper_file_name ( string  func_name,
string  suffix 
)

return malloc'ed "foo.database/Src/%{module}_helper_functions.c" should it depend on the target? no, because we could mix targets?

Parameters
func_nameunc_name
suffixuffix

Definition at line 2029 of file freia-utils.c.

2030 {
2031  string src_dir = db_get_directory_name_for_module(func_name);
2032  string fn = strdup(cat(src_dir, "/", func_name, HELPER "functions.", suffix));
2033  free(src_dir);
2034  return fn;
2035 }

References cat, db_get_directory_name_for_module(), free(), HELPER, and strdup().

Referenced by freia_compile(), and sc_delimiter().

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

◆ hwac_freia_api()

const freia_api_t* hwac_freia_api ( const char *  function)

freia-utils.c

Returns
the description of a FREIA AIPO API function. may be moved elswhere. raise an error if not found.
Parameters
functionunction

Definition at line 455 of file freia-utils.c.

456 {
457  static hash_table cache = NULL;
458  if (!cache)
459  {
460  const freia_api_t * api;
461  cache = hash_table_make(hash_string, 0);
462  for (api = FREIA_AIPO_API; api->function_name; api++)
463  hash_put(cache, api->function_name, api);
464  }
465  return (const freia_api_t *)
466  (hash_defined_p(cache, function)? hash_get(cache, function): NULL);
467 }
@ hash_string
Definition: newgen_hash.h:32

References FREIA_AIPO_API, freia_api_t::function_name, hash_defined_p(), hash_get(), hash_put(), hash_string, and hash_table_make().

Referenced by dag_append_freia_call(), freia_cleanup_sequence_rec(), freia_terapix_call(), hwac_freia_api_index(), reference_written_p(), sio_call_flt(), and swis_call_flt().

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

◆ hwac_freia_api_index()

int hwac_freia_api_index ( const  string)

returns the index of the description of an AIPO function

Parameters
stringunction

Definition at line 471 of file freia-utils.c.

472 {
473  const freia_api_t * api = hwac_freia_api(function);
474  return api? (api - FREIA_AIPO_API): -1;
475 }
const freia_api_t * hwac_freia_api(const char *function)
freia-utils.c
Definition: freia-utils.c:455

References FREIA_AIPO_API, and hwac_freia_api().

Referenced by commutative_operation_p(), dag_normalize(), freia_spoc_set_operation(), set_aipo_call(), switch_vertex_to_a_copy(), and switch_vertex_to_assign().

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

◆ hwac_kill_statement()

void hwac_kill_statement ( statement  s)

remove contents of statement s.

Definition at line 761 of file freia-utils.c.

762 {
763  hwac_replace_statement(s, freia_ok(), true);
764 }
call freia_ok(void)
build all is well freia constant
Definition: freia-utils.c:695

References freia_ok(), and hwac_replace_statement().

Referenced by freia_dag_optimize(), freia_spoc_pipeline(), freia_terapix_call(), and opencl_compile_mergeable_dag().

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

◆ hwac_replace_statement()

void hwac_replace_statement ( statement  s,
call  newc,
bool  kill 
)

replace statement contents with call to c, or continue if kill

Parameters
newcewc
killill

Definition at line 720 of file freia-utils.c.

721 {
723  pips_assert("must kill a call", instruction_call_p(old));
724  call c = instruction_call(old);
725  entity called = call_function(c);
726  if (ENTITY_C_RETURN_P(called))
727  {
728  // replace argument list
731  }
732  else if (freia_assignment_p(called))
733  {
734  // new second argument
735  list largs = call_arguments(c);
736  pips_assert("two arguments to assignment", gen_length(largs)==2);
737  expression first = EXPRESSION(CAR(largs));
738  free_expression(EXPRESSION(CAR(CDR(largs))));
739  gen_free_list(largs), largs = NIL;
740  call_arguments(c) =
742  }
743  else
744  {
745  free_instruction(old);
746  if (kill)
747  {
748  // ??? in C, it is not a do nothing instruction!
750  free_call(newc);
751  }
752  else
753  {
755  }
756  }
757 }
instruction make_instruction_call(call _field_)
Definition: ri.c:1184
void free_expression(expression p)
Definition: ri.c:853
void free_call(call p)
Definition: ri.c:236
void gen_full_free_list(list l)
Definition: genClib.c:1023
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309

References call_arguments, call_function, call_to_expression(), CAR, CDR, CONS, ENTITY_C_RETURN_P, EXPRESSION, free_call(), free_expression(), free_instruction(), freia_assignment_p(), gen_free_list(), gen_full_free_list(), gen_length(), instruction_call, instruction_call_p, make_continue_instruction(), make_instruction_call(), NIL, pips_assert, and statement_instruction.

Referenced by freia_substitute_by_helper_call(), hwac_kill_statement(), mppa_call_helper(), and sc_delimiter().

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

◆ is_freia_alloc()

bool is_freia_alloc ( const  statement)

Definition at line 1002 of file freia-utils.c.

1003 {
1004  return is_freia_this_call(s, FREIA_ALLOC);
1005 }
static bool is_freia_this_call(const statement s, const string fname)
Definition: freia-utils.c:995
#define FREIA_ALLOC
Definition: freia.h:48

References FREIA_ALLOC, and is_freia_this_call().

Referenced by freia_cmp_statement(), freia_memory_management_statement(), and get_upper_model().

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

◆ is_freia_dealloc()

bool is_freia_dealloc ( const  statement)

Definition at line 1007 of file freia-utils.c.

1008 {
1009  return is_freia_this_call(s, FREIA_FREE);
1010 }
#define FREIA_FREE
Definition: freia.h:49

References FREIA_FREE, and is_freia_this_call().

Referenced by freia_cleanup_sequence_rec(), freia_cmp_statement(), and freia_memory_management_statement().

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

◆ remove_simple_scalar_pointers()

bool remove_simple_scalar_pointers ( const  string)
Parameters
stringodule

Definition at line 584 of file freia_transformations.c.

585 {
586  debug_on("PIPS_HWAC_DEBUG_LEVEL");
587  pips_debug(1, "considering module %s\n", module);
588 
589  // else do the stuff
591  (statement) db_get_memory_resource(DBR_CODE, module, true);
594 
595  rssp_ctx ctx;
601 
602  // get candidates
604  {
605  if (pointer_candidate_p(var))
606  {
607  set_add_element(ctx.candidates, ctx.candidates, var);
609  {
611  entity v2 = address_of_scalar(e);
612  if (v2)
613  {
614  hash_put(ctx.points_to, var, v2);
615  hash_put(ctx.defined, var, expression_call(e));
616  }
617  }
618  }
619  }
620 
621 
622  // check condition
624  (mod_stat, &ctx,
626  // ignore sizeof
628  NULL);
629 
630  bool changed = false;
631  // apply transformation
632  SET_FOREACH(entity, var, ctx.candidates)
633  {
634  pips_debug(2, "considering entity %s inv=%d dr=%d def=%d pt=%d\n",
635  entity_name(var), set_belong_p(ctx.invalidated, var),
636  hash_defined_p(ctx.dereferenced, var),
637  hash_defined_p(ctx.defined, var),
638  hash_defined_p(ctx.points_to, var));
639 
640  if (!set_belong_p(ctx.invalidated, var) &&
641  hash_defined_p(ctx.dereferenced, var) &&
642  hash_defined_p(ctx.defined, var) &&
643  hash_defined_p(ctx.points_to, var))
644  {
645  changed = true;
646  // replace use
647  expression deref = (expression) hash_get(ctx.dereferenced, var);
649  (make_reference((entity) hash_get(ctx.points_to, var), NIL));
650  // drop definition
651  call definition = (call) hash_get(ctx.defined, var);
652  gen_free_list(call_arguments(definition)),
653  call_arguments(definition) = NIL;
655  // declaration cleanup?
656  }
657  }
658 
659  // result
660  if (changed)
662 
663  // cleanup
664  set_free(ctx.candidates);
665  set_free(ctx.invalidated);
671  debug_off();
672 
673  return true;
674 }
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
syntax make_syntax_reference(reference _field_)
Definition: ri.c:2494
struct _newgen_struct_expression_ * expression
Definition: alias_private.h:21
static void rssp_ref(reference r, rssp_ctx *ctx)
static entity address_of_scalar(expression e)
"&v"? return v, else return NULL
static bool pointer_candidate_p(entity var)
bool gen_false(__attribute__((unused)) gen_chunk *unused)
Return false and ignore the argument.
Definition: genClib.c:2796
#define entity_declarations(e)
MISC: newgen shorthands.
call expression_call(expression e)
Definition: expression.c:445
entity make_integer_constant_entity(_int)
entity make_integer_constant_entity(int c) make entity for integer constant c
Definition: variable.c:1345
#define sizeofexpression_domain
newgen_sequence_domain_defined
Definition: ri.h:354
struct _newgen_struct_call_ * call
Definition: ri.h:63
hash_table points_to
hash_table dereferenced
hash_table defined

References address_of_scalar(), call_arguments, call_function, rssp_ctx::candidates, db_get_memory_resource(), DB_PUT_MEMORY_RESOURCE, debug_off, debug_on, rssp_ctx::defined, rssp_ctx::dereferenced, entity_declarations, entity_initial, entity_name, expression_call(), expression_syntax, FOREACH, gen_context_multi_recurse(), gen_false(), gen_free_list(), gen_null(), gen_true(), get_current_module_entity(), hash_defined_p(), hash_get(), hash_pointer, hash_put(), hash_table_free(), hash_table_make(), rssp_ctx::invalidated, make_integer_constant_entity(), make_reference(), make_syntax_reference(), mod_stat, module, module_name_to_entity(), NIL, pips_debug, pointer_candidate_p(), rssp_ctx::points_to, reference_domain, reset_current_module_entity(), reset_current_module_statement(), rssp_ref(), set_add_element(), set_belong_p(), set_current_module_entity(), set_current_module_statement(), SET_FOREACH, set_free(), set_make(), set_pointer, sizeofexpression_domain, value_expression, and value_expression_p.

+ Here is the call graph for this function:

◆ same_constant_parameters()

bool same_constant_parameters ( const  dagvtx,
const  dagvtx 
)

tell whether v1 and v2 point to statements with the same parameters.

Parameters
dagvtx1
dagvtx2

Definition at line 1014 of file freia-utils.c.

1015 {
1016  call
1019  list
1020  lp1 = freia_extract_params
1021  (dagvtx_opid(v1), call_arguments(c1), NULL, NULL, NULL, NULL),
1022  lp2 = freia_extract_params
1023  (dagvtx_opid(v1), call_arguments(c2), NULL, NULL, NULL, NULL);
1024  bool same = lexpression_equal_p(lp1, lp2);
1025  gen_free_list(lp1), gen_free_list(lp2);
1026  // should also check that there is no w effects on parameters in between
1027  return same;
1028 }
_int dagvtx_opid(const dagvtx v)
Definition: dag-utils.c:121
list freia_extract_params(const int napi, list args, string_buffer head, string_buffer head2, hash_table params, int *nparams)
returns an allocated expression list of the parameters only (i.e.
Definition: freia-utils.c:613
static bool lexpression_equal_p(const list l1, const list l2)
Definition: freia-utils.c:953

References call_arguments, dagvtx_opid(), dagvtx_statement(), freia_extract_params(), freia_statement_to_call(), gen_free_list(), and lexpression_equal_p().

Referenced by freia_dag_optimize().

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

◆ set_append_vertex_statements()

void set_append_vertex_statements ( set  s,
list  lv 
)
Parameters
lvv

Definition at line 2385 of file dag-utils.c.

2386 {
2387  FOREACH(dagvtx, v, lv)
2388  {
2390  if (pstatement_statement_p(ps))
2392  }
2393 }

References dagvtx_content, FOREACH, pstatement_statement, pstatement_statement_p, set_add_element(), and vtxcontent_source.

Referenced by freia_trpx_compile_one_dag(), and opencl_compile_mergeable_dag().

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

◆ single_image_assignement_p()

bool single_image_assignement_p ( dag  d)

??? I'm unsure about what happens to dead code in the pipeline...

??? BUG the code may not work properly when image variable are reused within a pipe. The underlying issues are subtle and would need careful thinking: the initial code is correct, the dag representation is correct, but the generated code may reorder dag vertices so that reused variables are made to interact one with the other. Maybe I should recreate output variables in the generated code for every pipeline. this would imply a cleanup phase to removed unused images at the end. I would really need an SSA form on images? this function checks the assumption before proceeding further.

Definition at line 2217 of file dag-utils.c.

2218 {
2219  set outs = set_make(set_pointer);
2220  FOREACH(dagvtx, v, dag_vertices(d))
2221  {
2222  vtxcontent c = dagvtx_content(v);
2223  entity out = vtxcontent_out(c);
2224  if (out!=entity_undefined)
2225  {
2226  if (set_belong_p(outs, out)) {
2227  set_free(outs);
2228  return false;
2229  }
2230  set_add_element(outs, outs, out);
2231  }
2232  }
2233  set_free(outs);
2234  return true;
2235 }

References dag_vertices, dagvtx_content, entity_undefined, FOREACH, out, set_add_element(), set_belong_p(), set_free(), set_make(), set_pointer, and vtxcontent_out.

Referenced by dag_split_on_scalars().

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

◆ what_operation()

string what_operation ( const _int  type)
Returns
a string which describes the type of operation (i.e. the hardware used by the function for spoc).

Definition at line 499 of file freia-utils.c.

500 {
501  switch (type)
502  {
503  case spoc_type_sni: return "sni";
504  case spoc_type_oth: return "other";
505  case spoc_type_nop: return "none";
506  case spoc_type_inp: return "input";
507  case spoc_type_poc: return "poc";
508  case spoc_type_alu: return "alu";
509  case spoc_type_mes: return "measure";
510  case spoc_type_thr: return "threshold";
511  case spoc_type_out: return "output";
512  default: return "unexpected value...";
513  }
514 }
@ spoc_type_out
Definition: freia_spoc.h:180
@ spoc_type_inp
Definition: freia_spoc.h:175

References spoc_type_alu, spoc_type_inp, spoc_type_mes, spoc_type_nop, spoc_type_oth, spoc_type_out, spoc_type_poc, spoc_type_sni, and spoc_type_thr.

Referenced by basic_spoc_conf(), comment(), dagvtx_dump(), generate_wiring(), print_op_schedule(), and where_to_perform_operation().

+ Here is the caller graph for this function:

◆ what_operation_shape()

string what_operation_shape ( const _int  type)

SPoC: set shape depending on hardware component used by vertex.

Definition at line 518 of file freia-utils.c.

519 {
520  string shape;
521  switch (type)
522  {
523  case spoc_type_oth:
524  shape = "shape=none"; break;
525  case spoc_type_poc:
526  shape = "shape=box"; break;
527  case spoc_type_alu:
528  shape = "shape=trapezium,orientation=270"; break;
529  case spoc_type_thr:
530  shape = "shape=parallelogram"; break;
531  case spoc_type_mes:
532  shape = "shape=diamond"; break;
533  // these should not happen
534  case spoc_type_out:
535  case spoc_type_inp:
536  case spoc_type_nop:
537  default:
538  shape = "shape=circle";
539  }
540  return shape;
541 }

References spoc_type_alu, spoc_type_inp, spoc_type_mes, spoc_type_nop, spoc_type_oth, spoc_type_out, spoc_type_poc, and spoc_type_thr.

Referenced by dagvtx_dot().

+ Here is the caller graph for this function: