PIPS
dag-utils.c File Reference
#include <stdint.h>
#include <stdlib.h>
#include "genC.h"
#include "misc.h"
#include "freia.h"
#include "linear.h"
#include "pipsdbm.h"
#include "ri.h"
#include "effects.h"
#include "ri-util.h"
#include "effects-util.h"
#include "properties.h"
#include "freia_spoc_private.h"
#include "hwac.h"
+ Include dependency graph for dag-utils.c:

Go to the source code of this file.

Data Structures

struct  swis_ctx
 

Macros

#define IMG_DEP   ""
 
#define SCL_DEP   "arrowhead=empty"
 
#define DOT_SUFFIX   ".dot"
 
#define aipo_op_p(a, name)    same_string_p(AIPO name, a->function_name)
 
#define starts_with(s1, s2)   (strncmp(s1, s2, strlen(s2))==0) /**a la java */
 

Functions

string dagvtx_to_string (const dagvtx v)
 dag-utils.c More...
 
statement dagvtx_statement (const dagvtx v)
 return statement if any, or NULL (for input nodes). More...
 
void dag_statements (set stats, const dag d)
 build the set of actual statements in d More...
 
bool dagvtx_other_stuff_p (const dagvtx v)
 a vertex with a non AIPO or image related statement. More...
 
entity dagvtx_image (const dagvtx v)
 return the produced image or NULL More...
 
static void entity_list_dump (FILE *out, const string what, const list l)
 
_int dagvtx_number (const dagvtx v)
 returns the vertex number, i.e. More...
 
string dagvtx_number_str (const dagvtx v)
 
_int dagvtx_optype (const dagvtx v)
 
_int dagvtx_opid (const dagvtx v)
 
string dagvtx_function_name (const dagvtx v)
 
string dagvtx_operation (const dagvtx v)
 
string dagvtx_compact_operation (const dagvtx v)
 
int dagvtx_ordering (const dagvtx *v1, const dagvtx *v2)
 
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. More...
 
void dagvtx_nb_dump (FILE *out, const string what, const list l)
 
void dagvtx_dump (FILE *out, const string name, const dagvtx v)
 for dag debug. More...
 
void dag_dump (FILE *out, const string what, const dag d)
 for dag debug More...
 
static const char * entity_dot_name (entity e)
 
static void dagvtx_dot_node (FILE *out, const string prefix, const dagvtx v)
 
static void dagvtx_dot_node_sb (string_buffer sb, const string prefix, const dagvtx v)
 
static void dagvtx_dot (FILE *out, const dag d, const dagvtx vtx)
 
static void dagvtx_copy_list_dot (FILE *out, const list ls, const set inputs)
 
static void dagvtx_list_dot (FILE *out, const string comment, const list l, const set used)
 
static bool dagvtx_is_operator_p (const dagvtx v, const string opname)
 
static bool dagvtx_is_copy_p (const dagvtx v)
 returns whether the vertex is an image copy operation. More...
 
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 More...
 
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. More...
 
void dag_dot_dump_prefix (const string module, const string prefix, int number, const dag d, const list lb, const list la)
 
static void check_removed (const dagvtx v, const dagvtx removed)
 
static int dagvtx_cmp_entity (const dagvtx *v1, const dagvtx *v2)
 
static void vertex_list_sorted_by_entities (list l)
 
void dag_consistency_asserts (dag d)
 do some consistency checking... More...
 
static void dag_remove_unused_inputs (dag d)
 remove unused inputs More...
 
void dag_remove_vertex (dag d, const dagvtx v)
 remove vertex v from dag d. More...
 
dagvtx copy_dagvtx_norec (dagvtx v)
 copy a vertex, but without its successors. More...
 
bool dagvtx_is_measurement_p (const dagvtx v)
 returns whether the vertex is an image measurement operation. More...
 
void dag_append_vertex (dag d, dagvtx nv)
 append new vertex nv to dag d. More...
 
int dag_computation_count (const dag d)
 return the number of actual operations in dag d. More...
 
list dag_vertex_preds (const dag d, const dagvtx target)
 return target predecessor vertices as a list. More...
 
static bool gen_list_equals_p (const list l1, const list l2)
 
static bool switch_vertex_to_assign (dagvtx target, dagvtx source)
 replace target measure to a copy of source result... More...
 
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. More...
 
static void switch_vertex_to_a_copy (dagvtx target, dagvtx source, list tpreds)
 replace target vertex by a copy of source results... More...
 
static bool same_operation_p (const dagvtx v1, const dagvtx v2)
 
static bool commutative_operation_p (const dagvtx v1, const dagvtx v2)
 
static bool list_commuted_p (const list l1, const list l2)
 
static void unlink_copy_vertex (dag d, const entity source, dagvtx copy)
 "copy" copies "source" image in dag "d". More...
 
static bool all_vertices_are_copies_or_measures_p (const list lv)
 
static int number_of_copies (list l)
 
static expression compute_constant (string op, expression val1, expression val2)
 compute a constant expression for FREIA ??? TODO partial eval if values are constant More...
 
static void set_aipo_call (dagvtx v, string name, entity img, expression val)
 switch vertex statement to an aipo call More...
 
static void set_aipo_copy (dagvtx v, entity e)
 switch vertex to a copy of an image More...
 
static bool propagate_constant_image (dagvtx v, entity image, expression val)
 recursively propagate a constant image on a vertex More...
 
static void set_aipo_constant (dagvtx v, expression val)
 set vertex as a constant image and propagate to successors More...
 
static expression constant_image_p (dagvtx v)
 whether vertex generates a constant image More...
 
static entity copy_image_p (dagvtx v)
 tell whether vertex can be assimilated to a copy e.g. More...
 
static void propagate_constant_image_to_succs (dagvtx v, expression val)
 propagate constant image to vertex successors More...
 
static bool dag_simplify (dag d)
 apply basic algebraic simplification to dag More...
 
static bool dag_normalize (dag d)
 normalize, that is use less image operators only transformation is: sub_const(i, v) -> add_const(i, -v) More...
 
static int compatible_reduction_operation (const dagvtx v1, const dagvtx v2)
 
void freia_dag_optimize (dag d, hash_table exchanges, list *lbefore, list *lafter)
 remove dead image operations. More...
 
static bool all_mesures_p (list lv)
 return whether all vertices in list are mesures... More...
 
static set dag_stats (dag d)
 
static bool any_use_statement (set stats)
 hmmm... More...
 
static bool other_significant_uses (entity e, const hash_table occs, const set stats)
 
static bool variable_used_as_later_input (entity img, list ld)
 hmmm... More...
 
static bool dag_image_is_an_input (dag d, entity img)
 
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. More...
 
static dagvtx find_twin_vertex (dag d, dagvtx target)
 
void freia_hack_fix_global_ins_outs (dag dfull, dag d)
 catch some cases of missing outs between splits... More...
 
void dag_cleanup_other_statements (dag d)
 remove unneeded statements? you must know they are really un-needed! More...
 
bool single_image_assignement_p (dag d)
 ??? I'm unsure about what happens to dead code in the pipeline... More...
 
static bool any_scalar_dep (dagvtx v, set vs)
 returns whether there is a scalar RW dependency from any vs to v More...
 
static bool all_previous_stats_with_deps_are_computed (dag d, const set computed, dagvtx v)
 check scalar dependency from computed to v. More...
 
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. More...
 
void set_append_vertex_statements (set s, list lv)
 
static list fs_expression_list_to_entity_list (list args, int nargs)
 convert the first n items in list args to entities. More...
 
static entity extract_fist_item (list *lp)
 extract first entity item from list. More...
 
static void dag_append_freia_call (dag d, statement s)
 append statement s to dag d More...
 
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. More...
 
bool dag_no_image_operation (dag d)
 tell whether we have something to do with images ??? hmmm... More...
 
entity clone_variable_with_new_name (entity, const char *, const char *)
 This function build and return new variable from a variable a_variable, with name new_name. More...
 
string compilation_unit_of_module (const char *)
 The output is undefined if the module is referenced but not defined in the workspace, for instance because its code should be synthesized. More...
 
static entity freia_data2d_field (string field)
 
static expression do_point_to (entity var, string field_name)
 
static bool image_ref_flt (reference r, entity *image)
 
static entity get_upper_model (entity model, const hash_table occs)
 
statement freia_memory_management_statement (entity image, const hash_table occs, bool alloc)
 
static entity new_local_image_variable (entity model, const hash_table occs)
 
static void swis_ref_rwt (reference r, swis_ctx *ctx)
 
static bool swis_call_flt (call c, swis_ctx *ctx)
 
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 More...
 
static void switch_image_variable (dagvtx v, entity old, entity img)
 switch to new image variable in v & its direct successors More...
 
list dag_fix_image_reuse (dag d, hash_table init, const hash_table occs)
 fix intermediate image reuse in dag More...
 
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. More...
 
static string dagvtx_nb (const void *s)
 
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. More...
 
static list copy_vertices (list lv)
 
list dag_split_connected_components (dag d, set output_images)
 build connected components More...
 

Macro Definition Documentation

◆ aipo_op_p

#define aipo_op_p (   a,
  name 
)     same_string_p(AIPO name, a->function_name)

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

◆ DOT_SUFFIX

#define DOT_SUFFIX   ".dot"

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

◆ IMG_DEP

#define IMG_DEP   ""

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

◆ SCL_DEP

#define SCL_DEP   "arrowhead=empty"

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

◆ starts_with

#define starts_with (   s1,
  s2 
)    (strncmp(s1, s2, strlen(s2))==0) /**a la java */

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

Function Documentation

◆ all_mesures_p()

static bool all_mesures_p ( list  lv)
static

return whether all vertices in list are mesures...

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

1958 {
1959  bool only_mes = true;
1960  FOREACH(dagvtx, v, lv)
1961  {
1962  if (dagvtx_optype(v)!=spoc_type_mes)
1963  {
1964  only_mes = false;
1965  break;
1966  }
1967  }
1968  return only_mes;
1969 }
_int dagvtx_optype(const dagvtx v)
Definition: dag-utils.c:116
@ spoc_type_mes
Definition: freia_spoc.h:179
#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

References dagvtx_optype(), FOREACH, and spoc_type_mes.

Referenced by dag_compute_outputs().

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

◆ all_previous_stats_with_deps_are_computed()

static bool all_previous_stats_with_deps_are_computed ( dag  d,
const set  computed,
dagvtx  v 
)
static

check scalar dependency from computed to v.

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

2275 {
2276  bool okay = true;
2277 
2278  // scan in statement order... does it matter?
2280  FOREACH(dagvtx, pv, lv)
2281  {
2282  // all previous have been scanned
2283  if (pv==v) break;
2285  !set_belong_p(computed, pv))
2286  {
2287  okay = false;
2288  break;
2289  }
2290  }
2291  gen_free_list(lv);
2292 
2293  pips_debug(8, "all %d deps are okay: %s\n",
2294  (int) dagvtx_number(v), bool_to_string(okay));
2295  return okay;
2296 }
_int dagvtx_number(const dagvtx v)
returns the vertex number, i.e.
Definition: dag-utils.c:98
statement dagvtx_statement(const dagvtx v)
return statement if any, or NULL (for input nodes).
Definition: dag-utils.c:56
bool freia_scalar_rw_dep(const statement s, const statement t, list *vars)
Definition: freia-utils.c:929
#define dag_vertices(x)
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
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
string bool_to_string(bool)
Definition: string.c:243
bool set_belong_p(const set, const void *)
Definition: set.c:194
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References bool_to_string(), dag_vertices, dagvtx_number(), dagvtx_statement(), FOREACH, freia_scalar_rw_dep(), gen_copy_seq(), gen_free_list(), gen_nreverse(), pips_debug, and set_belong_p().

