Commit 6b9c9766 authored by Cédric VALENSI's avatar Cédric VALENSI

Sync

parent d8523fbe
......@@ -318,7 +318,7 @@ find_path(RPMBUILD_PATH NAMES rpmbuild) # look for rpmbuild
find_path(DPKG_DEB_PATH NAMES dpkg-deb) # look for dpkg-deb
SET(CPACK_PACKAGE_VERSION_MAJOR "2")
SET(CPACK_PACKAGE_VERSION_MINOR "8")
SET(CPACK_PACKAGE_VERSION_MINOR "9")
SET(CPACK_PACKAGE_VERSION_PATCH "0")
# ---- Check if at least one package generator has been found
......
.\" File generated using by MAQAO.
.TH MAQAO-ANALYZE "1" "2019/04/05" "MAQAO-ANALYZE 2.8.0" "User Commands"
.TH MAQAO-ANALYZE "1" "2019/06/19" "MAQAO-ANALYZE 2.9.0" "User Commands"
.SH NAME
maqao-analyze \- manual page for maqao analyze module.
.SH SYNOPSIS
......
.\" File generated using by MAQAO.
.TH MAQAO-MADRAS "1" "2019/04/05" "MAQAO-MADRAS 2.8.0" "User Commands"
.TH MAQAO-MADRAS "1" "2019/06/19" "MAQAO-MADRAS 2.9.0" "User Commands"
.SH NAME
maqao-madras \- manual page for maqao madras module.
.SH SYNOPSIS
......
.\" File generated using by MAQAO.
.TH MAQAO "1" "2019/04/05" "MAQAO 2.8.0" "User Commands"
.TH MAQAO "1" "2019/06/19" "MAQAO 2.9.0" "User Commands"
.SH NAME
maqao \- manual page for maqao module.
.SH SYNOPSIS
......
......@@ -37,6 +37,14 @@
# Possible values: STATIC (default) / EXTERNAL_DYNAMIC
#SET(MAQAO_LINKING STATIC)
# Disables linking with libunwind, even if present, for the static binary and dynamic libraries
# Possible values: TRUE / FALSE (default)
#SET(DISABLE_LIBUNWIND FALSE)
# Disables linking with libunwind, even if present, for dynamic libraries only
# Possible values: TRUE / FALSE (default)
#SET(DISABLE_LIBUNWIND_DYN FALSE)
# Specifies whether MAQAO is being compiled for a different architecture than the current one.
# Possible values: true / false (default)
#SET(CROSS_COMPILATION false)
......
......@@ -27,6 +27,9 @@ SET(OPTIM_LVL 3)
# A list of tags in the source code to not include in the static binary separated by ';'
#SET(EXCLUDE_CODE "")
# A list of micro-architectures to not include in the static binary separated by ';'
#SET(EXCLUDE_UARCHS "")
# A list of MAQAO Lua modules to include in the static binary separated by ';'
#SET(INCLUDE_MODULES "")
......@@ -34,6 +37,14 @@ SET(OPTIM_LVL 3)
# Possible values: STATIC (default) / EXTERNAL_DYNAMIC
#SET(MAQAO_LINKING STATIC)
# Disables linking with libunwind, even if present, for the static binary and dynamic libraries
# Possible values: TRUE / FALSE (default)
#SET(DISABLE_LIBUNWIND FALSE)
# Disables linking with libunwind, even if present, for dynamic libraries only
# Possible values: TRUE / FALSE (default)
#SET(DISABLE_LIBUNWIND_DYN FALSE)
# Specifies whether MAQAO is being compiled for a different architecture than the current one.
# Possible values: true / false (default)
#SET(CROSS_COMPILATION false)
......
......@@ -72,7 +72,8 @@ FILE(GLOB
)
# ---- Specify paths to sub-directories
UNSET(LIBS_SUPP CACHE)
UNSET(LIBS_SUPP CACHE) # Additional libraries for static executable
UNSET(LIBS_SUPP_DYN CACHE) # Additional libraries for dynamic libraries
ADD_SUBDIRECTORY(${LUA_DIR})
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(asm)
......@@ -239,7 +240,12 @@ SET_TARGET_PROPERTIES(maqao PROPERTIES COMPILE_FLAGS "${C_STATIC_FLAGS}")
# Link the MAQAO binary to the required libraries #
TARGET_LINK_LIBRARIES(maqao ${LUA_LIB_STATIC})
IF (NOT is_WINDOWS)
TARGET_LINK_LIBRARIES(maqao m dl pthread -Wl,--allow-multiple-definition ${LIBS_SUPP}) # allow-multiple-definition: libgcc already defines some libunwind symbols...
TARGET_LINK_LIBRARIES(maqao m dl pthread)
IF ("${MAQAO_LINKING}" STREQUAL "EXTERNAL_DYNAMIC")
TARGET_LINK_LIBRARIES(maqao -Wl,--allow-multiple-definition ${LIBS_SUPP_DYN}) # allow-multiple-definition: libgcc already defines some libunwind symbols...
ELSE ("${MAQAO_LINKING}" STREQUAL "EXTERNAL_DYNAMIC") #("${MAQAO_LINKING}" STREQUAL "STATIC")
TARGET_LINK_LIBRARIES(maqao -Wl,--allow-multiple-definition ${LIBS_SUPP}) # allow-multiple-definition: libgcc already defines some libunwind symbols...
ENDIF ("${MAQAO_LINKING}" STREQUAL "EXTERNAL_DYNAMIC")
ENDIF ()
IF (IS_STDCXX)
TARGET_LINK_LIBRARIES(maqao ${STDCXX})
......@@ -291,7 +297,7 @@ SET_TARGET_PROPERTIES(maqao-lib-dyn PROPERTIES COMPILE_FLAGS "${C_DYNAMIC_FLAGS}
IF (is_WINDOWS)
TARGET_LINK_LIBRARIES(maqao-lib-dyn ${LUA_LIB_DYN})
ELSEIF (is_UNIX)
TARGET_LINK_LIBRARIES(maqao-lib-dyn ${LUA_LIB_DYN} m dl pthread ${LIBS_SUPP})
TARGET_LINK_LIBRARIES(maqao-lib-dyn ${LUA_LIB_DYN} m dl pthread ${LIBS_SUPP_DYN})
ENDIF ()
IF (IS_STDCXX)
TARGET_LINK_LIBRARIES(maqao-lib-dyn ${STDCXX})
......
......@@ -486,21 +486,21 @@ static graph_t *get_path_DDG(array_t *path, int only_RAW)
}
/*
* Gets function/loop paths. If not previously computed (by another MAQAO function), compute them
* and informs the caller about that via the 'already_computed' parameter
* Gets function/loop paths. If not previously built (by another MAQAO function), build them
* and informs the caller about that via the 'already_built' parameter
* */
static queue_t *get_obj_paths(void *obj, int *already_computed,
static queue_t *get_obj_paths(void *obj, int *already_built,
queue_t* (*get_paths)(void *),
void (*compute_paths)(void *))
void (*build_paths)(void *))
{
queue_t *paths = get_paths(obj);
if (paths == NULL) {
*already_computed = FALSE;
compute_paths(obj);
*already_built = FALSE;
build_paths(obj);
paths = get_paths(obj);
} else
*already_computed = TRUE;
*already_built = TRUE;
return paths;
}
......@@ -508,12 +508,12 @@ static queue_t *get_obj_paths(void *obj, int *already_computed,
/* CF lcore_fctpath_getddg and build_DDG */
static queue_t *objpath_getddg(void *obj, int only_RAW,
queue_t* (*get_paths)(void *),
void (*compute_paths)(void *),
void (*build_paths)(void *),
void (*free_paths)(void *),
arch_t *arch)
{
int paths_already_computed;
queue_t *paths = get_obj_paths(obj, &paths_already_computed, get_paths, compute_paths);
int paths_already_built;
queue_t *paths = get_obj_paths(obj, &paths_already_built, get_paths, build_paths);
queue_t *ddg_allpaths = queue_new();
/* For each path */
......@@ -524,8 +524,8 @@ static queue_t *objpath_getddg(void *obj, int only_RAW,
queue_add_tail(ddg_allpaths, ddg);
}
/* Free paths if was computed on purpose */
if (paths_already_computed == FALSE)
/* Free paths if was built on purpose */
if (paths_already_built == FALSE)
free_paths(obj);
return ddg_allpaths;
......@@ -534,13 +534,13 @@ static queue_t *objpath_getddg(void *obj, int only_RAW,
/* CF lcore_fct_getddg and build_DDG */
static graph_t *obj_getddg(void *obj, int only_RAW,
queue_t* (*get_paths)(void *),
void (*compute_paths)(void *),
void (*build_paths)(void *),
void (*free_paths)(void *),
arch_t *arch)
{
graph_t *obj_ddg = graph_new();
int paths_already_computed;
queue_t *paths = get_obj_paths(obj, &paths_already_computed, get_paths, compute_paths);
int paths_already_built;
queue_t *paths = get_obj_paths(obj, &paths_already_built, get_paths, build_paths);
/* If only one path, directly build+get DDG */
if (queue_length(paths) == 1) {
......@@ -579,8 +579,8 @@ static graph_t *obj_getddg(void *obj, int only_RAW,
hashtable_free(ctxt.insn2node, NULL, NULL);
}
/* Free paths if was computed on purpose */
if (paths_already_computed == FALSE)
/* Free paths if was built on purpose */
if (paths_already_built == FALSE)
free_paths(obj);
lcore_set_ddg_latency (obj_ddg, get_default_latency (arch));
......@@ -592,22 +592,26 @@ static graph_t *obj_getddg(void *obj, int only_RAW,
* Specific to functions *
***************************************************************************************************/
static queue_t *_fct_get_paths (void *f) { return fct_get_paths (f); }
static void fct_compute_paths (void *f) { lcore_fct_computepaths (f); }
static void fct_free_paths (void *f) { lcore_fct_freepaths (f); }
static queue_t *_fct_get_paths (void *f) { return fct_get_paths (f); }
static void fct_build_paths (void *f) {
enum lcore_nb_paths_status status;
(void) lcore_fct_getnpaths (f, 0, &status);
if (status == LCORE_NB_PATHS_OK) lcore_fct_build_paths (f);
}
static void fct_free_paths (void *f) { lcore_fct_freepaths (f); }
/* CF lcore_fctpath_getddg and build_DDG */
static queue_t *fctpath_getddg(fct_t *fct, int only_RAW)
{
arch_t *arch = asmfile_get_arch (fct_get_asmfile (fct));
return objpath_getddg (fct, only_RAW, _fct_get_paths, fct_compute_paths, fct_free_paths, arch);
return objpath_getddg (fct, only_RAW, _fct_get_paths, fct_build_paths, fct_free_paths, arch);
}
static graph_t *fct_getddg(fct_t *fct, int only_RAW)
{
arch_t *arch = asmfile_get_arch (fct_get_asmfile (fct));
return obj_getddg(fct, only_RAW, _fct_get_paths, fct_compute_paths, fct_free_paths, arch);
return obj_getddg(fct, only_RAW, _fct_get_paths, fct_build_paths, fct_free_paths, arch);
}
/*
......@@ -646,22 +650,26 @@ graph_t *lcore_fct_getddg_ext(fct_t *fct)
* Specific to loops *
***************************************************************************************************/
static queue_t *_loop_get_paths (void *l) { return loop_get_paths (l); }
static void loop_compute_paths (void *l) { lcore_loop_computepaths (l); }
static void loop_free_paths (void *l) { lcore_loop_freepaths (l); }
static queue_t *_loop_get_paths (void *l) { return loop_get_paths (l); }
static void loop_build_paths (void *l) {
enum lcore_nb_paths_status status;
(void) lcore_loop_getnpaths (l, 0, &status);
if (status == LCORE_NB_PATHS_OK) lcore_loop_build_paths (l);
}
static void loop_free_paths (void *l) { lcore_loop_freepaths (l); }
/* CF lcore_looppath_getddg and build_DDG */
static queue_t *looppath_getddg(loop_t *loop, int only_RAW)
{
arch_t *arch = asmfile_get_arch (loop_get_asmfile (loop));
return objpath_getddg (loop, only_RAW, _loop_get_paths, loop_compute_paths, loop_free_paths, arch);
return objpath_getddg (loop, only_RAW, _loop_get_paths, loop_build_paths, loop_free_paths, arch);
}
/* CF lcore_loop_getddg and build_DDG */
static graph_t *loop_getddg(loop_t *loop, int only_RAW)
{
arch_t *arch = asmfile_get_arch (loop_get_asmfile (loop));
return obj_getddg(loop, only_RAW, _loop_get_paths, loop_compute_paths, loop_free_paths, arch);
return obj_getddg(loop, only_RAW, _loop_get_paths, loop_build_paths, loop_free_paths, arch);
}
/*
......@@ -843,19 +851,19 @@ static void _upd_cycle (queue_t *cycle, void *_data)
if (graph_max->max < max) graph_max->max = max;
}
/** Default maximum number of paths to compute in RecMII from a DDG entry node */
/** Default maximum number of paths to build in RecMII from a DDG entry node */
#define DDG_MAX_PATHS 1000
/*
* Returns a loop RecMII (longest latency chain) from its DDG
* \param ddg loop DDG
* \param max_paths maximum number of paths to compute for each CC. If negative value or zero, equivalent to DDG_MAX_PATHS
* \param max_paths maximum number of paths to build for each CC. If negative value or zero, equivalent to DDG_MAX_PATHS
* \param min RecMII using min latency
* \param max RecMII using max latency
*/
void get_RecMII(graph_t *ddg, int max_paths, float *min, float *max)
void get_RecMII(graph_t *ddg, unsigned max_paths, float *min, float *max)
{
if (max_paths <= 0)
if (max_paths == 0)
max_paths = DDG_MAX_PATHS;
_upd_cycle_data_t upd_cycle_data = { 0.0f, 0.0f };
......@@ -894,11 +902,11 @@ static void _ddg_upd_crit_paths (array_t *path, void *data)
* \param min_lat_crit_paths pointer to an array, set to critical paths considering minimum latency values
* \param max_lat_crit_paths idem min_lat_crit_paths considering maximum latencies
*/
void lcore_ddg_get_critical_paths (graph_t *ddg, int max_paths,
void lcore_ddg_get_critical_paths (graph_t *ddg, unsigned max_paths,
array_t **min_lat_crit_paths,
array_t **max_lat_crit_paths)
{
if (max_paths <= 0)
if (max_paths == 0)
max_paths = DDG_MAX_PATHS;
_ddg_upd_crit_paths_data_t crit_paths_data = { { 0.0f, array_new(), _get_min_lat },
......
......@@ -36,54 +36,53 @@
// API functions //
///////////////////////////////////////////////////////////////////////////////
static void compute_paths(block_t *root_block, int max_paths,
queue_t **obj_paths)
static void build_paths(const block_t *root_block, queue_t **obj_paths)
{
graph_node_t *root_node = root_block->cfg_node;
// npaths == max_paths means nb paths >= max_paths. To distinguish: using max_paths+1
const int npaths = graph_node_get_nb_paths(root_node, max_paths + 1);
queue_t *paths_nodes = graph_node_build_paths(root_node);
queue_t *paths_blocks = queue_new();
if (npaths <= max_paths) {
queue_t *paths_nodes = graph_node_compute_paths(root_node);
queue_t *paths_blocks = queue_new();
FOREACH_INQUEUE(paths_nodes, iter) {
array_t *path_nodes = GET_DATA_T(array_t*, iter); /* array of nodes */
array_t *path_blocks = array_new_with_custom_size
(array_length (path_nodes));
FOREACH_INQUEUE(paths_nodes, iter) {
array_t *path_nodes = GET_DATA_T(array_t*, iter); /* array of nodes */
array_t *path_blocks = array_new_with_custom_size
(array_length (path_nodes));
FOREACH_INARRAY(path_nodes, iter2) {
graph_node_t *node = ARRAY_GET_DATA(node, iter2);
block_t *block = GET_DATA_T(block_t*, node);
array_add(path_blocks, block);
}
array_free(path_nodes, NULL);
queue_add_tail(paths_blocks, path_blocks);
FOREACH_INARRAY(path_nodes, iter2) {
graph_node_t *node = ARRAY_GET_DATA(node, iter2);
block_t *block = GET_DATA_T(block_t*, node);
array_add(path_blocks, block);
}
queue_free(paths_nodes, NULL);
*obj_paths = paths_blocks;
array_free(path_nodes, NULL);
queue_add_tail(paths_blocks, path_blocks);
}
queue_free(paths_nodes, NULL);
*obj_paths = paths_blocks;
}
/*
* Computes paths for a function and overwrite its 'paths' field
* Following functions are not considered:
* - more than one entry
* - paths already computed
* - more than FCT_MAX_PATHS paths
* \param f a function
* Builds paths for a function and overwrite its 'paths' field
* \warning Assumes single entry function and (1 <= nb paths <= FCT_MAX_PATHS)
* \warning Call lcore_fct_getnpaths() before
* \remark: checks are done with debug profiles (NDEBUG not defined)
* \param fct a function
*/
void lcore_fct_computepaths(fct_t *f)
void lcore_fct_build_paths (fct_t *fct)
{
if (FCT_NB_ENTRIES (f) != 1 || fct_get_paths(f) != NULL)
return;
if (fct_get_paths (fct) != NULL) return; // Already built paths: nothing to do
assert (FCT_NB_ENTRIES (fct) == 1); // Assumes single entry function
block_t *root_block = queue_peek_head(fct_get_entry_blocks(f));
const block_t *root_block = fct_get_main_entry (fct);
compute_paths(root_block, FCT_MAX_PATHS, &(f->paths));
#ifndef NDEBUG
const unsigned nb_paths = graph_node_get_nb_paths (root_block->cfg_node, FCT_MAX_PATHS + 1);
assert (nb_paths > 0 && nb_paths <= FCT_MAX_PATHS); // Assumes valid nb
#endif
build_paths (root_block, &(fct->paths));
}
static void _remove_edge(graph_edge_t* edge)
......@@ -176,28 +175,33 @@ static void restore_edges_for_subgraph(list_t* removed_edges)
}
/*
* Computes paths for a loop and overwrite its 'paths' field
* Following loops are not considered:
* - more than one entry
* - paths already computed
* - more than LOOP_MAX_PATHS paths
* \param l a loop
* Builds paths for a loop and overwrite its 'paths' field
* \warning Assumes single entry loop and (1 <= nb paths <= LOOP_MAX_PATHS)
* \warning Call lcore_loop_getnpaths() before
* \remark: checks are done with debug profiles (NDEBUG not defined)
* \param loop a loop
*/
void lcore_loop_computepaths(loop_t *l)
void lcore_loop_build_paths (loop_t *loop)
{
if (LOOP_NB_ENTRIES (l) != 1 || loop_get_paths(l) != NULL)
return;
if (loop_get_paths (loop) != NULL) return; // Already built paths: nothing to do
block_t *root_block = list_getdata(loop_get_entries(l));
assert (LOOP_NB_ENTRIES (loop) == 1); // Assumes single entry loop
const block_t *root_block = list_getdata (loop_get_entries (loop));
//here, must "change" the CFG in order to have a subgraph containing
//only blocks from the loop l
list_t* removed_edges = remove_edges_for_subgraph(l);
list_t *removed_edges = remove_edges_for_subgraph (loop);
compute_paths(root_block, LOOP_MAX_PATHS, &(l->paths));
#ifndef NDEBUG
const unsigned nb_paths = graph_node_get_nb_paths (root_block->cfg_node, LOOP_MAX_PATHS + 1);
assert (nb_paths > 0 && nb_paths <= LOOP_MAX_PATHS);
#endif
build_paths (root_block, &(loop->paths));
//here, must rebuild the CFG in order to get the original graph
restore_edges_for_subgraph(removed_edges);
restore_edges_for_subgraph (removed_edges);
}
static void free_paths(queue_t *paths)
......@@ -237,36 +241,57 @@ void lcore_loop_freepaths(loop_t *l)
/*
* \brief returns the number of paths without computing them
* \param fct_t* f the targeted loop
* \param fct_t* f the targeted function
* \param max_paths maximum number of paths to enumerate
* \param status status code
*/
int lcore_fct_getnpaths(fct_t *f)
unsigned lcore_fct_getnpaths (const fct_t *fct, unsigned max_paths,
enum lcore_nb_paths_status *status)
{
if (FCT_NB_ENTRIES (f) == 1) {
const block_t *root_block = queue_peek_head(fct_get_entry_blocks(f));
return graph_node_get_nb_paths(root_block->cfg_node, -1);
if (max_paths == 0 || max_paths > FCT_MAX_PATHS) {
*status = LCORE_INVAL_MAX_PATHS;
return 0;
}
if (FCT_NB_ENTRIES (fct) != 1) {
*status = LCORE_UNKNOWN_NB_PATHS;
return 0;
}
return -1;
const block_t *root_block = fct_get_main_entry (fct);
const unsigned nb_paths = graph_node_get_nb_paths (root_block->cfg_node, max_paths + 1);
*status = nb_paths > max_paths ? LCORE_TOO_MANY_PATHS : LCORE_NB_PATHS_OK;
return nb_paths;
}
/*
* \brief returns the number of paths without computing them
* \param loop_t* l the targeted loop
* \param int take_branch decide whether to take
* a cycle once encountered or not
* \param max_paths maximum number of paths to enumerate
* \param status status code
*/
int lcore_loop_getnpaths(loop_t *l, int take_branch)
unsigned lcore_loop_getnpaths (loop_t *loop, unsigned max_paths,
enum lcore_nb_paths_status *status)
{
if ((take_branch == FALSE) && (LOOP_NB_ENTRIES (l) == 1)) {
list_t* removed_edges = remove_edges_for_subgraph(l);
const block_t *root_block = list_getdata(loop_get_entries(l));
int nb_path = graph_node_get_nb_paths(root_block->cfg_node, -1);
restore_edges_for_subgraph(removed_edges);
if (max_paths == 0 || max_paths > LOOP_MAX_PATHS) {
*status = LCORE_INVAL_MAX_PATHS;
return 0;
}
return nb_path;
if (LOOP_NB_ENTRIES (loop) != 1) {
*status = LCORE_UNKNOWN_NB_PATHS;
return 0;
}
return -1;
const block_t *root_block = list_getdata (loop_get_entries (loop));
list_t *removed_edges = remove_edges_for_subgraph (loop);
const unsigned nb_paths = graph_node_get_nb_paths (root_block->cfg_node, max_paths + 1);
restore_edges_for_subgraph (removed_edges);
*status = nb_paths > max_paths ? LCORE_TOO_MANY_PATHS : LCORE_NB_PATHS_OK;
return nb_paths;
}
/*
......
......@@ -837,19 +837,32 @@ typedef struct {
typedef DDG_latency_t (*get_DDG_latency_t) (insn_t *src, insn_t *dst);
//@const_start
enum lcore_nb_paths_status {
LCORE_NB_PATHS_OK = 0, /**<Paths can be safely computed*/
LCORE_UNKNOWN_NB_PATHS, /**<Unknown number of paths, not possible to compute paths*/
LCORE_TOO_MANY_PATHS, /**<Too many paths (> (FCT/LOOP)_MAX_PATHS), dangerous to compute paths*/
LCORE_INVAL_MAX_PATHS, /**<Invalid max_paths (expects 0 < max_paths <= (FCT/LOOP)_MAX_PATHS*/
};
//@const_stop
/**
* Computes paths for a function and overwrite its 'paths' field
* \note Functions with more than one entry are not considered
* Builds paths for a function and overwrite its 'paths' field
* \warning Assumes single entry function and (1 <= nb paths <= FCT_MAX_PATHS)
* \warning Call lcore_fct_getnpaths() before
* \remark: checks are done with debug profiles (NDEBUG not defined)
* \param f a function
*/
extern void lcore_fct_computepaths(fct_t *f);
extern void lcore_fct_build_paths(fct_t *f);
/**
* Computes paths for a loop and overwrite its 'paths' field
* \note Loops with more than one entry are not considered
* Builds paths for a loop and overwrite its 'paths' field
* \warning Assumes single entry loop and (1 <= nb paths <= LOOP_MAX_PATHS)
* \warning Call lcore_loop_getnpaths() before
* \remark: checks are done with debug profiles (NDEBUG not defined)
* \param l a loop
*/
extern void lcore_loop_computepaths(loop_t *l);
extern void lcore_loop_build_paths(loop_t *l);
/**
* \brief frees the memory allocated for the paths of a function
......@@ -866,17 +879,22 @@ extern void lcore_loop_freepaths(loop_t *l);
/**
* \brief returns the number of paths without computing them
* \param f the targeted function
* \return the number of paths
* \param max_paths maximum number of paths to enumerate
* \param status status code
* \return the number of paths or 0 if no path found or error
*/
extern int lcore_fct_getnpaths(fct_t *f);
extern unsigned lcore_fct_getnpaths(const fct_t *f, unsigned max_paths,
enum lcore_nb_paths_status *status);
/**
* \brief returns the number of paths without computing them
* \param l the targeted loop
* \param take_branch decide whether to take a cycle once encountered or not
* \return the number of paths
* \param max_paths maximum number of paths to enumerate
* \param status status code
* \return the number of paths or 0 if no path found or error
*/
extern int lcore_loop_getnpaths(loop_t *l, int take_branch);
extern unsigned lcore_loop_getnpaths(loop_t *l, unsigned max_paths,
enum lcore_nb_paths_status *status);
/**
* \brief check if a block "block" is an ancestor of a
......@@ -1000,7 +1018,7 @@ extern void lcore_set_ddg_latency (graph_t *ddg, get_DDG_latency_t get_latency);
* \param min RecMII using min latency
* \param max RecMII using max latency
*/
extern void get_RecMII(graph_t *ddg, int max_paths, float *min, float *max);
extern void get_RecMII(graph_t *ddg, unsigned max_paths, float *min, float *max);
/**
* Returns critical paths for a DDG
......@@ -1009,7 +1027,7 @@ extern void get_RecMII(graph_t *ddg, int max_paths, float *min, float *max);
* \param min_lat_crit_paths pointer to an array, set to critical paths considering minimum latency values
* \param max_lat_crit_paths idem min_lat_crit_paths considering maximum latencies
*/
extern void lcore_ddg_get_critical_paths (graph_t *ddg, int max_paths,
extern void lcore_ddg_get_critical_paths (graph_t *ddg, unsigned max_paths,
array_t **min_lat_crit_paths,
array_t **max_lat_crit_paths);
......
......@@ -84,8 +84,6 @@
#include "libmcommon.h"
#define GRAPH_MAX_PATHS 1000000 /* Default maximum number of paths counted by graph_node_get_nb_paths */
///////////////////////////////////////////////////////////////////////////////
// graph functions //
///////////////////////////////////////////////////////////////////////////////
......@@ -614,10 +612,10 @@ static int get_nb_children(const graph_node_t *node, const hashtable_t *bet)
}
/**
* Helper function, called by graph_node_compute_paths.
* Helper function, called by graph_node_build_paths.
* Updates paths ending with a given node
* \param node a graph node
* \param paths current set of paths built by graph_node_compute_paths
* \param paths current set of paths built by graph_node_build_paths
* \param bet backedges hashtable, allows to use graph_is_backedge_from_table
*/
static void update_pred_paths(const graph_node_t *node, queue_t *paths,
......@@ -684,23 +682,27 @@ static void update_pred_paths(const graph_node_t *node, queue_t *paths,
array_free(paths_to_remove, NULL);
/* Add into 'paths' the paths to add */
unsigned nb_paths = queue_length (paths);
FOREACH_INARRAY(paths_to_add, p3) {
array_t *cur_path = ARRAY_GET_DATA(cur_path, p3);
queue_add_tail(paths, cur_path);
if (nb_paths++ < GRAPH_MAX_PATHS)
queue_add_tail(paths, cur_path);
else
break;
}
array_free(paths_to_add, NULL);
}
/*
* Computes and returns paths (as a queue) in a graph, starting from a source node.
* Warning: The number of paths is not verified before computing them. It is up to the user
* to call graph_node_get_nb_paths before and decide if it is worth calling graph_node_compute_paths.
* Builds and returns paths (as a queue) in a graph, starting from a source node.
* Warning: The number of paths is not verified before building them. It is up to the user
* to call graph_node_get_nb_paths before and decide if it is worth calling graph_node_build_paths.
* \param root a graph (root node)
* \return queue of paths starting from root
*/
queue_t *graph_node_compute_paths(const graph_node_t *root)
queue_t *graph_node_build_paths(const graph_node_t *root)
{
/* Creates a first path containing the root node */
array_t *root_path = array_new();
......@@ -731,6 +733,15 @@ queue_t *graph_node_compute_paths(const graph_node_t *root)
return paths;
}
/*
* Deprecated: use graph_node_build_paths
*/
queue_t *graph_node_compute_paths(const graph_node_t *root)
{
WRNMSG ("graph_node_compute_paths is deprecated. Use graph_node_build_paths");
return graph_node_build_paths (root);
}
/*
* Frees the memory allocated for given paths
* \param paths paths to free
......@@ -751,7 +762,7 @@ void graph_free_paths(queue_t *paths)
* Recursive. Originally called from graph_node_get_nb_paths.
*/
static void update_nb_paths(const graph_node_t *node, const hashtable_t *bet,
int *nb_paths, int max_paths)
unsigned *nb_paths, unsigned max_paths)
{
if (*nb_paths >= max_paths)
return;
......@@ -773,17 +784,17 @@ static void update_nb_paths(const graph_node_t *node, const hashtable_t *bet,
/*
* Gets the number of paths in a graph starting from a given source (root) node.
* Paths are not computed (faster than first computing paths and count them).
* Paths are not built (faster than first building paths and count them).
* \param root a graph (root node)
* \param max_paths maximum number of paths that the user accepts to compute. A negative or zero value is equivalent to MAX_PATHS
* \param max_paths maximum number of paths to enumarate. A zero value is equivalent to GRAPH_MAX_PATHS
* \return paths number
*/
int graph_node_get_nb_paths(const graph_node_t *root, int max_paths)
unsigned graph_node_get_nb_paths(const graph_node_t *root, unsigned max_paths)
{
if (max_paths <= 0)
if (max_paths == 0)
max_paths = GRAPH_MAX_PATHS;
int nb_paths = 0;
unsigned nb_paths = 0;
/* Registers backedge in an hashtable for a fast checks */
hashtable_t *bet = graph_node_get_backedges_table(root);
......@@ -1286,7 +1297,7 @@ void graph_free (graph_t *graph, void (*f_node)(void*), void (*f_edge)(void*))
lc_free (graph);
}
void graph_for_each_path (graph_t *graph, int max_paths,
void graph_for_each_path (graph_t *graph, unsigned max_paths,
void (*fct) (array_t *, void *), void *data)
{
/* For each connected component */
......@@ -1298,11 +1309,11 @@ void graph_for_each_path (graph_t *graph, int max_paths,
FOREACH_INHASHTABLE(graph_connected_component_get_entry_nodes(cc), entry_node_iter) {
graph_node_t *entry_node = GET_KEY(graph_node_t*, entry_node_iter);
if (graph_node_get_nb_paths(entry_node, max_paths) >= max_paths)
if (graph_node_get_nb_paths(entry_node, max_paths+1) > max_paths)
continue;
/* For each path */
queue_t *paths = graph_node_compute_paths(entry_node);
queue_t *paths = graph_node_build_paths(entry_node);
FOREACH_INQUEUE(paths, paths_iter) {
array_t *path = GET_DATA_T(array_t*, paths_iter);
fct (path, data);
......@@ -1412,7 +1423,7 @@ static void _upd_path (array_t *path, void *_data)
array_free (cycles, NULL);
}
void graph_for_each_cycle (graph_t *graph, int max_paths,
void graph_for_each_cycle (graph_t *graph, unsigned max_paths,
boolean_t (*ignore_edge) (const graph_edge_t *edge),
void (*fct) (queue_t *cycle, void *), void *data)
{
......@@ -1472,7 +1483,7 @@ void graph_update_critical_paths (array_t *path, void *data)
* \param crit_paths pointer to an array, set to critical paths
* \param get_edge_weight function to return the weight of an edge (providing genericity)
*/
void graph_get_critical_paths (graph_t *graph, int max_paths,
void graph_get_critical_paths (graph_t *graph, unsigned max_paths,
array_t **crit_paths,
float (*get_edge_weight) (graph_edge_t *))
{
......
......@@ -3012,6 +3012,11 @@ extern int64_t txtfield_getnum(txtfield_t* field);
///////////////////////////////////////////////////////////////////////////////
// graphs //
///////////////////////////////////////////////////////////////////////////////
//@const_start
#define GRAPH_MAX_PATHS 1000000 /**<Default maximum number of paths counted by graph_node_get_nb_paths*/
//@const_stop
/**
* \struct graph_node_s
* \brief Structure holding a node of a graph
......@@ -3219,20 +3224,27 @@ extern int graph_is_backedge_from_table(const graph_edge_t *edge,