execution frequency based on Kirchhoff's current law
authorAdam Szalkowski <adam@ipd.info.uni-karlsruhe.de>
Wed, 31 May 2006 18:37:08 +0000 (18:37 +0000)
committerAdam Szalkowski <adam@ipd.info.uni-karlsruhe.de>
Wed, 31 May 2006 18:37:08 +0000 (18:37 +0000)
[r7842]

ir/ana/Makefile.in
ir/ana/execfreq.c [new file with mode: 0644]
ir/ana/execfreq.h [new file with mode: 0644]

index e154d2d..84014b0 100644 (file)
@@ -19,7 +19,7 @@ INSTALL_HEADERS = irouts.h trouts.h irdom.h cgana.h irloop.h irtypeinfo.h irsimp
                callgraph.h rta.h interval_analysis.h                                   \
                field_temperature.h execution_frequency.h irextbb.h irconsconfirm.h \
                analyze_irg_args.h height.h \
-               cdep.h
+               cdep.h execfreq.h
 
 SOURCES = $(INSTALL_HEADERS)
 
@@ -30,7 +30,7 @@ SOURCES += Makefile.in \
                callgraph.c field_temperature.c execution_frequency.c phiclass.c \
                irextbb.c irextbb_t.h irconsconfirm.c analyze_irg_args.c \
                compute_loop_info.c compute_loop_info.h height.c \
-               cdep.c
+               cdep.c execfreq.c
 
 include $(topdir)/MakeRules
 
@@ -38,7 +38,7 @@ CPPFLAGS += -I$(top_srcdir)/ir/adt -I$(top_srcdir)/ir/ir -I$(top_srcdir)/ir/comm
                -I$(top_srcdir)/ir/ident -I$(top_srcdir)/ir/tr -I$(top_srcdir)/ir/tv \
                -I$(top_srcdir)/ir/debug -I$(top_srcdir)/ir/ana -I$(top_srcdir)/ir/st \
                -I$(top_srcdir)/ir/opt -I$(top_srcdir)/ir/stat -I$(top_srcdir)/ir/external \
-               -I$(topdir)/ir/config -I$(top_srcdir)/ir/arch
+               -I$(topdir)/ir/config -I$(top_srcdir)/ir/arch -I$(HOME)/local/include
 
 include $(top_srcdir)/MakeTargets
 