Referenced by dag_computable_vertices().

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

◆ all_vertices_are_copies_or_measures_p()

static bool all_vertices_are_copies_or_measures_p ( const list  lv)
static
Returns
whether all vertices in list "lv" are copies.

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

932 {
933  FOREACH(dagvtx, v, lv)
935  return false;
936  return true;
937 }
bool dagvtx_is_measurement_p(const dagvtx v)
returns whether the vertex is an image measurement operation.
Definition: dag-utils.c:623
static bool dagvtx_is_copy_p(const dagvtx v)
returns whether the vertex is an image copy operation.
Definition: dag-utils.c:399

References dagvtx_is_copy_p(), dagvtx_is_measurement_p(), and FOREACH.

Referenced by freia_dag_optimize().

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

◆ any_scalar_dep()

static bool any_scalar_dep ( dagvtx  v,
set  vs 
)
static

returns whether there is a scalar RW dependency from any vs to v

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

2240 {
2241  bool dep = false;
2242  statement target = dagvtx_statement(v);
2243 
2244  // hmmm... may be called on a input node
2245  if (!target) return dep;
2246 
2247  SET_FOREACH(dagvtx, source, vs)
2248  {
2249  if (source==v)
2250  continue;
2251 
2252  pips_debug(9, "%"_intFMT" rw dep to %"_intFMT"?\n",
2253  dagvtx_number(source), statement_number(target));
2254  if (freia_scalar_rw_dep(dagvtx_statement(source), target, NULL))
2255  {
2256  dep = true;
2257  break;
2258  }
2259  }
2260 
2261  ifdebug(8) {
2262  string svs = set_to_string("vs", vs, (gen_string_func_t) dagvtx_number_str);
2263  pips_debug(8, "scalar rw dep on %d for (%s): %s\n",
2264  (int) dagvtx_number(v), svs, bool_to_string(dep));
2265  free(svs);
2266  }
2267 
2268  return dep;
2269 }
string dagvtx_number_str(const dagvtx v)
Definition: dag-utils.c:111
void free(void *)
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
string set_to_string(string, const set, gen_string_func_t)
return allocated string for set s
Definition: set.c:513
string(* gen_string_func_t)(const void *)
Definition: newgen_types.h:111
#define _intFMT
Definition: newgen_types.h:57
#define statement_number(x)
Definition: ri.h:2452
#define ifdebug(n)
Definition: sg.c:47

References _intFMT, bool_to_string(), dagvtx_number(), dagvtx_number_str(), dagvtx_statement(), free(), freia_scalar_rw_dep(), ifdebug, pips_debug, SET_FOREACH, set_to_string(), and statement_number.

Referenced by dag_computable_vertices().

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

◆ any_use_statement()

static bool any_use_statement ( set  stats)
static

hmmm...

this is poor, should rather rely on use-def chains.

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

1988 {
1989  bool used = false;
1990  SET_FOREACH(statement, s, stats)
1991  {
1993  if (c) {
1994  const char* name = entity_local_name(call_function(c));
1995  pips_debug(9, "call to %s\n", name);
1996  // some freia utils are considered harmless,
1997  // others imply an actual "use"
1998  if (!same_string_p(name, FREIA_FREE) &&
1999  !same_string_p(name, FREIA_ALLOC) &&
2000  !same_string_p(name, "freia_common_rx_image"))
2001  used = true;
2002  }
2003  }
2004  return used;
2005 }
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 FREIA_FREE
Definition: freia.h:49
#define FREIA_ALLOC
Definition: freia.h:48
#define same_string_p(s1, s2)
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
#define call_function(x)
Definition: ri.h:709

References call_function, entity_local_name(), FREIA_ALLOC, FREIA_FREE, freia_statement_to_call(), pips_debug, same_string_p, and SET_FOREACH.

Referenced by other_significant_uses().

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

◆ check_removed()

static void check_removed ( const dagvtx  v,
const dagvtx  removed 
)
static

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

514 {
515  pips_assert("not removed vertex", v!=removed);
516 }
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172

References pips_assert.

Referenced by dag_remove_vertex(), and freia_dag_optimize().

+ Here is the caller graph for this function:

◆ clone_variable_with_new_name()

entity clone_variable_with_new_name ( entity  a_variable,
const char *  new_name,
const char *  module_name 
)

This function build and return new variable from a variable a_variable, with name new_name.

If an entity called new_name already exists, return NULL. New variable is added to declarations

Assert that module represent a value code

This entity does not exist, we can safely create it

new_variable = copy_entity (a_variable); entity_name(new_variable) = strdup(concatenate(module_name, MODULE_SEP_STRING, new_name, NULL));

ew_variable = find_or_create_scalar_entity (strdup(concatenate(module_name, MODULE_SEP_STRING, new_name, NULL)),module_name, is_basic_int);

This entity already exist, we return null

Definition at line 269 of file phrase_tools.c.

272 {
273  entity module;
275 
277  /* Assert that module represent a value code */
278  pips_assert("it is a code", value_code_p(entity_initial(module)));
279 
282  new_name,
283  NULL),
285  {
286  /* This entity does not exist, we can safely create it */
287 
288  /* new_variable = copy_entity (a_variable);
289  entity_name(new_variable)
290  = strdup(concatenate(module_name,
291  MODULE_SEP_STRING,
292  new_name, NULL)); */
293 
296  new_name, NULL)),
300 
301  /*new_variable
302  = find_or_create_scalar_entity (strdup(concatenate(module_name,
303  MODULE_SEP_STRING,
304  new_name, NULL)),module_name,
305  is_basic_int);*/
306 
308  return new_variable;
309  }
310  else
311  {
312  /* This entity already exist, we return null */
313  return NULL;
314  }
315 }
type copy_type(type p)
TYPE.
Definition: ri.c:2655
value copy_value(value p)
VALUE.
Definition: ri.c:2784
storage copy_storage(storage p)
STORAGE.
Definition: ri.c:2228
static entity new_variable
entity to be replaced, the primary?
Definition: dynamic.c:860
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
static entity a_variable
#define MODULE_SEP_STRING
Definition: naming-local.h:30
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
void * gen_find_tabulated(const char *, int)
Definition: tabulated.c:218
static char * module
Definition: pips.c:74
#define make_entity(n, t, s, i)
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
void AddEntityToDeclarations(entity, entity)
END_EOLE.
Definition: variable.c:108
#define value_code_p(x)
Definition: ri.h:3065
#define entity_storage(x)
Definition: ri.h:2794
#define entity_undefined
Definition: ri.h:2761
#define entity_type(x)
Definition: ri.h:2792
#define entity_domain
newgen_syntax_domain_defined
Definition: ri.h:410
#define entity_initial(x)
Definition: ri.h:2796
char * strdup()

References a_variable, AddEntityToDeclarations(), concatenate(), copy_storage(), copy_type(), copy_value(), entity_domain, entity_initial, entity_storage, entity_type, entity_undefined, gen_find_tabulated(), make_entity, module, module_name(), module_name_to_entity(), MODULE_SEP_STRING, new_variable, pips_assert, strdup(), and value_code_p.

Referenced by new_local_image_variable().

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

◆ commutative_operation_p()

static bool commutative_operation_p ( const dagvtx  v1,
const dagvtx  v2 
)
static
Returns
whether two vertices are commutors

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

876 {
877  if (dagvtx_optype(v1) == dagvtx_optype(v2))
878  {
879  int n1 = (int) dagvtx_opid(v1), n2 = (int) dagvtx_opid(v2);
880  const freia_api_t * f1 = get_freia_api(n1);
881  return f1->commutator && hwac_freia_api_index(f1->commutator)==n2;
882  }
883  else return false;
884 }
void const char const char const int
_int dagvtx_opid(const dagvtx v)
Definition: dag-utils.c:121
const freia_api_t * get_freia_api(int index)
Definition: freia-utils.c:477
int hwac_freia_api_index(const string function)
returns the index of the description of an AIPO function
Definition: freia-utils.c:471
FREIA API function name -> SPoC hardware description (and others?)
Definition: freia.h:71
string commutator
Definition: freia.h:77

References freia_api_t::commutator, dagvtx_opid(), dagvtx_optype(), get_freia_api(), hwac_freia_api_index(), and int.

Referenced by freia_dag_optimize().

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

◆ compatible_reduction_operation()

static int compatible_reduction_operation ( const dagvtx  v1,
const dagvtx  v2 
)
static
Returns
0 keep both, 1 keep first, 2 keep second

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

1396 {
1397  const string
1398  o1 = dagvtx_compact_operation(v1),
1399  o2 = dagvtx_compact_operation(v2);
1400  if ((same_string_p(o1, "max!") && same_string_p(o2, "max")) ||
1401  (same_string_p(o1, "min!") && same_string_p(o2, "min")))
1402  return 1;
1403  else if ((same_string_p(o1, "max") && same_string_p(o2, "max!")) ||
1404  (same_string_p(o1, "min") && same_string_p(o2, "min!")))
1405  return 2;
1406  else
1407  return 0;
1408 }
string dagvtx_compact_operation(const dagvtx v)
Definition: dag-utils.c:140

References dagvtx_compact_operation(), and same_string_p.

Referenced by freia_dag_optimize().

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

◆ compilation_unit_of_module()

string compilation_unit_of_module ( const char *  module_name)

The output is undefined if the module is referenced but not defined in the workspace, for instance because its code should be synthesized.

Fabien Coelho suggests to build a default compilation unit where all synthesized module codes would be located.

Definition at line 350 of file module.c.

351 {
353  pips_assert("only for C modules\n", entity_undefined_p(e) || c_module_p(e));
354 
355  // Should only be called for C modules.
357 
358  // The guard may not be sufficient...
359  // and this may crash in db_get_memory_resource()
360  if(db_resource_p(DBR_USER_FILE, module_name)) {
361  string source_file_name =
362  db_get_memory_resource(DBR_USER_FILE, module_name, true);
363  string simpler_file_name = pips_basename(source_file_name, PP_C_ED);
364 
365  // It is not clear how robust it is going to be
366  // when file name conflicts occur.
368  simpler_file_name);
369  free(simpler_file_name);
370  }
371 
372  return compilation_unit_name;
373 }
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524
string compilation_unit_name
cproto-generated files
Definition: c_parser.c:49
char * pips_basename(char *fullpath, char *suffix)
Definition: file.c:822
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 asprintf
Definition: misc-local.h:225
#define FILE_SEP_STRING
Definition: naming-local.h:41
#define string_undefined
Definition: newgen_types.h:40
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
#define entity_undefined_p(x)
Definition: ri.h:2762

References asprintf, c_module_p(), compilation_unit_name, db_get_memory_resource(), db_resource_p(), entity_undefined_p, FILE_SEP_STRING, free(), module_name(), module_name_to_entity(), pips_assert, pips_basename(), and string_undefined.

Referenced by actual_c_parser(), add_new_module_from_text(), build_real_resources(), cast_STEP_ARG(), create_module_with_statement(), entity_from_user_name(), entity_more_or_less_minimal_name(), freia_data2d_field(), generic_initializer(), inline_expression_call(), linearize_array_generic(), normalize_microcode(), outliner_file(), outliner_scan(), sort_parameters(), step_compile_generated_module(), step_parameter(), string_to_entity(), and update_referenced_entities().

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

◆ compute_constant()

static expression compute_constant ( string  op,
expression  val1,
expression  val2 
)
static

compute a constant expression for FREIA ??? TODO partial eval if values are constant

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

958 {
959  // rough! could/should do some partial evaluation here
961  pips_assert("operator function found", eop!=entity_undefined);
962  call c = make_call(eop,
964  CONS(expression, copy_expression(val2), NIL)));
965  return call_to_expression(c);
966 }
call make_call(entity a1, list a2)
Definition: ri.c:269
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
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
expression call_to_expression(call c)
Build an expression that call a function or procedure.
Definition: expression.c:309

References call_to_expression(), CONS, copy_expression(), entity_undefined, local_name_to_top_level_entity(), make_call(), NIL, and pips_assert.

Referenced by propagate_constant_image().

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

◆ constant_image_p()

static expression constant_image_p ( dagvtx  v)
static

whether vertex generates a constant image

Parameters
vvertex to consider
Returns
constant allocated expression or NULL

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

1160 {
1161  vtxcontent c = dagvtx_content(v);
1162  _int op = vtxcontent_opid(c);
1163  const freia_api_t * api = get_freia_api(op);
1164  if (api->arg_img_in==2)
1165  {
1166  pips_assert("2 input images", gen_length(vtxcontent_inputs(c))==2);
1167  entity e1 = ENTITY(CAR(vtxcontent_inputs(c))),
1168  e2 = ENTITY(CAR(CDR(vtxcontent_inputs(c))));
1169  if (e1==e2 && (aipo_op_p(api, "sub") || aipo_op_p(api, "xor")))
1170  return int_to_expression(0);
1171  if (e1==e2 && aipo_op_p(api, "div"))
1172  return int_to_expression(1);
1173  }
1174  else if (api->arg_img_in==1)
1175  {
1176  bool
1177  erosion = aipo_op_p(api, "erode_8c") || aipo_op_p(api, "erode_6c"),
1178  dilatation = aipo_op_p(api, "dilate_8c") || aipo_op_p(api, "dilate_6c");
1179  // aipo_op_p(api, "convolution") 3x3?
1180  if (erosion || dilatation)
1181  {
1182  _int i00, i10, i20, i01, i11, i21, i02, i12, i22;
1183  if (freia_extract_kernel_vtx(v, true, &i00, &i10, &i20,
1184  &i01, &i11, &i21, &i02, &i12, &i22))
1185  {
1186  // zero boundary
1187  if (i00==0 && i10==0 && i20==0 && i01==0 &&
1188  i21==0 && i02==0 && i12==0 && i22==0)
1189  {
1190  if (i11==0)
1191  {
1192  if (erosion)
1193  return int_to_expression(0);
1194  else if (dilatation)
1196  }
1197  }
1198  }
1199  }
1200  else if (api->arg_misc_in==1) // arith cst op
1201  {
1203  _int val;
1204  if (expression_integer_value(e1, &val))
1205  {
1206  if ((aipo_op_p(api, "mul_const") && val==0) ||
1207  (aipo_op_p(api, "and_const") && val==0) ||
1208  (aipo_op_p(api, "inf_const") && val==0) ||
1209  (aipo_op_p(api, "const_div") && val==0))
1210  return int_to_expression(val);
1211 
1212  int maxval = freia_max_pixel_value();
1213  if ((aipo_op_p(api, "sup_const") && val==maxval) ||
1214  (aipo_op_p(api, "or_const") && val==maxval) ||
1215  (aipo_op_p(api, "addsat_const") && val==maxval))
1216  return int_to_expression(val);
1217 
1218  if ((aipo_op_p(api, "subsat_const") && val==maxval))
1219  return int_to_expression(0);
1220  }
1221  }
1222  }
1223  else if (api->arg_img_in==0)
1224  {
1225  if (aipo_op_p(api, "set_constant"))
1227  }
1228  return NULL;
1229 }
#define aipo_op_p(a, name)
Definition: dag-utils.c:951
int freia_max_pixel_value(void)
Definition: freia-utils.c:594
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
Definition: freia-utils.c:2012
expression freia_get_nth_scalar_param(const dagvtx v, int n)
Definition: freia-utils.c:589
#define dagvtx_content(x)
#define vtxcontent_opid(x)
#define vtxcontent_inputs(x)
static hash_table erosion
global variable used by the dagvtx_terapix_priority function, because qsort does not allow to pass so...
size_t gen_length(const list l)
Definition: list.c:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
intptr_t _int
_INT
Definition: newgen_types.h:53
bool expression_integer_value(expression e, intptr_t *pval)
Definition: eval.c:792
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
unsigned int arg_misc_in
Definition: freia.h:83
unsigned int arg_img_in
Definition: freia.h:80

References aipo_op_p, freia_api_t::arg_img_in, freia_api_t::arg_misc_in, CAR, CDR, copy_expression(), dagvtx_content, ENTITY, erosion, expression_integer_value(), freia_extract_kernel_vtx(), freia_get_nth_scalar_param(), freia_max_pixel_value(), gen_length(), get_freia_api(), int_to_expression(), pips_assert, vtxcontent_inputs, and vtxcontent_opid.

Referenced by dag_simplify().

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

◆ 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)

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:

◆ copy_image_p()

static entity copy_image_p ( dagvtx  v)
static

tell whether vertex can be assimilated to a copy e.g.

i+.0 i*.1 i/.1 i|.0 i-.0 i&i i|i i>i i<i

Returns
image to copy, or NULL

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

1236 {
1237  vtxcontent c = dagvtx_content(v);
1238  _int op = vtxcontent_opid(c);
1239  const freia_api_t * api = get_freia_api(op);
1240  if (api->arg_img_in==2)
1241  {
1242  pips_assert("2 input images", gen_length(vtxcontent_inputs(c))==2);
1243  entity e1 = ENTITY(CAR(vtxcontent_inputs(c))),
1244  e2 = ENTITY(CAR(CDR(vtxcontent_inputs(c))));
1245  if (e1==e2 && (aipo_op_p(api, "and") ||
1246  aipo_op_p(api, "or") ||
1247  aipo_op_p(api, "sup") ||
1248  aipo_op_p(api, "inf")))
1249  return e1;
1250  }
1251  else if (api->arg_img_in==1)
1252  {
1253  if (aipo_op_p(api, "erode_8c") ||
1254  aipo_op_p(api, "erode_6c") ||
1255  aipo_op_p(api, "dilate_8c") ||
1256  aipo_op_p(api, "dilate_6c"))
1257  // aipo_op_p(api, "convolution") 3x3?
1258  {
1259  _int i00, i10, i20, i01, i11, i21, i02, i12, i22;
1260  if (freia_extract_kernel_vtx(v, true, &i00, &i10, &i20,
1261  &i01, &i11, &i21, &i02, &i12, &i22))
1262  {
1263  // zero boundary
1264  if (i00==0 && i10==0 && i20==0 && i01==0 &&
1265  i21==0 && i02==0 && i12==0 && i22==0)
1266  {
1267  if (i11==1) return ENTITY(CAR(vtxcontent_inputs(c)));
1268  }
1269  }
1270  }
1271  else if (api->arg_misc_in==1)
1272  {
1274  _int val;
1275  if (expression_integer_value(e1, &val))
1276  {
1277  if ((aipo_op_p(api, "mul_const") && val==1) ||
1278  (aipo_op_p(api, "div_const") && val==1) ||
1279  (aipo_op_p(api, "or_const") && val==0) ||
1280  (aipo_op_p(api, "add_const") && val==0) ||
1281  (aipo_op_p(api, "sub_const") && val==0) ||
1282  (aipo_op_p(api, "sup_const") && val==0))
1283  return ENTITY(CAR(vtxcontent_inputs(c)));
1284 
1285  int maxval = freia_max_pixel_value();
1286  if ((aipo_op_p(api, "inf_const") && val==maxval) ||
1287  (aipo_op_p(api, "addsat") && val==maxval))
1288  return ENTITY(CAR(vtxcontent_inputs(c)));
1289  }
1290  }
1291  else if (api->arg_misc_in==0)
1292  {
1293  if (aipo_op_p(api, "copy"))
1294  return ENTITY(CAR(vtxcontent_inputs(c)));
1295  }
1296  }
1297  return NULL;
1298 }

References aipo_op_p, freia_api_t::arg_img_in, freia_api_t::arg_misc_in, CAR, CDR, dagvtx_content, ENTITY, expression_integer_value(), freia_extract_kernel_vtx(), freia_get_nth_scalar_param(), freia_max_pixel_value(), gen_length(), get_freia_api(), pips_assert, vtxcontent_inputs, and vtxcontent_opid.

Referenced by dag_simplify(), and propagate_constant_image().

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

◆ copy_vertices()

static list copy_vertices ( list  lv)
static

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

3025 {
3026  list nl = NIL;
3027  FOREACH(dagvtx, v, lv)
3028  if (dagvtx_number(v)!=0)
3029  nl = CONS(dagvtx, v, nl);
3030  return gen_nreverse(nl);
3031 }

References CONS, dagvtx_number(), FOREACH, gen_nreverse(), and NIL.

Referenced by dag_split_connected_components().

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

◆ dag_append_freia_call()

static void dag_append_freia_call ( dag  d,
statement  s 
)
static

append statement s to dag d

of entity

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

2428 {
2429  pips_debug(5, "adding statement %" _intFMT "\n", statement_number(s));
2430 
2432 
2433  if (c && entity_freia_api_p(call_function(c)))
2434  {
2435  entity called = call_function(c);
2436  const freia_api_t * api = hwac_freia_api(entity_local_name(called));
2437  pips_assert("some api", api!=NULL);
2438  list /* of entity */ args =
2440  api->arg_img_in+api->arg_img_out);
2441 
2442  // extract arguments
2444  pips_assert("one out image max for an AIPO", api->arg_img_out<=1);
2445  if (api->arg_img_out==1)
2446  out = extract_fist_item(&args);
2447  list ins = gen_list_head(&args, api->arg_img_in);
2448  pips_assert("no more arguments", gen_length(args)==0);
2449 
2450  vtxcontent cont =
2453  (api, &vtxcontent_optype(cont), &vtxcontent_opid(cont));
2454 
2455  dagvtx nv = make_dagvtx(cont, NIL);
2456  dag_append_vertex(d, nv);
2457  }
2458  else // some other kind of statement that we may keep in the DAG
2459  {
2460  dagvtx nv =
2463  dag_vertices(d) = CONS(dagvtx, nv, dag_vertices(d));
2464  }
2465 }
dagvtx make_dagvtx(vtxcontent a1, list a2)
vtxcontent make_vtxcontent(intptr_t a1, intptr_t a2, pstatement a3, list a4, entity a5)
pstatement make_pstatement_statement(statement _field_)
static FILE * out
Definition: alias_check.c:128
static list fs_expression_list_to_entity_list(list args, int nargs)
convert the first n items in list args to entities.
Definition: dag-utils.c:2398
static entity extract_fist_item(list *lp)
extract first entity item from list.
Definition: dag-utils.c:2417
void dag_append_vertex(dag d, dagvtx nv)
append new vertex nv to dag d.
Definition: dag-utils.c:632
bool entity_freia_api_p(const entity f)
returns whether the entity is a freia API (AIPO) function.
Definition: freia-utils.c:806
const freia_api_t * hwac_freia_api(const char *function)
freia-utils.c
Definition: freia-utils.c:455
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.
Definition: freia-utils.c:545
@ spoc_type_oth
Definition: freia_spoc.h:173
#define vtxcontent_optype(x)
list gen_list_head(list *lp, int n)
Definition: list.c:1015
#define call_arguments(x)
Definition: ri.h:711
unsigned int arg_img_out
Definition: freia.h:79