diff --git a/ir/ana/execfreq.c b/ir/ana/execfreq.c
new file mode 100644 (file)
index 0000000..fa2960b
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Project:     libFIRM
+ * File name:   ir/ana/execfreq.c
+ * Purpose:     Compute an estimate of basic block executions.
+ * Author:      Adam M. Szalkowski
+ * Modified by:
+ * Created:     28.05.2006
+ * CVS-ID:      $Id$
+ * Copyright:   (c) 2006 Universität Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+//#define USE_GSL
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef USE_GSL
+#include <gsl/gsl_linalg.h>
+#include <gsl/gsl_vector.h>
+#else
+#include "gaussjordan.h"
+#endif
+
+#include "execfreq.h"
+
+#include "firm_common_t.h"
+#include "set.h"
+#include "hashptr.h"
+
+#include "irprog_t.h"
+#include "irgraph_t.h"
+#include "irnode_t.h"
+#include "irloop.h"
+#include "irgwalk.h"
+#include "irouts.h"
+#include "irprintf.h"
+
+#include "execfreq.h"
+
+#define set_foreach(s,i) for((i)=set_first((s)); (i); (i)=set_next((s)))
+
+typedef struct _walkerdata_t {
+  set    *set;
+  size_t  idx;
+} walkerdata_t;
+
+static int
+cmp_freq(const void *a, const void *b, size_t size)
+{
+  const freq_t *p = a;
+  const freq_t *q = b;
+
+  return !(p->irn == q->irn);
+}
+
+static freq_t *
+set_find_freq(set * set, const ir_node * irn)
+{
+  freq_t     query;
+
+  query.irn = irn;
+  return set_find(set, &query, sizeof(query), HASH_PTR(irn));
+}
+
+static freq_t *
+set_insert_freq(set * set, const ir_node * irn)
+{
+  freq_t     query;
+
+  query.irn = irn;
+  query.freq = 0.0;
+  return set_insert(set, &query, sizeof(query), HASH_PTR(irn));
+}
+
+double
+get_block_execfreq(set * freqs, const ir_node * irn)
+{
+  assert(is_Block(irn));
+
+  freq_t *freq = set_find_freq(freqs, irn);
+  assert(freq);
+
+  return freq->freq;
+}
+
+#define ZERO(x)   (((x) > 0) ? ((x) < 0.0001) : ((x) > -0.0001))
+
+static void
+block_walker(ir_node * bb, void * data)
+{
+  walkerdata_t  *wd = data;
+
+  set_insert_freq(wd->set, bb);
+  set_irn_link(bb, (void*)wd->idx++);
+}
+
+#ifdef USE_GSL
+static gsl_vector *
+solve_lgs(double * a_data, double * b_data, size_t size)
+{
+  gsl_matrix_view m
+    = gsl_matrix_view_array (a_data, size, size);
+
+  gsl_vector_view b
+    = gsl_vector_view_array (b_data, size);
+
+  gsl_vector *x = gsl_vector_alloc (size);
+
+  int s;
+
+  gsl_permutation * p = gsl_permutation_alloc (size);
+
+  gsl_linalg_LU_decomp (&m.matrix, p, &s);
+
+  gsl_linalg_LU_solve (&m.matrix, p, &b.vector, x);
+
+  gsl_permutation_free (p);
+
+  return x;
+}
+#else
+static double *
+solve_lgs(double * A, double * b, size_t size)
+{
+  if(firm_gaussjordansolve(A,b,size) == 0) {
+    return b;
+  } else {
+    return NULL;
+  }
+}
+#endif
+
+static double
+get_cf_probability(const ir_node * bb, int pos)
+{
+#define LOOP_WEIGHT 9.0
+
+  double    sum = 0.0;
+  double    cur = 0.0;
+  int       i,
+           n;
+  ir_node  *pred = get_Block_cfgpred_block(bb, pos);
+
+  if(get_loop_depth(get_irn_loop(bb)) < get_loop_depth(get_irn_loop(pred))) {
+    cur = 1.0;
+  } else {
+    cur = LOOP_WEIGHT;
+  }
+
+  for(i = 0, n = get_Block_n_cfg_outs(pred); i < n; ++i) {
+    ir_node *succ = get_Block_cfg_out(pred, i);
+
+    if(get_loop_depth(get_irn_loop(succ)) < get_loop_depth(get_irn_loop(pred))) {
+      sum += 1.0;
+    } else {
+      sum += LOOP_WEIGHT;
+    }
+  }
+
+  return cur/sum;
+}
+
+set *
+compute_execfreq(ir_graph * irg)
+{
+  set          *freqs = new_set(cmp_freq, 32);
+  size_t        size;
+  double       *matrix;
+  double       *rhs;
+  size_t        i = 0;
+  freq_t       *freq;
+  walkerdata_t  wd;
+#ifdef USE_GSL
+  gsl_vector   *x;
+#else
+  double       *x;
+#endif
+
+  construct_cf_backedges(irg);
+
+  wd.idx = 0;
+  wd.set = freqs;
+
+  irg_block_walk_graph(irg, block_walker, NULL, &wd);
+
+  size = set_count(freqs);
+  matrix = malloc(size*size*sizeof(*matrix));
+  memset(matrix, 0, size*size*sizeof(*matrix));
+  rhs = malloc(size*sizeof(*rhs));
+  memset(rhs, 0, size*sizeof(*rhs));
+
+  set_foreach(freqs, freq) {
+    const ir_node  *bb = freq->irn;
+    size_t    idx = (int)get_irn_link(bb);
+
+    matrix[idx*(size+1)] = -1.0;
+
+    if(bb == get_irg_start_block(irg)) {
+      rhs[(int)get_irn_link(bb)] = -1.0;
+      continue;
+    }
+
+    for(i = 0; i < get_Block_n_cfgpreds(bb); ++i) {
+      ir_node   *pred = get_Block_cfgpred_block(bb, i);
+      size_t     pred_idx = (int)get_irn_link(pred);
+
+//      matrix[pred_idx + idx*size] += 1.0/(double)get_Block_n_cfg_outs(pred);
+      matrix[pred_idx + idx*size] += get_cf_probability(bb, i);
+    }
+  }
+
+  x = solve_lgs(matrix, rhs, size);
+  if(x == NULL) {
+    del_set(freqs);
+    return NULL;
+  }
+
+  set_foreach(freqs, freq) {
+    const ir_node  *bb = freq->irn;
+    size_t          idx = PTR_TO_INT(get_irn_link(bb));
+
+#ifdef USE_GSL
+    freq->freq = ZERO(gsl_vector_get(x, idx)) ? 0.0 : gsl_vector_get(x, idx);
+#else
+    freq->freq = ZERO(x[idx]) ? 0.0 : x[idx];
+#endif
+    ir_fprintf(stderr, "execfreq %+F: %f\n", bb, freq->freq);
+  }
+
+#ifdef USE_GSL
+  gsl_vector_free(x);
+#endif
+  free(matrix);
+
+  return freqs;
+}
+
+void
+free_execfreq(set * freqs)
+{
+  if(freqs) del_set(freqs);
+}
+
+#undef ELEM
diff --git a/ir/ana/execfreq.h b/ir/ana/execfreq.h
new file mode 100644 (file)
index 0000000..2557be4
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef EXECFREQ_H_
+#define EXECFREQ_H_
+
+#include "irgraph_t.h"
+#include "irnode_t.h"
+
+typedef struct _freq_t {
+  const ir_node    *irn;
+  double            freq;
+} freq_t;
+
+set *compute_execfreq(ir_graph * irg);
+
+void free_execfreq(set * freqs);
+
+double get_block_execfreq(set * freqs, const ir_node * irn);
+
+#endif