References _intFMT, freia_api_t::arg_img_in, freia_api_t::arg_img_out, call_arguments, call_function, CONS, dag_append_vertex(), dag_vertices, entity_freia_api_p(), entity_local_name(), entity_undefined, extract_fist_item(), freia_spoc_set_operation(), freia_statement_to_call(), fs_expression_list_to_entity_list(), gen_length(), gen_list_head(), hwac_freia_api(), make_dagvtx(), make_pstatement_statement(), make_vtxcontent(), NIL, out, pips_assert, pips_debug, spoc_type_oth, statement_number, vtxcontent_opid, and vtxcontent_optype.

Referenced by freia_build_dag().

+ 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 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 dag_inputs(x)
bool gen_in_list_p(const void *vo, const list lx)
tell whether vo belongs to lx
Definition: list.c:734

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
@ 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
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

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 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
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)
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
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

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
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 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  module,
const string  name,
const dag  d,
const list  lb,
const list  la 
)

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

Parameters
moduleodule
nameame
lbb
laa

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
string db_get_directory_name_for_module(const char *name)
returns the allocated and mkdir'ed directory for module name
Definition: lowlevel.c:150

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  module,
const string  prefix,
int  number,
const dag  d,
const list  lb,
const list  la 
)
Parameters
moduleodule
prefixrefix
numberumber
lbb
laa

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  what,
const dag  d 
)

for dag debug

Parameters
outut
whathat

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_image_is_an_input()

static bool dag_image_is_an_input ( dag  d,
entity  img 
)
static

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

2046 {
2047  bool is_input = false;
2048  FOREACH(dagvtx, v, dag_inputs(d))
2049  {
2050  if (dagvtx_image(v)==img)
2051  {
2052  is_input = true;
2053  break;
2054  }
2055  }
2056 
2057  pips_debug(4, "image %s input: %s\n",
2058  entity_name(img), bool_to_string(is_input));
2059 
2060  return is_input;
2061 }
#define entity_name(x)
Definition: ri.h:2790

References bool_to_string(), dag_inputs, dagvtx_image(), entity_name, FOREACH, and pips_debug.

Referenced by dag_compute_outputs().

+ 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_normalize()

static bool dag_normalize ( dag  d)
static

normalize, that is use less image operators only transformation is: sub_const(i, v) -> add_const(i, -v)

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

1352 {
1353  bool changed = false;
1354  FOREACH(dagvtx, v, dag_vertices(d))
1355  {
1356  vtxcontent ct = dagvtx_content(v);
1357  statement s = dagvtx_statement(v);
1358  call c = s? freia_statement_to_call(s): NULL;
1359  if (c)
1360  {
1361  list args = call_arguments(c);
1362  entity func = call_function(c);
1363  if (same_string_p(entity_local_name(func), AIPO "sub_const"))
1364  {
1365  changed = true;
1366  // sub_const -> add_const(opposite)
1367  // does it always make sense for unsigned pixels?
1368  vtxcontent_opid(ct) = hwac_freia_api_index(AIPO "add_const");
1370  list l3 = CDR(CDR(args));
1371  _int v;
1372  if (expression_integer_value(EXPRESSION(CAR(l3)), &v))
1373  {
1374  // partial eval
1376  EXPRESSION_(CAR(l3)) = int_to_expression(-v);
1377  }
1378  else
1379  {
1380  // symbolic
1381  EXPRESSION_(CAR(l3)) =
1382  MakeUnaryCall(
1384  EXPRESSION(CAR(l3)));
1385  }
1386  }
1387  // what else?
1388  }
1389  }
1390  return changed;
1391 }
void free_expression(expression p)
Definition: ri.c:853
#define AIPO
Definition: freia.h:51
#define UNARY_MINUS_OPERATOR_NAME
expression MakeUnaryCall(entity f, expression a)
Creates a call expression to a function with one argument.
Definition: expression.c:342
#define EXPRESSION_(x)
Definition: ri.h:1220
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217

References AIPO, call_arguments, call_function, CAR, CDR, dag_vertices, dagvtx_content, dagvtx_statement(), entity_local_name(), EXPRESSION, EXPRESSION_, expression_integer_value(), FOREACH, free_expression(), freia_statement_to_call(), hwac_freia_api_index(), int_to_expression(), local_name_to_top_level_entity(), MakeUnaryCall(), same_string_p, UNARY_MINUS_OPERATOR_NAME, and vtxcontent_opid.

Referenced by freia_dag_optimize().

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

◆ dag_remove_unused_inputs()

static void dag_remove_unused_inputs ( dag  d)
static

remove unused inputs

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

552 {
553  list nl = NIL;
554  FOREACH(dagvtx, v, dag_inputs(d))
555  {
556  if (dagvtx_succs(v)!=NIL) // do we keep it?
557  nl = CONS(dagvtx, v, nl);
558  else
559  gen_remove(&dag_vertices(d), v);
560  // ??? memory leak? there may be "pointers" somewhere to these?
561  // free_dagvtx(v);
562  }
563  if (dag_inputs(d)) gen_free_list(dag_inputs(d));
564  dag_inputs(d) = gen_nreverse(nl);
565 }
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 CONS, dag_inputs, dag_vertices, dagvtx_succs, FOREACH, gen_free_list(), gen_nreverse(), gen_remove(), and NIL.

Referenced by dag_remove_vertex().

+ Here is the call graph for this function:
+ 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

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_simplify()

static bool dag_simplify ( dag  d)
static

apply basic algebraic simplification to dag

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

1303 {
1304  bool changed = false;
1305 
1306  // propagate constants and detect copies
1307  FOREACH(dagvtx, v, dag_vertices(d))
1308  {
1309  expression val;
1310  entity img;
1311  if ((val=constant_image_p(v))!=NULL)
1312  {
1313  changed = true;
1314 
1315  // fix successors of predecessors of new "constant" operation
1316  list preds = dag_vertex_preds(d, v);
1317  FOREACH(dagvtx, p, preds)
1318  gen_remove(&dagvtx_succs(p), v);
1319  gen_free_list(preds);
1320 
1321  // swich operation to constant
1322  set_aipo_constant(v, val);
1323  free_expression(val);
1324  }
1325  else if ((img=copy_image_p(v))!=NULL)
1326  {
1327  changed = true;
1328  set_aipo_copy(v, img);
1329  }
1330  // another one just for fun: I+I -> 2*I
1331  // this is good for SPoC
1332  else if (dagvtx_is_operator_p(v, "add"))
1333  {
1334  list preds = dag_vertex_preds(d, v);
1335  pips_assert("two args to add", gen_length(preds)==2);
1336  if (DAGVTX(CAR(preds))==DAGVTX(CAR(CDR(preds))))
1337  {
1338  changed = true;
1339  set_aipo_call(v, "mul_const",
1340  dagvtx_image(DAGVTX(CAR(preds))), int_to_expression(2));
1341  }
1342  }
1343  }
1344 
1345  return changed;
1346 }
static void set_aipo_call(dagvtx v, string name, entity img, expression val)
switch vertex statement to an aipo call
Definition: dag-utils.c:974
static bool dagvtx_is_operator_p(const dagvtx v, const string opname)
Definition: dag-utils.c:390
static void set_aipo_copy(dagvtx v, entity e)
switch vertex to a copy of an image
Definition: dag-utils.c:1016
static void set_aipo_constant(dagvtx, expression)
set vertex as a constant image and propagate to successors
Definition: dag-utils.c:1149
static expression constant_image_p(dagvtx)
whether vertex generates a constant image
Definition: dag-utils.c:1159
static entity copy_image_p(dagvtx)
tell whether vertex can be assimilated to a copy e.g.
Definition: dag-utils.c:1235

References CAR, CDR, constant_image_p(), copy_image_p(), dag_vertex_preds(), dag_vertices, DAGVTX, dagvtx_image(), dagvtx_is_operator_p(), dagvtx_succs, FOREACH, free_expression(), gen_free_list(), gen_length(), gen_remove(), int_to_expression(), pips_assert, set_aipo_call(), set_aipo_constant(), and set_aipo_copy().

Referenced by freia_dag_optimize().

+ 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
#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  d 
)

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 }

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_stats()

static set dag_stats ( dag  d)
static
Returns
the set of all statements in dag

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

1974 {
1975  set stats = set_make(set_pointer);
1976  statement s;
1977  FOREACH(dagvtx, v, dag_vertices(d))
1978  if ((s = dagvtx_statement(v)))
1979  set_add_element(stats, stats, s);
1980  return stats;
1981 }

References dag_vertices, dagvtx_statement(), FOREACH, set_add_element(), set_make(), and set_pointer.

Referenced by dag_compute_outputs().

+ 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 }

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_cmp_entity()

static int dagvtx_cmp_entity ( const dagvtx v1,
const dagvtx v2 
)
static

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

519 {
522 }
int compare_entities(const entity *pe1, const entity *pe2)
Comparison function for qsort.
Definition: entity.c:1328

References compare_entities(), dagvtx_content, and vtxcontent_out.

Referenced by vertex_list_sorted_by_entities().

+ 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  v)

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 }
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_copy_list_dot()

static void dagvtx_copy_list_dot ( FILE *  out,
const list  ls,
const set  inputs 
)
static

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

351 {
352  FOREACH(statement, s, ls)
353  {
355  if (c && same_string_p(entity_local_name(call_function(c)), AIPO "copy"))
356  {
357  list args = call_arguments(c);
358  pips_assert("two args to aipo copy", gen_length(args)==2);
361  fprintf(out,
362  " \"%s%s\" [shape=circle];\n"
363  " \"%s =\" [shape=circle,label=\"=\",style=\"dashed\"]\n"
364  " \"%s%s\" -> \"%s =\";\n"
365  " \"%s =\" -> \"%s%s\";\n",
366  entity_dot_name(dst), set_belong_p(inputs, dst)? "'": "",
367  entity_dot_name(dst),
368  entity_dot_name(src), set_belong_p(inputs, src)? "'": "",
369  entity_dot_name(dst), entity_dot_name(dst),
370  entity_dot_name(dst), set_belong_p(inputs, dst)? "'": "");
371  }
372  // should not be a else?
373  }
374 }
#define src(name, suf)
HPFC by Fabien Coelho, May 1993 and later...
Definition: compile.c:41
entity expression_to_entity(expression e)
just returns the entity of an expression, or entity_undefined
Definition: expression.c:3140

References AIPO, call_arguments, call_function, CAR, CDR, entity_dot_name(), entity_local_name(), EXPRESSION, expression_to_entity(), FOREACH, fprintf(), freia_statement_to_call(), gen_length(), out, pips_assert, same_string_p, set_belong_p(), and src.

Referenced by dag_dot().

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

◆ dagvtx_dot()

static void dagvtx_dot ( FILE *  out,
const dag  d,
const dagvtx  vtx 
)
static

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

253 {
254  // collect prettyprint properties
255  bool label_nodes = get_bool_property("FREIA_DAG_LABEL_NODES");
256  bool show_arcs = get_bool_property("FREIA_DAG_LABEL_ARCS");
257  bool filter_nodes = get_bool_property("FREIA_DAG_FILTER_NODES");
258 
259  vtxcontent co = dagvtx_content(vtx);
260  const char* vname = NULL;
262  vname = entity_dot_name(vtxcontent_out(co));
263 
264  if (dagvtx_number(vtx)==0)
265  {
266  // this is an input image, only image dependencies
267  FOREACH(dagvtx, succ, dagvtx_succs(vtx))
268  {
269  fprintf(out, " \"%s\"", vname);
270  dagvtx_dot_node(out, " -> ", succ);
271  fprintf(out, ";\n");
272  }
273  }
274  else
275  {
276  // we are dealing with a computation...
277  string attribute = what_operation_shape(vtxcontent_optype(co));
279  bool some_arcs = false;
280 
281  // first check for image dependencies
282  FOREACH(dagvtx, succ, dagvtx_succs(vtx))
283  {
284  dagvtx_dot_node_sb(sa, " ", vtx);
285  dagvtx_dot_node_sb(sa, " -> ", succ);
286  sb_cat(sa, show_arcs? " [label=\"": "",
287  show_arcs? vname: "", show_arcs? "\"]": "", ";\n");
288  some_arcs = true;
289  }
290 
291  // then scalar dependencies anywhere... hmmm...
292  FOREACH(dagvtx, v, dag_vertices(d))
293  {
294  list vars = NIL;
295  if (// another vertex
296  vtx!=v &&
297  // with dependencies
299  dagvtx_statement(v), &vars))
300  {
301  // show scalar dep in sequence order
302  if (dagvtx_number(v)>dagvtx_number(vtx))
303  {
304  dagvtx_dot_node_sb(sa, " ", vtx);
305  dagvtx_dot_node_sb(sa, " -> ", v);
306  }
307  else
308  {
309  dagvtx_dot_node_sb(sa, " ", v);
310  dagvtx_dot_node_sb(sa, " -> ", vtx);
311  }
312 
313  sb_cat(sa, " [" SCL_DEP);
314 
315  if (vars && show_arcs)
316  {
317  int count = 0;
318  sb_cat(sa, ",label=\"");
319  FOREACH(entity, var, vars)
320  sb_cat(sa, count++? " ": "", entity_dot_name(var));
321  sb_cat(sa, "\"");
322  }
323  sb_cat(sa, "];\n");
324 
325  some_arcs = true;
326  }
327  gen_free_list(vars), vars = NIL;
328  }
329 
330  bool some_image_stuff = !dagvtx_other_stuff_p(vtx);
331 
332  if (!filter_nodes || some_image_stuff || (filter_nodes && some_arcs))
333  {
334  // appends the node description
335  dagvtx_dot_node(out, " ", vtx);
336  fprintf(out, " [%s", attribute);
337  if (!label_nodes)
338  // show a short label with only the operation
339  fprintf(out, ",label=\"%s\"", dagvtx_compact_operation(vtx));
340  fprintf(out, "];\n");
341  // now appends arcs...
343  }
344 
345  // cleanup
346  string_buffer_free(&sa);
347  }
348 }
#define SCL_DEP
Definition: dag-utils.c:231
static void dagvtx_dot_node_sb(string_buffer sb, const string prefix, const dagvtx v)
Definition: dag-utils.c:245
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
string what_operation_shape(const _int type)
SPoC: set shape depending on hardware component used by vertex.
Definition: freia-utils.c:518
#define sb_cat(args...)
Definition: freia.h:42
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
internally defined structure.
Definition: string_buffer.c:47

References count, dag_vertices, dagvtx_compact_operation(), dagvtx_content, dagvtx_dot_node(), dagvtx_dot_node_sb(), dagvtx_number(), dagvtx_other_stuff_p(), dagvtx_statement(), dagvtx_succs, entity_dot_name(), entity_undefined, FOREACH, fprintf(), freia_scalar_rw_dep(), gen_free_list(), get_bool_property(), NIL, out, sb_cat, SCL_DEP, string_buffer_free(), string_buffer_make(), string_buffer_to_file(), vtxcontent_optype, vtxcontent_out, and what_operation_shape().

Referenced by dag_dot().

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

◆ dagvtx_dot_node()

static void dagvtx_dot_node ( FILE *  out,
const string  prefix,
const dagvtx  v 
)
static

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

239 {
240  fprintf(out, "%s\"%"_intFMT" %s\"", prefix? prefix: "",
242 }

References _intFMT, dagvtx_compact_operation(), dagvtx_number(), fprintf(), out, and prefix.

Referenced by dag_dot(), and dagvtx_dot().

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

◆ dagvtx_dot_node_sb()

static void dagvtx_dot_node_sb ( string_buffer  sb,
const string  prefix,
const dagvtx  v 
)
static

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

246 {
247  sb_cat(sb, prefix? prefix: "");
248  sb_cat(sb, "\"", i2a((int) dagvtx_number(v)),
249  " ", dagvtx_compact_operation(v), "\"");
250 }
Definition: statement.c:4047

References dagvtx_compact_operation(), dagvtx_number(), i2a(), prefix, and sb_cat.

Referenced by dagvtx_dot().

+ 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  name,
const dagvtx  v 
)

for dag debug.

Parameters
outut
nameame

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 statement_ordering(x)
Definition: ri.h:2454

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  v)

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  v)

◆ dagvtx_is_copy_p()

static bool dagvtx_is_copy_p ( const dagvtx  v)
static

returns whether the vertex is an image copy operation.

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

400 {
401  return dagvtx_is_operator_p(v, "copy");
402 }

References dagvtx_is_operator_p().

Referenced by all_vertices_are_copies_or_measures_p(), dag_dot(), freia_dag_optimize(), and number_of_copies().

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

◆ dagvtx_is_measurement_p()

bool dagvtx_is_measurement_p ( const dagvtx  v)

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 }

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_is_operator_p()

static bool dagvtx_is_operator_p ( const dagvtx  v,
const string  opname 
)
static

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

391 {
392  vtxcontent c = dagvtx_content(v);
393  const freia_api_t * api = get_freia_api(vtxcontent_opid(c));
394  return same_string_p(cat(AIPO, opname), api->function_name);
395 }
static const char * opname(const char *s)

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

Referenced by dag_simplify(), and dagvtx_is_copy_p().

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

◆ dagvtx_list_dot()

static void dagvtx_list_dot ( FILE *  out,
const string  comment,
const list  l,
const set  used 
)
static

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

378 {
379  if (comment) fprintf(out, " // %s\n", comment);
380  FOREACH(dagvtx, v, l)
381  {
383  fprintf(out, " \"%s%s\" [shape=circle];\n",
384  entity_dot_name(img),
385  used? (set_belong_p(used, img)? "'": ""): "");
386  }
387  fprintf(out, "\n");
388 }
static void comment(string_buffer code, spoc_hardware_type hw, dagvtx v, int stage, int side, bool flip)
Definition: freia_spoc.c:52

References comment(), dagvtx_content, entity_dot_name(), FOREACH, fprintf(), out, set_belong_p(), and vtxcontent_out.

Referenced by dag_dot().

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

◆ dagvtx_nb()

static string dagvtx_nb ( const void *  s)
static

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

2931  {
2932  return i2a((int) dagvtx_number((dagvtx) s));
2933 }

References dagvtx_number(), and i2a().

Referenced by dag_connected_component(), and dag_split_connected_components().

+ 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  what,
const list  l 
)
Parameters
outut
whathat

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  v)

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  v)

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  v)

◆ 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  v)

a vertex with a non AIPO or image related statement.

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

77 {
79 }

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  v)

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:

◆ do_point_to()

static expression do_point_to ( entity  var,
string  field_name 
)
static

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

2534 {
2535  // entity f2d = local_name_to_top_level_entity(FREIA_IMAGE_TYPE);
2536  expression evar = entity_to_expression(var);
2541  NULL)));
2542 }
static entity freia_data2d_field(string field)
Definition: dag-utils.c:2513
list gen_make_list(int domain,...)
Definition: list.c:851
#define POINT_TO_OPERATOR_NAME
Definition: ri-util-local.h:92
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154

References call_to_expression(), entity_to_expression(), expression_domain, freia_data2d_field(), gen_make_list(), local_name_to_top_level_entity(), make_call(), and POINT_TO_OPERATOR_NAME.

Referenced by new_local_image_variable().

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

◆ entity_dot_name()

static const char* entity_dot_name ( entity  e)
static

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

234 {
235  return entity_user_name(e);
236 }
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487

References entity_user_name().

Referenced by dag_dot(), dagvtx_copy_list_dot(), dagvtx_dot(), and dagvtx_list_dot().

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

◆ entity_list_dump()

static void entity_list_dump ( FILE *  out,
const string  what,
const list  l 
)
static

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

89 {
90  fprintf(out, "%s: ", what);
91  FOREACH(entity, e, l)
92  fprintf(out, " %s,", safe_entity_name(e));
93  fprintf(out, "\n");
94 }

References FOREACH, fprintf(), out, and safe_entity_name().

Referenced by dagvtx_dump().

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

◆ extract_fist_item()

static entity extract_fist_item ( list lp)
static

extract first entity item from list.

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

2418 {
2419  list l = gen_list_head(lp, 1);
2420  entity e = ENTITY(CAR(l));
2421  gen_free_list(l);
2422  return e;
2423 }

References CAR, ENTITY, gen_free_list(), and gen_list_head().

Referenced by dag_append_freia_call().

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

◆ find_twin_vertex()

static dagvtx find_twin_vertex ( dag  d,
dagvtx  target 
)
static

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

2149 {
2150  // pips_debug(9, "target is %"_intFMT"\n", dagvtx_number(target));
2151  FOREACH(dagvtx, v, dag_vertices(d))
2152  if (dagvtx_number(target)==dagvtx_number(v))
2153  return v;
2154  pips_internal_error("twin vertex not found for %" _intFMT "\n",
2155  dagvtx_number(target));
2156  return NULL;
2157 }
#define pips_internal_error
Definition: misc-local.h:149

References _intFMT, dag_vertices, dagvtx_number(), FOREACH, and pips_internal_error.

Referenced by freia_hack_fix_global_ins_outs().

+ Here is the call graph for this function:
+ 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
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

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_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
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
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
hash_table hash_table_make(hash_key_type key_type, size_t size)
Definition: hash.c:294
void * hash_get(const hash_table htp, const void *key)
this function retrieves in the hash table pointed to by htp the couple whose key is equal to key.
Definition: hash.c:449
void hash_table_free(hash_table htp)
this function deletes a hash table that is no longer useful.
Definition: hash.c:327
bool hash_defined_p(const hash_table htp, const void *key)
true if key has e value in htp.
Definition: hash.c:484
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
@ hash_pointer
Definition: newgen_hash.h:32
set set_intersection(set, const set, const set)
Definition: set.c:229
set set_union(set, const set, const set)
Definition: set.c:211

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_data2d_field()

static entity freia_data2d_field ( string  field)
static

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

2514 {
2515  string cu =
2518  pips_assert("freia_data2d type found", fi!=entity_undefined);
2519  type ut = ultimate_type(entity_type(fi));
2520 
2521  list fields =
2523  pips_assert("some fields", fields);
2524  FOREACH(entity, f, fields)
2525  if (same_string_p(field,
2527  return f;
2528  // should not get there
2529  pips_internal_error("cannot find freia_data2d field %s\n", field);
2530  return NULL;
2531 }
string compilation_unit_of_module(const char *)
The output is undefined if the module is referenced but not defined in the workspace,...
Definition: module.c:350
#define FREIA_IMAGE_TYPE
Definition: freia.h:46
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define DUMMY_STRUCT_PREFIX
Definition: naming-local.h:87
#define TYPEDEF_PREFIX
Definition: naming-local.h:62
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
type ultimate_type(type)
Definition: type.c:3466
#define type_struct(x)
Definition: ri.h:2964
#define basic_derived(x)
Definition: ri.h:640
#define type_variable(x)
Definition: ri.h:2949
#define variable_basic(x)
Definition: ri.h:3120

References basic_derived, compilation_unit_of_module(), DUMMY_STRUCT_PREFIX, entity_local_name(), entity_type, entity_undefined, f(), FindOrCreateEntity(), FOREACH, FREIA_IMAGE_TYPE, get_current_module_entity(), pips_assert, pips_internal_error, same_string_p, type_struct, type_variable, TYPEDEF_PREFIX, ultimate_type(), and variable_basic.

Referenced by do_point_to().

+ 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_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
sequence statement_sequence(statement)
Get the sequence of a statement sequence.
Definition: statement.c:1328
call statement_call(statement)
Get the call of a statement.
Definition: statement.c:1406
bool statement_sequence_p(statement)
Statement classes induced from instruction type.
Definition: statement.c:335
#define ENTITY_ASSIGN_P(e)
#define reference_domain
newgen_range_domain_defined
Definition: ri.h:338
#define sequence_statements(x)
Definition: ri.h:2360
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413

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_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
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
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58

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:

◆ fs_expression_list_to_entity_list()

static list fs_expression_list_to_entity_list ( list  args,
int  nargs 
)
static

convert the first n items in list args to entities.

of entity

Parameters
argsof expression

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

2399 {
2400  list /* of entity */ lent = NIL;
2401  int n=0;
2402  FOREACH(expression, ex, args)
2403  {
2404  syntax s = expression_syntax(ex);
2405  pips_assert("is a ref", syntax_reference_p(s));
2406  reference r = syntax_reference(s);
2407  pips_assert("simple ref", reference_indices(r)==NIL);
2408  lent = CONS(entity, reference_variable(r), lent);
2409  if (++n==nargs) break;
2410  }
2411  lent = gen_nreverse(lent);
2412  return lent;
2413 }
#define syntax_reference_p(x)
Definition: ri.h:2728
#define syntax_reference(x)
Definition: ri.h:2730
#define reference_variable(x)
Definition: ri.h:2326
#define reference_indices(x)
Definition: ri.h:2328
#define expression_syntax(x)
Definition: ri.h:1247

References CONS, expression_syntax, FOREACH, gen_nreverse(), NIL, pips_assert, reference_indices, reference_variable, syntax_reference, and syntax_reference_p.

Referenced by dag_append_freia_call().

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

◆ gen_list_equals_p()

static bool gen_list_equals_p ( const list  l1,
const list  l2 
)
static

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

708 {
709  bool equal = true;
710  list p1 = (list) l1, p2 = (list) l2;
711  while (equal && p1 && p2) {
712  if (CHUNK(CAR(p1))!=CHUNK(CAR(p2)))
713  equal = false;
714  p1 = CDR(p1), p2 = CDR(p2);
715  }
716  equal &= (!p1 && !p2);
717  return equal;
718 }
#define CHUNK(x)
Definition: genC.h:90
struct cons * list
Definition: newgen_types.h:106

References CAR, CDR, and CHUNK.

Referenced by freia_dag_optimize().

+ Here is the caller graph for this function:

◆ get_upper_model()

static entity get_upper_model ( entity  model,
const hash_table  occs 
)
static

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

2561 {
2562  entity image = NULL;
2563  // first look in declarations
2566  // then look for statements...
2567  if (!image && hash_defined_p(occs, model))
2568  {
2569  SET_FOREACH(statement, s, (set) hash_get(occs, model))
2570  {
2571  if (is_freia_alloc(s))
2574  if (image && image!=model) break;
2575  image = NULL;
2576  }
2577  }
2578  // go upwards!
2579  if (image && image!=model) image = get_upper_model(image, occs);
2580  return image? image: model;
2581 }
static entity get_upper_model(entity model, const hash_table occs)
Definition: dag-utils.c:2560

References entity_initial, freia_statement_to_call(), gen_context_recurse, gen_null2(), hash_defined_p(), hash_get(), image_ref_flt(), is_freia_alloc(), reference_domain, and SET_FOREACH.

Referenced by new_local_image_variable().

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

◆ image_ref_flt()

static bool image_ref_flt ( reference  r,
entity image 
)
static

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

2548 {
2549  entity var = reference_variable(r);
2550  if (freia_image_variable_p(var))
2551  {
2552  *image = var;
2553  gen_recurse_stop(NULL);
2554  }
2555  // do not go in array indexes
2556  return false;
2557 }
bool freia_image_variable_p(const entity var)
rather approximative?
Definition: freia-utils.c:768
void gen_recurse_stop(void *obj)
Tells the recursion not to go in this object.
Definition: genClib.c:3251

References freia_image_variable_p(), gen_recurse_stop(), and reference_variable.

Referenced by freia_memory_management_statement(), and get_upper_model().

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

◆ list_commuted_p()

static bool list_commuted_p ( const list  l1,
const list  l2 
)
static
Returns
whether two lists are commuted

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

889 {
890  pips_assert("length 2", gen_length(l1)==2 && gen_length(l2)==2);
891  return CHUNKP(CAR(CDR(l1)))==CHUNKP(CAR(l2)) &&
892  CHUNKP(CAR(l1))==CHUNKP(CAR(CDR(l2)));
893 }
#define CHUNKP(x)
Definition: genC.h:92

References CAR, CDR, CHUNKP, gen_length(), and pips_assert.

Referenced by freia_dag_optimize().

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

◆ new_local_image_variable()

static entity new_local_image_variable ( entity  model,
const hash_table  occs 
)
static
Returns
a new image from the model

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

2627 {
2628  entity img = NULL;
2629  int index = 1;
2630  do
2631  {
2632  string varname;
2633  int n = asprintf(&varname, "%s_%d", entity_local_name(model), index);
2634  pips_assert("asprintf succeeded", n!=-1);
2636  (model, varname, module_local_name(get_current_module_entity()));
2637  free(varname);
2638  index++;
2639  if (img)
2640  {
2641  // use the reference of the model instead of the model itself, if found.
2642  entity ref = get_upper_model(model, occs);
2643 
2646  do_point_to(ref, "bpp"),
2647  do_point_to(ref, "widthWa"),
2648  do_point_to(ref, "heightWa"),
2649  NULL));
2650 
2651  // handle allocation as the declaration initial value, if possible
2652  if (formal_parameter_p(ref))
2653  {
2654  free_value(entity_initial(img));
2656  }
2657  else
2658  {
2660 
2661  if (sa)
2662  {
2663  // insert statement just after the reference declaration
2664  free_value(entity_initial(img));
2666 
2669  insert_statement(sa, na, false);
2670  }
2671  else
2672  {
2673  // this may happen if the "ref" is allocated at its declaration point,
2674  // as this statement is not currently found by our search
2675 
2676  // ??? try with a direct declaration
2677  free_value(entity_initial(img));
2678  entity_initial(img) =
2680  }
2681  }
2682 
2683  // should not be a parameter! overwrite storage if so...
2684  if (formal_parameter_p(img))
2685  {
2688  // make_storage_ram(make_ram(get_current_module_entity(),
2689  // entity_undefined, UNKNOWN_RAM_OFFSET, NIL));
2690  }
2691  }
2692  }
2693  while (img==NULL);
2694  return img;
2695 }
value make_value_expression(expression _field_)
Definition: ri.c:2850
storage make_storage_rom(void)
Definition: ri.c:2285
void free_storage(storage p)
Definition: ri.c:2231
void free_value(value p)
Definition: ri.c:2787
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
entity clone_variable_with_new_name(entity, const char *, const char *)
This function build and return new variable from a variable a_variable, with name new_name.
Definition: phrase_tools.c:269
statement freia_memory_management_statement(entity image, const hash_table occs, bool alloc)
Definition: dag-utils.c:2587
static expression do_point_to(entity var, string field_name)
Definition: dag-utils.c:2533
statement make_assign_statement(expression, expression)
Definition: statement.c:583
void insert_statement(statement, statement, bool)
This is the normal entry point.
Definition: statement.c:2570
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582

References alloc(), asprintf, call_to_expression(), clone_variable_with_new_name(), do_point_to(), entity_initial, entity_local_name(), entity_storage, entity_to_expression(), expression_domain, formal_parameter_p(), free(), free_storage(), free_value(), FREIA_ALLOC, freia_memory_management_statement(), gen_make_list(), get_current_module_entity(), get_upper_model(), insert_statement(), int_to_expression(), local_name_to_top_level_entity(), make_assign_statement(), make_call(), make_storage_rom(), make_value_expression(), module_local_name(), pips_assert, and ref.

Referenced by dag_fix_image_reuse().

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

◆ number_of_copies()

static int number_of_copies ( list  l)
static
Returns
the number of copies in the vertex list
Parameters
lof dagvtx

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

942 {
943  int n=0;
944  FOREACH(dagvtx, v, l)
945  if (dagvtx_is_copy_p(v))
946  n++;
947  return n;
948 }

References dagvtx_is_copy_p(), and FOREACH.

Referenced by freia_dag_optimize().

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

◆ other_significant_uses()

static bool other_significant_uses ( entity  e,
const hash_table  occs,
const set  stats 
)
static
Returns
whether there is a significant use of e outside of stats

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

2011 {
2012  if (!occs) return true; // safe
2013  set all_stats = (set) hash_get(occs, e);
2014  pips_assert("some statement set", all_stats);
2015  set others = set_make(set_pointer);
2016  set_difference(others, all_stats, stats);
2017  // is there something significant in others?
2018  bool used = any_use_statement(others);
2019  set_free(others);
2020  pips_debug(9, "%s is %susefull\n", entity_name(e), used? "": "not ");
2021  return used;
2022 }
static bool any_use_statement(set stats)
hmmm...
Definition: dag-utils.c:1987
struct _set_chunk * set
Definition: newgen_set.h:38
set set_difference(set, const set, const set)
Definition: set.c:256

References any_use_statement(), entity_name, hash_get(), pips_assert, pips_debug, set_difference(), set_free(), set_make(), and set_pointer.

Referenced by dag_compute_outputs().

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

◆ propagate_constant_image()

static bool propagate_constant_image ( dagvtx  v,
entity  image,
expression  val 
)
static

recursively propagate a constant image on a vertex

Parameters
vstarting vertex
imagewhich is constant
valactual value of all image pixels
Returns
whether v can be unlinked ??? small memory leaks

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

1056 {
1057  vtxcontent c = dagvtx_content(v);
1058  _int op = vtxcontent_opid(c);
1060  if (op<=0) return false;
1061  // op>0
1062  const freia_api_t * api = get_freia_api(op);
1063  int noccs = gen_occurences(image, vtxcontent_inputs(c));
1064  pips_assert("image is used at least once", noccs>0);
1065  int nargs = gen_length(vtxcontent_inputs(c));
1066  bool image_is_first = ENTITY(CAR(vtxcontent_inputs(c)))==image;
1067 
1068  if (copy_image_p(v)!=NULL)
1069  {
1071  set_aipo_copy(v, image);
1072  return false;
1073  }
1074 
1075  if (noccs==1 && nargs==1) // Cst(n)<op>.m => Cst(n<op>m)
1076  {
1077  string op = NULL;
1078  if (aipo_op_p(api, "add_const")) op = "+";
1079  else if (aipo_op_p(api, "sub_const")) op = "-";
1080  else if (aipo_op_p(api, "mul_const")) op = "*";
1081  else if (aipo_op_p(api, "div_const")) op = "/";
1082  else if (aipo_op_p(api, "and_const")) op = BITWISE_AND_OPERATOR_NAME;
1083  else if (aipo_op_p(api, "or_const")) op = "|";
1084  else if (aipo_op_p(api, "xor_const")) op = BITWISE_XOR_OPERATOR_NAME;
1085  // ??? TODO addsat, subsat, inf, sup, not, log2...
1086  // but I need the corresponding scalar functions
1087  // some of which depends on the actual pixel type
1088  else if (aipo_op_p(api, "erode_6c") || aipo_op_p(api, "dilate_6c") ||
1089  aipo_op_p(api, "erode_8c") || aipo_op_p(api, "dilate_8c"))
1090  newval = val;
1091  // ??? TODO threshold
1092  // ??? TODO global_min/global_max can be switch to a simple assign
1093  // ??? TODO global_vol can be switched to n_pixels*val
1094 
1095  if (op)
1096  newval = compute_constant(op, val, freia_get_nth_scalar_param(v, 1));
1097  if (newval!=expression_undefined)
1098  {
1099  set_aipo_constant(v, newval);
1100  return true;
1101  }
1102  }
1103  else if (noccs==1 && nargs==2)
1104  {
1105  string op = NULL;
1106  entity other = image_is_first?
1108 
1109  if (aipo_op_p(api, "add")) op = "add_const";
1110  else if (aipo_op_p(api, "mul")) op = "mul_const";
1111  else if (aipo_op_p(api, "and")) op = "add_const";
1112  else if (aipo_op_p(api, "or")) op = "or_const";
1113  else if (aipo_op_p(api, "xor")) op = "xor_const";
1114  else if (aipo_op_p(api, "inf")) op = "inf_const";
1115  else if (aipo_op_p(api, "sup")) op = "sup_const";
1116  else if (aipo_op_p(api, "addsat")) op = "addsat_const";
1117  else if (aipo_op_p(api, "subsat")) op = "subsat_const";
1118  else if (aipo_op_p(api, "absdiff")) op = "absdiff_const";
1119  else if (aipo_op_p(api, "sub"))
1120  op = image_is_first? "const_sub": "sub_const";
1121  else if (aipo_op_p(api, "div"))
1122  op = image_is_first? "const_div": "div_const";
1123 
1124  if (op)
1125  {
1126  set_aipo_call(v, op, other, val);
1127  return true;
1128  }
1129  }
1130  else if (noccs==2)
1131  {
1132  // special case for (image <op> image)
1133  if (aipo_op_p(api, "add"))
1134  {
1136  return true;
1137  }
1138  else if (aipo_op_p(api, "sub"))
1139  {
1141  return true;
1142  }
1143  }
1144  return false;
1145 }
static expression compute_constant(string op, expression val1, expression val2)
compute a constant expression for FREIA ??? TODO partial eval if values are constant
Definition: dag-utils.c:957
static void propagate_constant_image_to_succs(dagvtx v, expression val)
propagate constant image to vertex successors
Definition: dag-utils.c:1031
#define BITWISE_XOR_OPERATOR_NAME
#define BITWISE_AND_OPERATOR_NAME
#define expression_undefined
Definition: ri.h:1223

References aipo_op_p, BITWISE_AND_OPERATOR_NAME, BITWISE_XOR_OPERATOR_NAME, CAR, CDR, compute_constant(), copy_image_p(), dagvtx_content, ENTITY, expression_undefined, freia_get_nth_scalar_param(), gen_length(), gen_occurences(), get_freia_api(), int_to_expression(), pips_assert, propagate_constant_image_to_succs(), set_aipo_call(), set_aipo_constant(), set_aipo_copy(), vtxcontent_inputs, and vtxcontent_opid.

Referenced by propagate_constant_image_to_succs().

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

◆ propagate_constant_image_to_succs()

static void propagate_constant_image_to_succs ( dagvtx  v,
expression  val 
)
static

propagate constant image to vertex successors

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

1032 {
1033  vtxcontent c = dagvtx_content(v);
1034  list nsuccs = NIL;
1035  // i=? -> i+i => to identical successors, but forward once
1037  FOREACH(dagvtx, s, dagvtx_succs(v))
1038  {
1039  if (!set_belong_p(seen, s) &&
1041  nsuccs = CONS(dagvtx, s, nsuccs);
1042  set_add_element(seen, seen, s);
1043  }
1044  set_free(seen);
1045  dagvtx_succs(v) = gen_nreverse(nsuccs);
1046 }
static bool propagate_constant_image(dagvtx, entity, expression)
recursively propagate a constant image on a vertex
Definition: dag-utils.c:1055

References CONS, dagvtx_content, dagvtx_succs, FOREACH, gen_nreverse(), NIL, propagate_constant_image(), seen, set_add_element(), set_belong_p(), set_free(), set_make(), set_pointer, and vtxcontent_out.

Referenced by propagate_constant_image(), and set_aipo_constant().

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

◆ same_operation_p()

static bool same_operation_p ( const dagvtx  v1,
const dagvtx  v2 
)
static
Returns
whether two vertices are the same operation

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

867 {
868  return
869  dagvtx_optype(v1) == dagvtx_optype(v2) &&
870  dagvtx_opid(v1) == dagvtx_opid(v2);
871 }

References dagvtx_opid(), and dagvtx_optype().

Referenced by freia_dag_optimize().

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

◆ set_aipo_call()

static void set_aipo_call ( dagvtx  v,
string  name,
entity  img,
expression  val 
)
static

switch vertex statement to an aipo call

Parameters
vvertex to modify
namefunction short name to switch to, must be an AIPO function
imgpossible image argument, may be entity_undefined or NULL
valpossible scalar argument, may be expression undefined or NULL

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

975 {
976  vtxcontent c = dagvtx_content(v);
978  pips_assert("some statement!", pstatement_statement_p(ps));
979 
980  // build function name
981  string fname = strdup(cat(AIPO, name));
982 
983  // remove previous image inputs
985  vtxcontent_inputs(c) =
986  (img && img!=entity_undefined)? CONS(entity, img, NIL): NIL;
987 
988  // set id & type
990  pips_assert("function index found", vtxcontent_opid(c)!=-1);
991  vtxcontent_optype(c) =
992  same_string_p(name, "copy")? spoc_type_nop: spoc_type_alu;
993 
994  // set call
997  pips_assert("AIPO function found", func!=entity_undefined);
998  call_function(cf) = func;
999 
1000  // build expression list in reverse order
1001  list args = NIL;
1002  if (val && val!=expression_undefined)
1003  args = CONS(expression, copy_expression(val), args);
1004  if (img && img!=entity_undefined)
1005  args = CONS(expression, entity_to_expression(img), args);
1007  // with a bold memory leak (effects may use refs?)
1008  call_arguments(cf) = args;
1009 
1010  // cleanup
1011  free(fname);
1012 }
@ spoc_type_nop
Definition: freia_spoc.h:174
@ spoc_type_alu
Definition: freia_spoc.h:177

References AIPO, call_arguments, call_function, cat, CONS, copy_expression(), dagvtx_content, entity_to_expression(), entity_undefined, expression_undefined, free(), freia_statement_to_call(), gen_free_list(), hwac_freia_api_index(), local_name_to_top_level_entity(), NIL, pips_assert, pstatement_statement, pstatement_statement_p, same_string_p, spoc_type_alu, spoc_type_nop, strdup(), vtxcontent_inputs, vtxcontent_opid, vtxcontent_optype, vtxcontent_out, and vtxcontent_source.

Referenced by dag_simplify(), propagate_constant_image(), set_aipo_constant(), and set_aipo_copy().

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

◆ set_aipo_constant()

static void set_aipo_constant ( dagvtx  v,
expression  val 
)
static

set vertex as a constant image and propagate to successors

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

1150 {
1151  set_aipo_call(v, "set_constant", entity_undefined, val);
1153 }

References entity_undefined, propagate_constant_image_to_succs(), and set_aipo_call().

Referenced by dag_simplify(), and propagate_constant_image().

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

◆ set_aipo_copy()

static void set_aipo_copy ( dagvtx  v,
entity  e 
)
static

switch vertex to a copy of an image

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

1017 {
1018  set_aipo_call(v, "copy", e, NULL);
1019 }

References set_aipo_call().

Referenced by dag_simplify(), and propagate_constant_image().

+ 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:

◆ substitute_image_in_statement()

static void substitute_image_in_statement ( dagvtx  v,
entity  source,
entity  target,
bool  used 
)
static

subtitute produced or used image in the statement of vertex v.

Parameters
vvertex
sourceimage variable to replace
targetnew image variable to use
usedwhether to replace used image (input, forward propagation) or procuded image (output, backward propagation)

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

774 {
775  pips_debug(8, "image %s -> %s in %"_intFMT"\n",
776  entity_name(source), entity_name(target), dagvtx_number(v));
777 
778  int nsubs=0;
779  vtxcontent vc = dagvtx_content(v);
780  pstatement ps = vtxcontent_source(vc);
781  pips_assert("is a statement", pstatement_statement_p(ps));
782 
783  // get call
785  list args = call_arguments(c);
786 
787  const freia_api_t * api = dagvtx_freia_api(v);
788 
789  // how many argument to skip, how many to replace
790  unsigned int skip, subs;
791 
792  if (used)
793  skip = api->arg_img_out, subs = api->arg_img_in;
794  else
795  skip = 0, subs = api->arg_img_out;
796 
797  pips_assert("call length is okay", gen_length(args)>=skip+subs);
798 
799  while (skip--)
800  args = CDR(args);
801 
802  while (subs--)
803  {
804  expression e = EXPRESSION(CAR(args));
805  // I'm not sure what to do if an image is not a simple reference...
806  pips_assert("image argument is a reference", expression_reference_p(e));
808 
809  if (reference_variable(r)==source)
810  nsubs++, reference_variable(r) = target;
811  args = CDR(args);
812  }
813 
814  // ??? Hmmm... this happens in freia_3muls, not sure why.
815  // pips_assert("some image substitutions", nsubs>0);
816 }
#define dagvtx_freia_api(v)
Definition: freia.h:97
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

References _intFMT, freia_api_t::arg_img_in, freia_api_t::arg_img_out, call_arguments, CAR, CDR, dagvtx_content, dagvtx_freia_api, dagvtx_number(), entity_name, EXPRESSION, expression_reference(), expression_reference_p(), freia_statement_to_call(), gen_length(), pips_assert, pips_debug, pstatement_statement, pstatement_statement_p, reference_variable, and vtxcontent_source.

Referenced by freia_dag_optimize(), switch_vertex_to_a_copy(), and unlink_copy_vertex().

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

◆ swis_call_flt()

static bool swis_call_flt ( call  c,
swis_ctx ctx 
)
static

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

2708 {
2710  if (api)
2711  {
2712  list args = call_arguments(c);
2713  pips_assert("freia api call length is ok",
2714  gen_length(args)== (api->arg_img_out + api->arg_img_in +
2715  api->arg_misc_out + api->arg_misc_in));
2716  unsigned int i;
2717  // output arguments
2718  for(i=0; i<api->arg_img_out; i++)
2719  {
2720  if (!ctx->write)
2722  args = CDR(args);
2723  }
2724  // input arguments
2725  for(i=0; i<api->arg_img_in; i++)
2726  {
2727  if (ctx->write)
2729  args = CDR(args);
2730  }
2731  // skip remainder anyway
2732  while (args)
2733  {
2735  args = CDR(args);
2736  }
2737  }
2738  // else this is not an AIPO call... we substitute everywhere
2739  return true;
2740 }
unsigned int arg_misc_out
Definition: freia.h:82
bool write
Definition: dag-utils.c:2699

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, call_arguments, call_function, CAR, CDR, entity_local_name(), EXPRESSION, gen_length(), gen_recurse_stop(), hwac_freia_api(), pips_assert, and swis_ctx::write.

Referenced by freia_switch_image_in_statement().

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

◆ swis_ref_rwt()

static void swis_ref_rwt ( reference  r,
swis_ctx ctx 
)
static

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

2702 {
2703  if (reference_variable(r)==ctx->old)
2704  reference_variable(r) = ctx->new;
2705 }
entity old
Definition: dag-utils.c:2699
entity new
Definition: dag-utils.c:2699

References swis_ctx::new, swis_ctx::old, and reference_variable.

Referenced by freia_switch_image_in_statement().

+ Here is the caller graph for this function:

◆ switch_image_variable()

static void switch_image_variable ( dagvtx  v,
entity  old,
entity  img 
)
static

switch to new image variable in v & its direct successors

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

2759 {
2760  vtxcontent c = dagvtx_content(v);
2761  pips_assert("switch image output", vtxcontent_out(c)==old);
2762  vtxcontent_out(c) = img;
2763  statement st = dagvtx_statement(v);
2764  pips_assert("some production statement", st!=NULL);
2765  freia_switch_image_in_statement(st, old, img, true);
2766  FOREACH(dagvtx, s, dagvtx_succs(v))
2767  {
2768  vtxcontent cs = dagvtx_content(s);
2769  gen_replace_in_list(vtxcontent_inputs(cs), old, img);
2770  statement st = dagvtx_statement(s);
2771  pips_assert("some producer statement", st!=NULL);
2772  freia_switch_image_in_statement(st, old, img, false);
2773  }
2774 }
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

References dagvtx_content, dagvtx_statement(), dagvtx_succs, FOREACH, freia_switch_image_in_statement(), gen_replace_in_list(), pips_assert, vtxcontent_inputs, and vtxcontent_out.

Referenced by dag_fix_image_reuse().

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

◆ switch_vertex_to_a_copy()

static void switch_vertex_to_a_copy ( dagvtx  target,
dagvtx  source,
list  tpreds 
)
static

replace target vertex by a copy of source results...

Parameters
targetto be removed
sourcedoes perform the same computation
tpredstarget predecessors to be added to source

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

824 {
825  pips_debug(5, "replacing %"_intFMT" by %"_intFMT"\n",
826  dagvtx_number(target), dagvtx_number(source));
827 
828  ifdebug(9) {
829  dagvtx_dump(stderr, "in source", source);
830  dagvtx_dump(stderr, "in target", target);
831  }
832 
833  entity src_img = dagvtx_image(source);
834  // fix contents
835  vtxcontent cot = dagvtx_content(target);
839  vtxcontent_inputs(cot) = CONS(entity, src_img, NIL);
840 
841  // fix vertices
842  FOREACH(dagvtx, v, tpreds)
843  gen_remove(&dagvtx_succs(v), target);
844 
845  entity trg_img = dagvtx_image(target);
846  FOREACH(dagvtx, s, dagvtx_succs(target))
847  {
848  gen_list_patch(vtxcontent_inputs(dagvtx_content(s)), trg_img, src_img);
849  // also fix subsequent statements, for AIPO output
850  substitute_image_in_statement(s, trg_img, src_img, true);
851  }
852  dagvtx_succs(source) = gen_once(target, dagvtx_succs(source));
853  dagvtx_succs(source) = gen_nconc(dagvtx_succs(target), dagvtx_succs(source));
854  dagvtx_succs(target) = NIL;
855 
856  // should I kill the statement? no, done by the copy removal stuff
857 
858  ifdebug(9) {
859  dagvtx_dump(stderr, "out source", source);
860  dagvtx_dump(stderr, "out target", target);
861  }
862 }
void gen_list_patch(list l, const void *x, const void *y)
Replace all the reference to x in list l by a reference to y:
Definition: list.c:985

References _intFMT, AIPO, CONS, dagvtx_content, dagvtx_dump(), dagvtx_image(), dagvtx_number(), dagvtx_succs, FOREACH, gen_free_list(), gen_list_patch(), gen_nconc(), gen_once(), gen_remove(), hwac_freia_api_index(), ifdebug, NIL, pips_debug, spoc_type_nop, substitute_image_in_statement(), vtxcontent_inputs, vtxcontent_opid, and vtxcontent_optype.

Referenced by freia_dag_optimize().

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

◆ switch_vertex_to_assign()

static bool switch_vertex_to_assign ( dagvtx  target,
dagvtx  source 
)
static

replace target measure to a copy of source result...

Parameters
targetto be removed/replaced because redundant
sourceto be kept
Returns
whether the statement is to be actually removed

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

726 {
727  pips_debug(5, "replacing measure %"_intFMT" by %"_intFMT" result\n",
728  dagvtx_number(target), dagvtx_number(source));
729 
730  // update target vertex
731  vtxcontent cot = dagvtx_content(target);
733  vtxcontent_opid(cot) = hwac_freia_api_index("freia_aipo_scalar_copy");
734  // no more image inputs
736  vtxcontent_inputs(cot) = NIL;
737 
738  // ??? source -> target scalar dependency?
739 
740  // update actual statement.
741  call cref = statement_call(dagvtx_statement(source));
742  expression eref = EXPRESSION(CAR(CDR(call_arguments(cref))));
743  call cnew = statement_call(dagvtx_statement(target));
744  expression enew = EXPRESSION(CAR(CDR(call_arguments(cnew))));
745 
746  if (expression_equal_p(eref, enew))
747  // just remove the fully redundant measure
748  return true;
749 
750  // replace by assign
752 
753  // ??? memory leak or core dump
754  // gen_full_free_list(call_arguments(cnew));
755  // possibly due to effects which are loaded?
756  call_arguments(cnew) =
760  NIL);
761 
762  return false;
763 }
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
expression dereference_expression(expression e)
generate a newly allocated expression for *(e)
Definition: expression.c:3934

References _intFMT, call_arguments, call_function, CAR, CDR, dagvtx_content, dagvtx_number(), dagvtx_statement(), dereference_expression(), EXPRESSION, expression_domain, expression_equal_p(), gen_free_list(), gen_make_list(), hwac_freia_api_index(), local_name_to_top_level_entity(), NIL, pips_debug, spoc_type_oth, statement_call(), vtxcontent_inputs, vtxcontent_opid, and vtxcontent_optype.

Referenced by freia_dag_optimize().

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

◆ unlink_copy_vertex()

static void unlink_copy_vertex ( dag  d,
const entity  source,
dagvtx  copy 
)
static

"copy" copies "source" image in dag "d".

remove it properly (forward copy propagation)

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

899 {
900  pips_debug(8, "unlinking %"_intFMT"\n", dagvtx_number(copy));
901 
902  entity target = vtxcontent_out(dagvtx_content(copy));
903  // may be NULL if source is an input
904  dagvtx prod = dagvtx_get_producer(d, copy, source, 0);
905 
906  // add copy successors as successors of prod
907  // it is kept as a successor in case it is not removed
908  if (prod)
909  {
910  FOREACH(dagvtx, vs, dagvtx_succs(copy))
911  dagvtx_succs(prod) = gen_once(vs, dagvtx_succs(prod));
912  }
913 
914  // replace use of target image by source image in all v successors
915  FOREACH(dagvtx, succ, dagvtx_succs(copy))
916  {
917  vtxcontent sc = dagvtx_content(succ);
918  gen_list_patch(vtxcontent_inputs(sc), target, source);
919 
920  // also in the statement inputs... (needed for AIPO target)
921  substitute_image_in_statement(succ, target, source, true);
922  }
923 
924  // copy has no more successors
926  dagvtx_succs(copy) = NIL;
927 }

References _intFMT, dagvtx_content, dagvtx_get_producer(), dagvtx_number(), dagvtx_succs, FOREACH, gen_free_list(), gen_list_patch(), gen_once(), NIL, pips_debug, substitute_image_in_statement(), vtxcontent_inputs, and vtxcontent_out.

Referenced by freia_dag_optimize().

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

◆ variable_used_as_later_input()

static bool variable_used_as_later_input ( entity  img,
list  ld 
)
static

hmmm...

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

2027 {
2028  bool used = false;
2029  FOREACH(dag, d, ld)
2030  {
2031  FOREACH(dagvtx, v, dag_inputs(d))
2032  {
2033  if (dagvtx_image(v)==img)
2034  {
2035  used = true;
2036  break;
2037  }
2038  }
2039  if (used) break;
2040  }
2041  pips_debug(8, "%s: %s\n", entity_name(img), bool_to_string(used));
2042  return used;
2043 }

References bool_to_string(), dag_inputs, dagvtx_image(), entity_name, FOREACH, and pips_debug.

Referenced by dag_compute_outputs().

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

◆ vertex_list_sorted_by_entities()

static void vertex_list_sorted_by_entities ( list  l)
static

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

525 {
527 }
static int dagvtx_cmp_entity(const dagvtx *v1, const dagvtx *v2)
Definition: dag-utils.c:518

References dagvtx_cmp_entity(), and gen_sort_list().

Referenced by dag_append_vertex(), and dag_remove_vertex().

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