[llvm-commits] [llvm] r78354 - in /llvm/trunk/lib/CodeGen: PBQP.cpp PBQP.h PBQP/ PBQP/AnnotatedGraph.h PBQP/ExhaustiveSolver.h PBQP/GraphBase.h PBQP/GraphGenerator.h PBQP/HeuristicSolver.h PBQP/Heuristics/ PBQP/Heuristics/Briggs.h PBQP/PBQPMath.h PBQP/SimpleGraph.h PBQP/Solution.h PBQP/Solver.h RegAllocPBQP.cpp
Evan Cheng
evan.cheng at apple.com
Sun Aug 9 21:52:03 PDT 2009
I somehow doubt PBQP is very good fit for a single register target.
Evan
On Aug 9, 2009, at 9:42 PM, Sanjiv Gupta wrote:
> This is causing too much unnecessary spilling for PIC16.
> Attached is a test case. The option to use with llc are
> -pre-RA-sched=list-burr -regalloc=pbqp -march=pic16
>
> Try it with 78353 and 78354 and see the difference for yourself.
>
> - Sanjiv
>
>
> Lang Hames wrote:
>> Author: lhames
>> Date: Thu Aug 6 18:32:48 2009
>> New Revision: 78354
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=78354&view=rev
>> Log:
>> New C++ PBQP solver. Currently about as fast (read _slow_) as the
>> old C based solver, but I'll be working to improve that. The PBQP
>> allocator has been updated to use the new solver.
>>
>> Added:
>> llvm/trunk/lib/CodeGen/PBQP/
>> llvm/trunk/lib/CodeGen/PBQP/AnnotatedGraph.h
>> llvm/trunk/lib/CodeGen/PBQP/ExhaustiveSolver.h
>> llvm/trunk/lib/CodeGen/PBQP/GraphBase.h
>> llvm/trunk/lib/CodeGen/PBQP/GraphGenerator.h
>> llvm/trunk/lib/CodeGen/PBQP/HeuristicSolver.h
>> llvm/trunk/lib/CodeGen/PBQP/Heuristics/
>> llvm/trunk/lib/CodeGen/PBQP/Heuristics/Briggs.h
>> llvm/trunk/lib/CodeGen/PBQP/PBQPMath.h
>> llvm/trunk/lib/CodeGen/PBQP/SimpleGraph.h
>> llvm/trunk/lib/CodeGen/PBQP/Solution.h
>> llvm/trunk/lib/CodeGen/PBQP/Solver.h
>> Removed:
>> llvm/trunk/lib/CodeGen/PBQP.cpp
>> llvm/trunk/lib/CodeGen/PBQP.h
>> Modified:
>> llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp
>>
>> Removed: llvm/trunk/lib/CodeGen/PBQP.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP.cpp?rev=78353&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/PBQP.cpp (removed)
>> @@ -1,1395 +0,0 @@
>> -//===---------------- PBQP.cpp --------- PBQP Solver ------------
>> *- C++ -*-===//
>> -//
>> -// The LLVM Compiler Infrastructure
>> -//
>> -// This file is distributed under the University of Illinois Open
>> Source
>> -// License. See LICENSE.TXT for details.
>> -//
>> -//
>> =
>> =
>> =
>> ----------------------------------------------------------------------=
>> ==//
>> -//
>> -// Developed by: Bernhard Scholz
>> -// The University of Sydney
>> -// http://www.it.usyd.edu.au/~scholz
>> -//
>> =
>> =
>> =
>> ----------------------------------------------------------------------=
>> ==//
>> -
>> -#include "PBQP.h"
>> -#include "llvm/Config/alloca.h"
>> -#include <limits>
>> -#include <cassert>
>> -#include <cstring>
>> -
>> -namespace llvm {
>> -
>> -/
>> **************************************************************************
>> - * Data Structures -
>> **************************************************************************/
>> -
>> -/* edge of PBQP graph */
>> -typedef struct adjnode {
>> - struct adjnode *prev, /* doubly chained list */
>> - *succ, - *reverse; /* reverse
>> edge */
>> - int adj; /* adj. node */
>> - PBQPMatrix *costs; /* cost matrix of edge */
>> -
>> - bool tc_valid; /* flag whether following fields are
>> valid */
>> - int *tc_safe_regs; /* safe registers */
>> - int tc_impact; /* impact */ -} adjnode;
>> -
>> -/* bucket node */
>> -typedef struct bucketnode {
>> - struct bucketnode *prev; /* doubly chained list */
>> - struct bucketnode *succ; - int u; /* node
>> */
>> -} bucketnode;
>> -
>> -/* data structure of partitioned boolean quadratic problem */
>> -struct pbqp {
>> - int num_nodes; /* number of nodes */
>> - int max_deg; /* maximal degree of a node */
>> - bool solved; /* flag that indicates whether PBQP
>> has been solved yet */
>> - bool optimal; /* flag that indicates whether PBQP
>> is optimal */
>> - PBQPNum min;
>> - bool changed; /* flag whether graph has changed in
>> simplification */
>> -
>> - /* node fields */
>> - PBQPVector **node_costs; /* cost vectors of nodes */
>> - int *node_deg; /* node degree of nodes */
>> - int *solution; /* solution for node */
>> - adjnode **adj_list; /* adj. list */
>> - bucketnode **bucket_ptr; /* bucket pointer of a node */
>> -
>> - /* node stack */
>> - int *stack; /* stack of nodes */
>> - int stack_ptr; /* stack pointer */
>> -
>> - /* bucket fields */
>> - bucketnode **bucket_list; /* bucket list */
>> -
>> - int num_r0; /* counters for number statistics */
>> - int num_ri;
>> - int num_rii;
>> - int num_rn; - int num_rn_special; -};
>> -
>> -bool isInf(PBQPNum n) { return n ==
>> std::numeric_limits<PBQPNum>::infinity(); } -
>> -/
>> *****************************************************************************
>> - * allocation/de-allocation of pbqp problem -
>> ****************************************************************************/
>> -
>> -/* allocate new partitioned boolean quadratic program problem */
>> -pbqp *alloc_pbqp(int num_nodes)
>> -{
>> - pbqp *this_;
>> - int u;
>> - - assert(num_nodes > 0);
>> - - /* allocate memory for pbqp data structure */ - this_ =
>> (pbqp *)malloc(sizeof(pbqp));
>> -
>> - /* Initialize pbqp fields */
>> - this_->num_nodes = num_nodes;
>> - this_->solved = false;
>> - this_->optimal = true;
>> - this_->min = 0.0;
>> - this_->max_deg = 0;
>> - this_->changed = false;
>> - this_->num_r0 = 0;
>> - this_->num_ri = 0;
>> - this_->num_rii = 0;
>> - this_->num_rn = 0;
>> - this_->num_rn_special = 0;
>> - - /* initialize/allocate stack fields of pbqp */ - this_-
>> >stack = (int *) malloc(sizeof(int)*num_nodes);
>> - this_->stack_ptr = 0;
>> - - /* initialize/allocate node fields of pbqp */
>> - this_->adj_list = (adjnode **) malloc(sizeof(adjnode *)
>> *num_nodes);
>> - this_->node_deg = (int *) malloc(sizeof(int)*num_nodes);
>> - this_->solution = (int *) malloc(sizeof(int)*num_nodes);
>> - this_->bucket_ptr = (bucketnode **) malloc(sizeof(bucketnode **)
>> *num_nodes);
>> - this_->node_costs = (PBQPVector**) malloc(sizeof(PBQPVector*) *
>> num_nodes);
>> - for(u=0;u<num_nodes;u++) {
>> - this_->solution[u]=-1;
>> - this_->adj_list[u]=NULL;
>> - this_->node_deg[u]=0;
>> - this_->bucket_ptr[u]=NULL;
>> - this_->node_costs[u]=NULL;
>> - }
>> - - /* initialize bucket list */
>> - this_->bucket_list = NULL;
>> - - return this_;
>> -}
>> -
>> -/* free pbqp problem */
>> -void free_pbqp(pbqp *this_)
>> -{
>> - int u;
>> - int deg;
>> - adjnode *adj_ptr,*adj_next;
>> - bucketnode *bucket,*bucket_next;
>> - - assert(this_ != NULL);
>> - - /* free node cost fields */
>> - for(u=0;u < this_->num_nodes;u++) {
>> - delete this_->node_costs[u];
>> - }
>> - free(this_->node_costs);
>> - - /* free bucket list */
>> - for(deg=0;deg<=this_->max_deg;deg++) {
>> - for(bucket=this_->bucket_list[deg];bucket!
>> =NULL;bucket=bucket_next) {
>> - this_->bucket_ptr[bucket->u] = NULL;
>> - bucket_next = bucket-> succ;
>> - free(bucket);
>> - }
>> - }
>> - free(this_->bucket_list);
>> - - /* free adj. list */
>> - assert(this_->adj_list != NULL);
>> - for(u=0;u < this_->num_nodes; u++) {
>> - for(adj_ptr = this_->adj_list[u]; adj_ptr != NULL; adj_ptr =
>> adj_next) {
>> - adj_next = adj_ptr -> succ;
>> - if (u < adj_ptr->adj) {
>> - assert(adj_ptr != NULL);
>> - delete adj_ptr->costs;
>> - }
>> - if (adj_ptr -> tc_safe_regs != NULL) {
>> - free(adj_ptr -> tc_safe_regs);
>> - }
>> - free(adj_ptr);
>> - }
>> - }
>> - free(this_->adj_list);
>> - - /* free other node fields */
>> - free(this_->node_deg);
>> - free(this_->solution);
>> - free(this_->bucket_ptr);
>> -
>> - /* free stack */
>> - free(this_->stack);
>> -
>> - /* free pbqp data structure itself */
>> - free(this_);
>> -}
>> -
>> -
>> -/
>> ****************************************************************************
>> - * adj. node routines -
>> ****************************************************************************/
>> -
>> -/* find data structure of adj. node of a given node */
>> -static
>> -adjnode *find_adjnode(pbqp *this_,int u,int v)
>> -{
>> - adjnode *adj_ptr;
>> - - assert (this_ != NULL);
>> - assert (u >= 0 && u < this_->num_nodes);
>> - assert (v >= 0 && v < this_->num_nodes);
>> - assert(this_->adj_list != NULL);
>> -
>> - for(adj_ptr = this_ -> adj_list[u];adj_ptr != NULL; adj_ptr =
>> adj_ptr -> succ) {
>> - if (adj_ptr->adj == v) {
>> - return adj_ptr;
>> - }
>> - }
>> - return NULL;
>> -}
>> -
>> -/* allocate a new data structure for adj. node */
>> -static
>> -adjnode *alloc_adjnode(pbqp *this_,int u, PBQPMatrix *costs)
>> -{
>> - adjnode *p;
>> -
>> - assert(this_ != NULL);
>> - assert(costs != NULL);
>> - assert(u >= 0 && u < this_->num_nodes);
>> -
>> - p = (adjnode *)malloc(sizeof(adjnode));
>> - assert(p != NULL);
>> - - p->adj = u;
>> - p->costs = costs; -
>> - p->tc_valid= false;
>> - p->tc_safe_regs = NULL;
>> - p->tc_impact = 0;
>> -
>> - return p;
>> -}
>> -
>> -/* insert adjacence node to adj. list */
>> -static
>> -void insert_adjnode(pbqp *this_, int u, adjnode *adj_ptr)
>> -{
>> -
>> - assert(this_ != NULL);
>> - assert(adj_ptr != NULL);
>> - assert(u >= 0 && u < this_->num_nodes);
>> -
>> - /* if adjacency list of node is not empty -> update
>> - first node of the list */
>> - if (this_ -> adj_list[u] != NULL) {
>> - assert(this_->adj_list[u]->prev == NULL);
>> - this_->adj_list[u] -> prev = adj_ptr;
>> - }
>> -
>> - /* update doubly chained list pointers of pointers */
>> - adj_ptr -> succ = this_->adj_list[u];
>> - adj_ptr -> prev = NULL;
>> -
>> - /* update adjacency list pointer of node u */
>> - this_->adj_list[u] = adj_ptr;
>> -}
>> -
>> -/* remove entry in an adj. list */
>> -static
>> -void remove_adjnode(pbqp *this_, int u, adjnode *adj_ptr)
>> -{
>> - assert(this_!= NULL);
>> - assert(u >= 0 && u <= this_->num_nodes);
>> - assert(this_->adj_list != NULL);
>> - assert(adj_ptr != NULL);
>> - - if (adj_ptr -> prev == NULL) {
>> - this_->adj_list[u] = adj_ptr -> succ;
>> - } else {
>> - adj_ptr -> prev -> succ = adj_ptr -> succ;
>> - } -
>> - if (adj_ptr -> succ != NULL) {
>> - adj_ptr -> succ -> prev = adj_ptr -> prev;
>> - }
>> -
>> - if(adj_ptr->reverse != NULL) {
>> - adjnode *rev = adj_ptr->reverse;
>> - rev->reverse = NULL;
>> - }
>> -
>> - if (adj_ptr -> tc_safe_regs != NULL) {
>> - free(adj_ptr -> tc_safe_regs);
>> - }
>> -
>> - free(adj_ptr);
>> -}
>> -
>> -/
>> *****************************************************************************
>> - * node functions -
>> ****************************************************************************/
>> -
>> -/* get degree of a node */
>> -static
>> -int get_deg(pbqp *this_,int u)
>> -{
>> - adjnode *adj_ptr;
>> - int deg = 0;
>> - - assert(this_ != NULL);
>> - assert(u >= 0 && u < this_->num_nodes);
>> - assert(this_->adj_list != NULL);
>> -
>> - for(adj_ptr = this_ -> adj_list[u];adj_ptr != NULL; adj_ptr =
>> adj_ptr -> succ) {
>> - deg ++;
>> - }
>> - return deg;
>> -}
>> -
>> -/* reinsert node */
>> -static
>> -void reinsert_node(pbqp *this_,int u)
>> -{
>> - adjnode *adj_u,
>> - *adj_v;
>> -
>> - assert(this_!= NULL);
>> - assert(u >= 0 && u <= this_->num_nodes);
>> - assert(this_->adj_list != NULL);
>> -
>> - for(adj_u = this_ -> adj_list[u]; adj_u != NULL; adj_u = adj_u -
>> > succ) {
>> - int v = adj_u -> adj;
>> - adj_v = alloc_adjnode(this_,u,adj_u->costs);
>> - insert_adjnode(this_,v,adj_v);
>> - }
>> -}
>> -
>> -/* remove node */
>> -static
>> -void remove_node(pbqp *this_,int u)
>> -{
>> - adjnode *adj_ptr;
>> -
>> - assert(this_!= NULL);
>> - assert(u >= 0 && u <= this_->num_nodes);
>> - assert(this_->adj_list != NULL);
>> -
>> - for(adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr =
>> adj_ptr -> succ) {
>> - remove_adjnode(this_,adj_ptr->adj,adj_ptr -> reverse);
>> - }
>> -}
>> -
>> -/
>> *****************************************************************************
>> - * edge functions
>> -
>> ****************************************************************************/
>> -
>> -/* insert edge to graph */
>> -/* (does not check whether edge exists in graph */
>> -static
>> -void insert_edge(pbqp *this_, int u, int v, PBQPMatrix *costs)
>> -{
>> - adjnode *adj_u,
>> - *adj_v;
>> - - /* create adjanceny entry for u */
>> - adj_u = alloc_adjnode(this_,v,costs);
>> - insert_adjnode(this_,u,adj_u);
>> -
>> -
>> - /* create adjanceny entry for v */
>> - adj_v = alloc_adjnode(this_,u,costs);
>> - insert_adjnode(this_,v,adj_v);
>> - - /* create link for reverse edge */
>> - adj_u -> reverse = adj_v;
>> - adj_v -> reverse = adj_u;
>> -}
>> -
>> -/* delete edge */
>> -static
>> -void delete_edge(pbqp *this_,int u,int v)
>> -{
>> - adjnode *adj_ptr;
>> - adjnode *rev;
>> - - assert(this_ != NULL);
>> - assert( u >= 0 && u < this_->num_nodes);
>> - assert( v >= 0 && v < this_->num_nodes);
>> -
>> - adj_ptr=find_adjnode(this_,u,v);
>> - assert(adj_ptr != NULL);
>> - assert(adj_ptr->reverse != NULL);
>> -
>> - delete adj_ptr -> costs;
>> - - rev = adj_ptr->reverse; - remove_adjnode(this_,u,adj_ptr);
>> - remove_adjnode(this_,v,rev);
>> -} -
>> -/
>> *****************************************************************************
>> - * cost functions -
>> ****************************************************************************/
>> -
>> -/* Note: Since cost(u,v) = transpose(cost(v,u)), it would be
>> necessary to store - two matrices for both edges (u,v) and (v,u).
>> However, we only store the - matrix for the case u < v. For the
>> other case we transpose the stored matrix
>> - if required. -*/
>> -
>> -/* add costs to cost vector of a node */
>> -void add_pbqp_nodecosts(pbqp *this_,int u, PBQPVector *costs)
>> -{
>> - assert(this_ != NULL);
>> - assert(costs != NULL);
>> - assert(u >= 0 && u <= this_->num_nodes);
>> - - if (!this_->node_costs[u]) {
>> - this_->node_costs[u] = new PBQPVector(*costs);
>> - } else {
>> - *this_->node_costs[u] += *costs;
>> - }
>> -}
>> -
>> -/* get cost matrix ptr */
>> -static
>> -PBQPMatrix *get_costmatrix_ptr(pbqp *this_, int u, int v)
>> -{
>> - adjnode *adj_ptr;
>> - PBQPMatrix *m = NULL;
>> -
>> - assert (this_ != NULL);
>> - assert (u >= 0 && u < this_->num_nodes);
>> - assert (v >= 0 && v < this_->num_nodes); -
>> - adj_ptr = find_adjnode(this_,u,v);
>> -
>> - if (adj_ptr != NULL) {
>> - m = adj_ptr -> costs;
>> - } -
>> - return m;
>> -}
>> -
>> -/* get cost matrix ptr */
>> -/* Note: only the pointer is returned for - cost(u,v), if u < v.
>> -*/ -static
>> -PBQPMatrix *pbqp_get_costmatrix(pbqp *this_, int u, int v)
>> -{
>> - adjnode *adj_ptr = find_adjnode(this_,u,v);
>> - - if (adj_ptr != NULL) {
>> - if ( u < v) {
>> - return new PBQPMatrix(*adj_ptr->costs);
>> - } else {
>> - return new PBQPMatrix(adj_ptr->costs->transpose());
>> - }
>> - } else {
>> - return NULL;
>> - } -}
>> -
>> -/* add costs to cost matrix of an edge */
>> -void add_pbqp_edgecosts(pbqp *this_,int u,int v, PBQPMatrix *costs)
>> -{
>> - PBQPMatrix *adj_costs;
>> -
>> - assert(this_!= NULL);
>> - assert(costs != NULL);
>> - assert(u >= 0 && u <= this_->num_nodes);
>> - assert(v >= 0 && v <= this_->num_nodes);
>> - - /* does the edge u-v exists ? */
>> - if (u == v) {
>> - PBQPVector *diag = new PBQPVector(costs->diagonalize());
>> - add_pbqp_nodecosts(this_,v,diag);
>> - delete diag;
>> - } else if ((adj_costs = get_costmatrix_ptr(this_,u,v))!=NULL) {
>> - if ( u < v) {
>> - *adj_costs += *costs;
>> - } else {
>> - *adj_costs += costs->transpose();
>> - }
>> - } else {
>> - adj_costs = new PBQPMatrix((u < v) ? *costs : costs->transpose
>> ());
>> - insert_edge(this_,u,v,adj_costs);
>> - } -}
>> -
>> -/* remove bucket from bucket list */
>> -static
>> -void pbqp_remove_bucket(pbqp *this_, bucketnode *bucket)
>> -{
>> - int u = bucket->u;
>> - - assert(this_ != NULL);
>> - assert(u >= 0 && u < this_->num_nodes);
>> - assert(this_->bucket_list != NULL);
>> - assert(this_->bucket_ptr[u] != NULL);
>> - - /* update predecessor node in bucket list - (if no
>> preceeding bucket exists, then
>> - the bucket_list pointer needs to be - updated.)
>> - */ - if (bucket->prev != NULL) {
>> - bucket->prev-> succ = bucket->succ; - } else {
>> - this_->bucket_list[this_->node_deg[u]] = bucket -> succ;
>> - }
>> - - /* update successor node in bucket list */ - if (bucket-
>> >succ != NULL) { - bucket->succ-> prev = bucket->prev;
>> - }
>> -}
>> -
>> -/
>> **********************************************************************************
>> - * pop functions
>> -
>> **********************************************************************************/
>> -
>> -/* pop node of given degree */
>> -static
>> -int pop_node(pbqp *this_,int deg)
>> -{
>> - bucketnode *bucket;
>> - int u;
>> -
>> - assert(this_ != NULL);
>> - assert(deg >= 0 && deg <= this_->max_deg);
>> - assert(this_->bucket_list != NULL);
>> - - /* get first bucket of bucket list */
>> - bucket = this_->bucket_list[deg];
>> - assert(bucket != NULL);
>> -
>> - /* remove bucket */
>> - pbqp_remove_bucket(this_,bucket);
>> - u = bucket->u;
>> - free(bucket);
>> - return u;
>> -}
>> -
>> -/
>> **********************************************************************************
>> - * reorder functions
>> -
>> **********************************************************************************/
>> -
>> -/* add bucket to bucketlist */
>> -static
>> -void add_to_bucketlist(pbqp *this_,bucketnode *bucket, int deg)
>> -{
>> - bucketnode *old_head;
>> - - assert(bucket != NULL);
>> - assert(this_ != NULL);
>> - assert(deg >= 0 && deg <= this_->max_deg);
>> - assert(this_->bucket_list != NULL);
>> -
>> - /* store node degree (for re-ordering purposes)*/
>> - this_->node_deg[bucket->u] = deg;
>> - - /* put bucket to front of doubly chained list */
>> - old_head = this_->bucket_list[deg];
>> - bucket -> prev = NULL;
>> - bucket -> succ = old_head;
>> - this_ -> bucket_list[deg] = bucket;
>> - if (bucket -> succ != NULL ) {
>> - assert ( old_head -> prev == NULL);
>> - old_head -> prev = bucket;
>> - }
>> -}
>> -
>> -
>> -/* reorder node in bucket list according to - current node
>> degree */
>> -static
>> -void reorder_node(pbqp *this_, int u)
>> -{
>> - int deg; - - assert(this_ != NULL);
>> - assert(u>= 0 && u < this_->num_nodes);
>> - assert(this_->bucket_list != NULL);
>> - assert(this_->bucket_ptr[u] != NULL);
>> -
>> - /* get current node degree */
>> - deg = get_deg(this_,u);
>> - - /* remove bucket from old bucket list only
>> - if degree of node has changed. */
>> - if (deg != this_->node_deg[u]) {
>> - pbqp_remove_bucket(this_,this_->bucket_ptr[u]);
>> - add_to_bucketlist(this_,this_->bucket_ptr[u],deg);
>> - } -}
>> -
>> -/* reorder adj. nodes of a node */
>> -static
>> -void reorder_adjnodes(pbqp *this_,int u)
>> -{
>> - adjnode *adj_ptr;
>> - - assert(this_!= NULL);
>> - assert(u >= 0 && u <= this_->num_nodes);
>> - assert(this_->adj_list != NULL);
>> -
>> - for(adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr =
>> adj_ptr -> succ) {
>> - reorder_node(this_,adj_ptr->adj);
>> - }
>> -}
>> -
>> -/
>> **********************************************************************************
>> - * creation functions
>> -
>> **********************************************************************************/
>> -
>> -/* create new bucket entry */
>> -/* consistency of the bucket list is not checked! */
>> -static
>> -void create_bucket(pbqp *this_,int u,int deg)
>> -{
>> - bucketnode *bucket;
>> - - assert(this_ != NULL);
>> - assert(u >= 0 && u < this_->num_nodes);
>> - assert(this_->bucket_list != NULL);
>> - - bucket = (bucketnode *)malloc(sizeof(bucketnode));
>> - assert(bucket != NULL);
>> -
>> - bucket -> u = u;
>> - this_->bucket_ptr[u] = bucket;
>> -
>> - add_to_bucketlist(this_,bucket,deg);
>> -}
>> -
>> -/* create bucket list */
>> -static
>> -void create_bucketlist(pbqp *this_)
>> -{
>> - int u;
>> - int max_deg;
>> - int deg;
>> -
>> - assert(this_ != NULL);
>> - assert(this_->bucket_list == NULL);
>> -
>> - /* determine max. degree of the nodes */
>> - max_deg = 2; /* at least of degree two! */
>> - for(u=0;u<this_->num_nodes;u++) {
>> - deg = this_->node_deg[u] = get_deg(this_,u);
>> - if (deg > max_deg) {
>> - max_deg = deg;
>> - }
>> - }
>> - this_->max_deg = max_deg;
>> - - /* allocate bucket list */
>> - this_ -> bucket_list = (bucketnode **)malloc(sizeof(bucketnode *)
>> *(max_deg + 1));
>> - memset(this_->bucket_list,0,sizeof(bucketnode *)*(max_deg + 1));
>> - assert(this_->bucket_list != NULL);
>> - - /* insert nodes to the list */
>> - for(u=0;u<this_->num_nodes;u++) {
>> - create_bucket(this_,u,this_->node_deg[u]); - }
>> -}
>> -
>> -/
>> *****************************************************************************
>> - * PBQP simplification for trivial nodes
>> -
>> ****************************************************************************/
>> -
>> -/* remove trivial node with cost vector length of one */
>> -static
>> -void disconnect_trivialnode(pbqp *this_,int u)
>> -{
>> - int v;
>> - adjnode *adj_ptr, - *next;
>> - PBQPMatrix *c_uv;
>> - PBQPVector *c_v;
>> - - assert(this_ != NULL);
>> - assert(this_->node_costs != NULL);
>> - assert(u >= 0 && u < this_ -> num_nodes);
>> - assert(this_->node_costs[u]->getLength() == 1);
>> - - /* add edge costs to node costs of adj. nodes */
>> - for(adj_ptr = this_->adj_list[u]; adj_ptr != NULL; adj_ptr =
>> next){
>> - next = adj_ptr -> succ;
>> - v = adj_ptr -> adj;
>> - assert(v >= 0 && v < this_ -> num_nodes);
>> - - /* convert matrix to cost vector offset for adj. node */
>> - c_uv = pbqp_get_costmatrix(this_,u,v);
>> - c_v = new PBQPVector(c_uv->getRowAsVector(0));
>> - *this_->node_costs[v] += *c_v;
>> - - /* delete edge & free vec/mat */
>> - delete c_v;
>> - delete c_uv;
>> - delete_edge(this_,u,v);
>> - } -}
>> -
>> -/* find all trivial nodes and disconnect them */
>> -static -void eliminate_trivial_nodes(pbqp *this_)
>> -{
>> - int u;
>> - - assert(this_ != NULL);
>> - assert(this_ -> node_costs != NULL);
>> - - for(u=0;u < this_ -> num_nodes; u++) {
>> - if (this_->node_costs[u]->getLength() == 1) {
>> - disconnect_trivialnode(this_,u); - }
>> - }
>> -}
>> -
>> -/
>> *****************************************************************************
>> - * Normal form for PBQP -
>> ****************************************************************************/
>> -
>> -/* simplify a cost matrix. If the matrix
>> - is independent, then simplify_matrix
>> - returns true - otherwise false. In
>> - vectors u and v the offset values of
>> - the decomposition are stored. -*/
>> -
>> -static
>> -bool normalize_matrix(PBQPMatrix *m, PBQPVector *u, PBQPVector *v)
>> -{
>> - assert( m != NULL);
>> - assert( u != NULL);
>> - assert( v != NULL);
>> - assert( u->getLength() > 0);
>> - assert( v->getLength() > 0);
>> - - assert(m->getRows() == u->getLength());
>> - assert(m->getCols() == v->getLength());
>> -
>> - /* determine u vector */
>> - for(unsigned r = 0; r < m->getRows(); ++r) {
>> - PBQPNum min = m->getRowMin(r);
>> - (*u)[r] += min;
>> - if (!isInf(min)) {
>> - m->subFromRow(r, min);
>> - } else {
>> - m->setRow(r, 0);
>> - }
>> - }
>> - - /* determine v vector */
>> - for(unsigned c = 0; c < m->getCols(); ++c) {
>> - PBQPNum min = m->getColMin(c);
>> - (*v)[c] += min;
>> - if (!isInf(min)) {
>> - m->subFromCol(c, min);
>> - } else {
>> - m->setCol(c, 0);
>> - }
>> - }
>> - - /* determine whether matrix is - independent or not. -
>> */
>> - return m->isZero();
>> -}
>> -
>> -/* simplify single edge */
>> -static
>> -void simplify_edge(pbqp *this_,int u,int v)
>> -{
>> - PBQPMatrix *costs;
>> - bool is_zero; - - assert (this_ != NULL);
>> - assert (u >= 0 && u <this_->num_nodes);
>> - assert (v >= 0 && v <this_->num_nodes);
>> - assert (u != v);
>> -
>> - /* swap u and v if u > v in order to avoid un-necessary
>> - tranpositions of the cost matrix */
>> - - if (u > v) {
>> - int swap = u;
>> - u = v;
>> - v = swap;
>> - }
>> - - /* get cost matrix and simplify it */ - costs =
>> get_costmatrix_ptr(this_,u,v);
>> - is_zero=normalize_matrix(costs,this_->node_costs[u],this_-
>> >node_costs[v]);
>> -
>> - /* delete edge */
>> - if(is_zero){
>> - delete_edge(this_,u,v);
>> - this_->changed = true;
>> - }
>> -}
>> -
>> -/* normalize cost matrices and remove - edges in PBQP if they
>> ary independent, - i.e. can be decomposed into two - cost
>> vectors.
>> -*/
>> -static
>> -void eliminate_independent_edges(pbqp *this_)
>> -{
>> - int u,v;
>> - adjnode *adj_ptr,*next;
>> - - assert(this_ != NULL);
>> - assert(this_ -> adj_list != NULL);
>> -
>> - this_->changed = false;
>> - for(u=0;u < this_->num_nodes;u++) {
>> - for (adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr
>> = next) {
>> - next = adj_ptr -> succ;
>> - v = adj_ptr -> adj;
>> - assert(v >= 0 && v < this_->num_nodes);
>> - if (u < v) {
>> - simplify_edge(this_,u,v);
>> - } - }
>> - }
>> -}
>> -
>> -
>> -/
>> *****************************************************************************
>> - * PBQP reduction rules -
>> ****************************************************************************/
>> -
>> -/* RI reduction
>> - This reduction rule is applied for nodes - of degree one. */
>> -
>> -static
>> -void apply_RI(pbqp *this_,int x)
>> -{
>> - int y;
>> - unsigned xlen,
>> - ylen;
>> - PBQPMatrix *c_yx;
>> - PBQPVector *c_x, *delta;
>> - - assert(this_ != NULL);
>> - assert(x >= 0 && x < this_->num_nodes);
>> - assert(this_ -> adj_list[x] != NULL);
>> - assert(this_ -> adj_list[x] -> succ == NULL);
>> -
>> - /* get adjacence matrix */
>> - y = this_ -> adj_list[x] -> adj;
>> - assert(y >= 0 && y < this_->num_nodes);
>> - - /* determine length of cost vectors for node x and y */
>> - xlen = this_ -> node_costs[x]->getLength();
>> - ylen = this_ -> node_costs[y]->getLength();
>> -
>> - /* get cost vector c_x and matrix c_yx */
>> - c_x = this_ -> node_costs[x];
>> - c_yx = pbqp_get_costmatrix(this_,y,x); - assert (c_yx != NULL);
>> -
>> - - /* allocate delta vector */
>> - delta = new PBQPVector(ylen);
>> -
>> - /* compute delta vector */
>> - for(unsigned i = 0; i < ylen; ++i) {
>> - PBQPNum min = (*c_yx)[i][0] + (*c_x)[0];
>> - for(unsigned j = 1; j < xlen; ++j) {
>> - PBQPNum c = (*c_yx)[i][j] + (*c_x)[j];
>> - if ( c < min ) - min = c;
>> - }
>> - (*delta)[i] = min; - } -
>> - /* add delta vector */
>> - *this_ -> node_costs[y] += *delta;
>> -
>> - /* delete node x */
>> - remove_node(this_,x);
>> -
>> - /* reorder adj. nodes of node x */
>> - reorder_adjnodes(this_,x);
>> -
>> - /* push node x on stack */
>> - assert(this_ -> stack_ptr < this_ -> num_nodes);
>> - this_->stack[this_ -> stack_ptr++] = x;
>> -
>> - /* free vec/mat */
>> - delete c_yx;
>> - delete delta;
>> -
>> - /* increment counter for number statistic */
>> - this_->num_ri++;
>> -}
>> -
>> -/* RII reduction
>> - This reduction rule is applied for nodes - of degree two. */
>> -
>> -static
>> -void apply_RII(pbqp *this_,int x)
>> -{
>> - int y,z; - unsigned xlen,ylen,zlen;
>> - adjnode *adj_yz;
>> -
>> - PBQPMatrix *c_yx, *c_zx;
>> - PBQPVector *cx;
>> - PBQPMatrix *delta;
>> - - assert(this_ != NULL);
>> - assert(x >= 0 && x < this_->num_nodes);
>> - assert(this_ -> adj_list[x] != NULL);
>> - assert(this_ -> adj_list[x] -> succ != NULL);
>> - assert(this_ -> adj_list[x] -> succ -> succ == NULL);
>> -
>> - /* get adjacence matrix */
>> - y = this_ -> adj_list[x] -> adj;
>> - z = this_ -> adj_list[x] -> succ -> adj;
>> - assert(y >= 0 && y < this_->num_nodes);
>> - assert(z >= 0 && z < this_->num_nodes);
>> - - /* determine length of cost vectors for node x and y */
>> - xlen = this_ -> node_costs[x]->getLength();
>> - ylen = this_ -> node_costs[y]->getLength();
>> - zlen = this_ -> node_costs[z]->getLength();
>> -
>> - /* get cost vector c_x and matrix c_yx */
>> - cx = this_ -> node_costs[x];
>> - c_yx = pbqp_get_costmatrix(this_,y,x); - c_zx =
>> pbqp_get_costmatrix(this_,z,x); - assert(c_yx != NULL);
>> - assert(c_zx != NULL);
>> -
>> - /* Colour Heuristic */
>> - if ( (adj_yz = find_adjnode(this_,y,z)) != NULL) {
>> - adj_yz->tc_valid = false;
>> - adj_yz->reverse->tc_valid = false; - }
>> -
>> - /* allocate delta matrix */
>> - delta = new PBQPMatrix(ylen, zlen);
>> -
>> - /* compute delta matrix */
>> - for(unsigned i=0;i<ylen;i++) {
>> - for(unsigned j=0;j<zlen;j++) {
>> - PBQPNum min = (*c_yx)[i][0] + (*c_zx)[j][0] + (*cx)[0];
>> - for(unsigned k=1;k<xlen;k++) {
>> - PBQPNum c = (*c_yx)[i][k] + (*c_zx)[j][k] + (*cx)[k];
>> - if ( c < min ) {
>> - min = c;
>> - }
>> - }
>> - (*delta)[i][j] = min;
>> - }
>> - }
>> -
>> - /* add delta matrix */
>> - add_pbqp_edgecosts(this_,y,z,delta);
>> -
>> - /* delete node x */
>> - remove_node(this_,x);
>> -
>> - /* simplify cost matrix c_yz */
>> - simplify_edge(this_,y,z);
>> -
>> - /* reorder adj. nodes */
>> - reorder_adjnodes(this_,x);
>> -
>> - /* push node x on stack */
>> - assert(this_ -> stack_ptr < this_ -> num_nodes);
>> - this_->stack[this_ -> stack_ptr++] = x;
>> -
>> - /* free vec/mat */
>> - delete c_yx;
>> - delete c_zx;
>> - delete delta;
>> -
>> - /* increment counter for number statistic */
>> - this_->num_rii++;
>> -
>> -}
>> -
>> -/* RN reduction */
>> -static
>> -void apply_RN(pbqp *this_,int x)
>> -{
>> - unsigned xlen;
>> -
>> - assert(this_ != NULL);
>> - assert(x >= 0 && x < this_->num_nodes);
>> - assert(this_ -> node_costs[x] != NULL);
>> -
>> - xlen = this_ -> node_costs[x] -> getLength();
>> -
>> - /* after application of RN rule no optimality
>> - can be guaranteed! */
>> - this_ -> optimal = false;
>> - - /* push node x on stack */
>> - assert(this_ -> stack_ptr < this_ -> num_nodes);
>> - this_->stack[this_ -> stack_ptr++] = x;
>> -
>> - /* delete node x */ - remove_node(this_,x);
>> -
>> - /* reorder adj. nodes of node x */
>> - reorder_adjnodes(this_,x);
>> -
>> - /* increment counter for number statistic */
>> - this_->num_rn++;
>> -}
>> -
>> -
>> -static
>> -void compute_tc_info(pbqp *this_, adjnode *p)
>> -{
>> - adjnode *r;
>> - PBQPMatrix *m;
>> - int x,y;
>> - PBQPVector *c_x, *c_y;
>> - int *row_inf_counts;
>> -
>> - assert(p->reverse != NULL);
>> -
>> - /* set flags */ - r = p->reverse;
>> - p->tc_valid = true;
>> - r->tc_valid = true;
>> -
>> - /* get edge */
>> - x = r->adj;
>> - y = p->adj;
>> -
>> - /* get cost vectors */
>> - c_x = this_ -> node_costs[x];
>> - c_y = this_ -> node_costs[y];
>> -
>> - /* get cost matrix */
>> - m = pbqp_get_costmatrix(this_, x, y);
>> -
>> - - /* allocate allowed set for edge (x,y) and (y,x) */
>> - if (p->tc_safe_regs == NULL) {
>> - p->tc_safe_regs = (int *) malloc(sizeof(int) * c_x->getLength
>> ());
>> - } -
>> - if (r->tc_safe_regs == NULL ) {
>> - r->tc_safe_regs = (int *) malloc(sizeof(int) * c_y->getLength
>> ());
>> - }
>> -
>> - p->tc_impact = r->tc_impact = 0;
>> -
>> - row_inf_counts = (int *) alloca(sizeof(int) * c_x->getLength());
>> -
>> - /* init arrays */
>> - p->tc_safe_regs[0] = 0;
>> - row_inf_counts[0] = 0;
>> - for(unsigned i = 1; i < c_x->getLength(); ++i){
>> - p->tc_safe_regs[i] = 1;
>> - row_inf_counts[i] = 0;
>> - }
>> -
>> - r->tc_safe_regs[0] = 0;
>> - for(unsigned j = 1; j < c_y->getLength(); ++j){
>> - r->tc_safe_regs[j] = 1;
>> - }
>> -
>> - for(unsigned j = 0; j < c_y->getLength(); ++j) {
>> - int col_inf_counts = 0;
>> - for (unsigned i = 0; i < c_x->getLength(); ++i) {
>> - if (isInf((*m)[i][j])) {
>> - ++col_inf_counts;
>> - ++row_inf_counts[i];
>> - - p->tc_safe_regs[i] = 0;
>> - r->tc_safe_regs[j] = 0;
>> - }
>> - }
>> - if (col_inf_counts > p->tc_impact) {
>> - p->tc_impact = col_inf_counts;
>> - }
>> - }
>> -
>> - for(unsigned i = 0; i < c_x->getLength(); ++i){
>> - if (row_inf_counts[i] > r->tc_impact)
>> - {
>> - r->tc_impact = row_inf_counts[i];
>> - }
>> - }
>> - - delete m;
>> -}
>> -
>> -/* - * Checks whether node x can be locally coloured. - */
>> -static -int is_colorable(pbqp *this_,int x)
>> -{
>> - adjnode *adj_ptr;
>> - PBQPVector *c_x;
>> - int result = 1;
>> - int *allowed;
>> - int num_allowed = 0;
>> - unsigned total_impact = 0;
>> -
>> - assert(this_ != NULL);
>> - assert(x >= 0 && x < this_->num_nodes);
>> - assert(this_ -> node_costs[x] != NULL);
>> -
>> - c_x = this_ -> node_costs[x];
>> -
>> - /* allocate allowed set */
>> - allowed = (int *)malloc(sizeof(int) * c_x->getLength());
>> - for(unsigned i = 0; i < c_x->getLength(); ++i){
>> - if (!isInf((*c_x)[i]) && i > 0) {
>> - allowed[i] = 1;
>> - ++num_allowed;
>> - } else { - allowed[i] = 0;
>> - }
>> - }
>> -
>> - /* determine local minimum */
>> - for(adj_ptr=this_->adj_list[x] ;adj_ptr != NULL; adj_ptr =
>> adj_ptr -> succ) {
>> - if (!adj_ptr -> tc_valid) { - compute_tc_info
>> (this_, adj_ptr);
>> - }
>> -
>> - total_impact += adj_ptr->tc_impact;
>> -
>> - if (num_allowed > 0) {
>> - for (unsigned i = 1; i < c_x->getLength(); ++i){
>> - if (allowed[i]){
>> - if (!adj_ptr->tc_safe_regs[i]){
>> - allowed[i] = 0;
>> - --num_allowed;
>> - if (num_allowed == 0)
>> - break;
>> - }
>> - }
>> - }
>> - }
>> - - if ( total_impact >= c_x->getLength() - 1 &&
>> num_allowed == 0 ) {
>> - result = 0;
>> - break;
>> - }
>> - }
>> - free(allowed);
>> -
>> - return result;
>> -}
>> -
>> -/* use briggs heuristic - note: this_ is not a general heuristic.
>> it only is useful for - interference graphs.
>> - */
>> -int pop_colorablenode(pbqp *this_)
>> -{
>> - int deg;
>> - bucketnode *min_bucket=NULL;
>> - PBQPNum min = std::numeric_limits<PBQPNum>::infinity();
>> - - /* select node where the number of colors is less than the
>> node degree */
>> - for(deg=this_->max_deg;deg > 2;deg--) {
>> - bucketnode *bucket;
>> - for(bucket=this_->bucket_list[deg];bucket!= NULL;bucket =
>> bucket -> succ) {
>> - int u = bucket->u;
>> - if (is_colorable(this_,u)) {
>> - pbqp_remove_bucket(this_,bucket);
>> - this_->num_rn_special++;
>> - free(bucket);
>> - return u; - } - }
>> - }
>> -
>> - /* select node with minimal ratio between average node costs and
>> degree of node */
>> - for(deg=this_->max_deg;deg >2; deg--) {
>> - bucketnode *bucket;
>> - for(bucket=this_->bucket_list[deg];bucket!= NULL;bucket =
>> bucket -> succ) {
>> - PBQPNum h;
>> - int u;
>> - - u = bucket->u;
>> - assert(u>=0 && u < this_->num_nodes);
>> - h = (*this_->node_costs[u])[0] / (PBQPNum) deg;
>> - if (h < min) {
>> - min_bucket = bucket;
>> - min = h;
>> - } - }
>> - }
>> -
>> - /* return node and free bucket */
>> - if (min_bucket != NULL) {
>> - int u;
>> -
>> - pbqp_remove_bucket(this_,min_bucket);
>> - u = min_bucket->u;
>> - free(min_bucket);
>> - return u;
>> - } else {
>> - return -1;
>> - }
>> -}
>> -
>> -
>> -/
>> *****************************************************************************
>> - * PBQP graph parsing
>> -
>> ****************************************************************************/
>> - -/* reduce pbqp problem (first phase) */
>> -static
>> -void reduce_pbqp(pbqp *this_)
>> -{
>> - int u;
>> -
>> - assert(this_ != NULL);
>> - assert(this_->bucket_list != NULL);
>> -
>> - for(;;){
>> -
>> - if (this_->bucket_list[1] != NULL) {
>> - u = pop_node(this_,1);
>> - apply_RI(this_,u); - } else if (this_->bucket_list[2] !=
>> NULL) {
>> - u = pop_node(this_,2);
>> - apply_RII(this_,u);
>> - } else if ((u = pop_colorablenode(this_)) != -1) {
>> - apply_RN(this_,u);
>> - } else {
>> - break;
>> - }
>> - } -}
>> -
>> -/
>> *****************************************************************************
>> - * PBQP back propagation
>> -
>> ****************************************************************************/
>> -
>> -/* determine solution of a reduced node. Either
>> - RI or RII was applied for this_ node. */
>> -static
>> -void determine_solution(pbqp *this_,int x)
>> -{
>> - PBQPVector *v = new PBQPVector(*this_ -> node_costs[x]);
>> - adjnode *adj_ptr;
>> -
>> - assert(this_ != NULL);
>> - assert(x >= 0 && x < this_->num_nodes);
>> - assert(this_ -> adj_list != NULL);
>> - assert(this_ -> solution != NULL);
>> -
>> - for(adj_ptr=this_->adj_list[x] ;adj_ptr != NULL; adj_ptr =
>> adj_ptr -> succ) {
>> - int y = adj_ptr -> adj;
>> - int y_sol = this_ -> solution[y];
>> -
>> - PBQPMatrix *c_yx = pbqp_get_costmatrix(this_,y,x);
>> - assert(y_sol >= 0 && y_sol < (int)this_->node_costs[y]-
>> >getLength());
>> - (*v) += c_yx->getRowAsVector(y_sol);
>> - delete c_yx;
>> - }
>> - this_ -> solution[x] = v->minIndex();
>> -
>> - delete v;
>> -}
>> -
>> -/* back popagation phase of PBQP */
>> -static
>> -void back_propagate(pbqp *this_)
>> -{
>> - int i;
>> -
>> - assert(this_ != NULL);
>> - assert(this_->stack != NULL);
>> - assert(this_->stack_ptr < this_->num_nodes);
>> -
>> - for(i=this_ -> stack_ptr-1;i>=0;i--) {
>> - int x = this_ -> stack[i];
>> - assert( x >= 0 && x < this_ -> num_nodes);
>> - reinsert_node(this_,x);
>> - determine_solution(this_,x);
>> - }
>> -}
>> -
>> -/* solve trivial nodes of degree zero */
>> -static
>> -void determine_trivialsolution(pbqp *this_)
>> -{
>> - int u;
>> - PBQPNum delta;
>> -
>> - assert( this_ != NULL);
>> - assert( this_ -> bucket_list != NULL);
>> -
>> - /* determine trivial solution */
>> - while (this_->bucket_list[0] != NULL) {
>> - u = pop_node(this_,0);
>> -
>> - assert( u >= 0 && u < this_ -> num_nodes);
>> -
>> - this_->solution[u] = this_->node_costs[u]->minIndex();
>> - delta = (*this_->node_costs[u])[this_->solution[u]];
>> - this_->min = this_->min + delta;
>> -
>> - /* increment counter for number statistic */
>> - this_->num_r0++;
>> - }
>> -}
>> -
>> -/
>> *****************************************************************************
>> - * debug facilities
>> -
>> ****************************************************************************/
>> -static
>> -void check_pbqp(pbqp *this_)
>> -{
>> - int u,v;
>> - PBQPMatrix *costs;
>> - adjnode *adj_ptr;
>> - - assert( this_ != NULL);
>> - - for(u=0;u< this_->num_nodes; u++) {
>> - assert (this_ -> node_costs[u] != NULL);
>> - for(adj_ptr = this_ -> adj_list[u];adj_ptr != NULL; adj_ptr =
>> adj_ptr -> succ) {
>> - v = adj_ptr -> adj;
>> - assert( v>= 0 && v < this_->num_nodes);
>> - if (u < v ) {
>> - costs = adj_ptr -> costs;
>> - assert( costs->getRows() == this_->node_costs[u]->getLength
>> () &&
>> - costs->getCols() == this_->node_costs[v]->getLength
>> ());
>> - } - }
>> - }
>> -}
>> -
>> -/
>> *****************************************************************************
>> - * PBQP solve routines -
>> ****************************************************************************/
>> -
>> -/* solve PBQP problem */
>> -void solve_pbqp(pbqp *this_)
>> -{
>> - assert(this_ != NULL);
>> - assert(!this_->solved); - - /* check vector & matrix
>> dimensions */
>> - check_pbqp(this_);
>> -
>> - /* simplify PBQP problem */ - - /* eliminate trivial nodes,
>> i.e.
>> - nodes with cost vectors of length one. */
>> - eliminate_trivial_nodes(this_); -
>> - /* eliminate edges with independent - cost matrices and
>> normalize matrices */
>> - eliminate_independent_edges(this_);
>> - - /* create bucket list for graph parsing */
>> - create_bucketlist(this_);
>> - - /* reduce phase */
>> - reduce_pbqp(this_);
>> - - /* solve trivial nodes */
>> - determine_trivialsolution(this_);
>> -
>> - /* back propagation phase */
>> - back_propagate(this_); - - this_->solved = true;
>> -}
>> -
>> -/* get solution of a node */
>> -int get_pbqp_solution(pbqp *this_,int x)
>> -{
>> - assert(this_ != NULL);
>> - assert(this_->solution != NULL);
>> - assert(this_ -> solved);
>> - - return this_->solution[x];
>> -}
>> -
>> -/* is solution optimal? */
>> -bool is_pbqp_optimal(pbqp *this_)
>> -{
>> - assert(this_ -> solved);
>> - return this_->optimal;
>> -}
>> -
>> -} -
>> -/* end of pbqp.c */
>>
>> Removed: llvm/trunk/lib/CodeGen/PBQP.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP.h?rev=78353&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP.h (original)
>> +++ llvm/trunk/lib/CodeGen/PBQP.h (removed)
>> @@ -1,284 +0,0 @@
>> -//===---------------- PBQP.cpp --------- PBQP Solver ------------
>> *- C++ -*-===//
>> -//
>> -// The LLVM Compiler Infrastructure
>> -//
>> -// This file is distributed under the University of Illinois Open
>> Source
>> -// License. See LICENSE.TXT for details.
>> -//
>> -//
>> =
>> =
>> =
>> ----------------------------------------------------------------------=
>> ==//
>> -//
>> -// Developed by: Bernhard Scholz
>> -// The University of Sydney
>> -// http://www.it.usyd.edu.au/~scholz
>> -//
>> =
>> =
>> =
>> ----------------------------------------------------------------------=
>> ==//
>> -
>> -// TODO:
>> -//
>> -// * Default to null costs on vector initialisation?
>> -// * C++-ify the rest of the solver.
>> -
>> -#ifndef LLVM_CODEGEN_PBQPSOLVER_H
>> -#define LLVM_CODEGEN_PBQPSOLVER_H
>> -
>> -#include <cassert>
>> -#include <algorithm>
>> -#include <functional>
>> -
>> -namespace llvm {
>> -
>> -//! \brief Floating point type to use in PBQP solver.
>> -typedef double PBQPNum;
>> -
>> -//! \brief PBQP Vector class.
>> -class PBQPVector {
>> -public:
>> -
>> - //! \brief Construct a PBQP vector of the given size.
>> - explicit PBQPVector(unsigned length) :
>> - length(length), data(new PBQPNum[length]) {
>> - std::fill(data, data + length, 0);
>> - }
>> -
>> - //! \brief Copy construct a PBQP vector.
>> - PBQPVector(const PBQPVector &v) :
>> - length(v.length), data(new PBQPNum[length]) {
>> - std::copy(v.data, v.data + length, data);
>> - }
>> -
>> - ~PBQPVector() { delete[] data; }
>> -
>> - //! \brief Assignment operator.
>> - PBQPVector& operator=(const PBQPVector &v) {
>> - delete[] data;
>> - length = v.length;
>> - data = new PBQPNum[length];
>> - std::copy(v.data, v.data + length, data);
>> - return *this;
>> - }
>> -
>> - //! \brief Return the length of the vector
>> - unsigned getLength() const throw () {
>> - return length;
>> - }
>> -
>> - //! \brief Element access.
>> - PBQPNum& operator[](unsigned index) {
>> - assert(index < length && "PBQPVector element access out of
>> bounds.");
>> - return data[index];
>> - }
>> -
>> - //! \brief Const element access.
>> - const PBQPNum& operator[](unsigned index) const {
>> - assert(index < length && "PBQPVector element access out of
>> bounds.");
>> - return data[index];
>> - }
>> -
>> - //! \brief Add another vector to this one.
>> - PBQPVector& operator+=(const PBQPVector &v) {
>> - assert(length == v.length && "PBQPVector length mismatch.");
>> - std::transform(data, data + length, v.data, data,
>> std::plus<PBQPNum>()); - return *this;
>> - }
>> -
>> - //! \brief Subtract another vector from this one.
>> - PBQPVector& operator-=(const PBQPVector &v) {
>> - assert(length == v.length && "PBQPVector length mismatch.");
>> - std::transform(data, data + length, v.data, data,
>> std::minus<PBQPNum>()); - return *this;
>> - }
>> -
>> - //! \brief Returns the index of the minimum value in this vector
>> - unsigned minIndex() const {
>> - return std::min_element(data, data + length) - data;
>> - }
>> -
>> -private:
>> - unsigned length;
>> - PBQPNum *data;
>> -};
>> -
>> -
>> -//! \brief PBQP Matrix class
>> -class PBQPMatrix {
>> -public:
>> -
>> - //! \brief Construct a PBQP Matrix with the given dimensions.
>> - PBQPMatrix(unsigned rows, unsigned cols) :
>> - rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
>> - std::fill(data, data + (rows * cols), 0);
>> - }
>> -
>> - //! \brief Copy construct a PBQP matrix.
>> - PBQPMatrix(const PBQPMatrix &m) :
>> - rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) {
>> - std::copy(m.data, m.data + (rows * cols), data); - }
>> -
>> - ~PBQPMatrix() { delete[] data; }
>> -
>> - //! \brief Assignment operator.
>> - PBQPMatrix& operator=(const PBQPMatrix &m) {
>> - delete[] data;
>> - rows = m.rows; cols = m.cols;
>> - data = new PBQPNum[rows * cols];
>> - std::copy(m.data, m.data + (rows * cols), data);
>> - return *this;
>> - }
>> -
>> - //! \brief Return the number of rows in this matrix.
>> - unsigned getRows() const throw () { return rows; }
>> -
>> - //! \brief Return the number of cols in this matrix.
>> - unsigned getCols() const throw () { return cols; }
>> -
>> - //! \brief Matrix element access.
>> - PBQPNum* operator[](unsigned r) {
>> - assert(r < rows && "Row out of bounds.");
>> - return data + (r * cols);
>> - }
>> -
>> - //! \brief Matrix element access.
>> - const PBQPNum* operator[](unsigned r) const {
>> - assert(r < rows && "Row out of bounds.");
>> - return data + (r * cols);
>> - }
>> -
>> - //! \brief Returns the given row as a vector.
>> - PBQPVector getRowAsVector(unsigned r) const {
>> - PBQPVector v(cols);
>> - for (unsigned c = 0; c < cols; ++c)
>> - v[c] = (*this)[r][c];
>> - return v; - }
>> -
>> - //! \brief Reset the matrix to the given value.
>> - PBQPMatrix& reset(PBQPNum val = 0) {
>> - std::fill(data, data + (rows * cols), val);
>> - return *this;
>> - }
>> -
>> - //! \brief Set a single row of this matrix to the given value.
>> - PBQPMatrix& setRow(unsigned r, PBQPNum val) {
>> - assert(r < rows && "Row out of bounds.");
>> - std::fill(data + (r * cols), data + ((r + 1) * cols), val);
>> - return *this;
>> - }
>> -
>> - //! \brief Set a single column of this matrix to the given value.
>> - PBQPMatrix& setCol(unsigned c, PBQPNum val) {
>> - assert(c < cols && "Column out of bounds.");
>> - for (unsigned r = 0; r < rows; ++r)
>> - (*this)[r][c] = val;
>> - return *this;
>> - }
>> -
>> - //! \brief Matrix transpose.
>> - PBQPMatrix transpose() const {
>> - PBQPMatrix m(cols, rows);
>> - for (unsigned r = 0; r < rows; ++r)
>> - for (unsigned c = 0; c < cols; ++c)
>> - m[c][r] = (*this)[r][c];
>> - return m;
>> - }
>> -
>> - //! \brief Returns the diagonal of the matrix as a vector.
>> - //!
>> - //! Matrix must be square.
>> - PBQPVector diagonalize() const {
>> - assert(rows == cols && "Attempt to diagonalize non-square
>> matrix.");
>> -
>> - PBQPVector v(rows);
>> - for (unsigned r = 0; r < rows; ++r)
>> - v[r] = (*this)[r][r];
>> - return v;
>> - } -
>> - //! \brief Add the given matrix to this one.
>> - PBQPMatrix& operator+=(const PBQPMatrix &m) {
>> - assert(rows == m.rows && cols == m.cols &&
>> - "Matrix dimensions mismatch.");
>> - std::transform(data, data + (rows * cols), m.data, data,
>> - std::plus<PBQPNum>());
>> - return *this;
>> - }
>> -
>> - //! \brief Returns the minimum of the given row
>> - PBQPNum getRowMin(unsigned r) const {
>> - assert(r < rows && "Row out of bounds");
>> - return *std::min_element(data + (r * cols), data + ((r + 1) *
>> cols));
>> - }
>> -
>> - //! \brief Returns the minimum of the given column
>> - PBQPNum getColMin(unsigned c) const {
>> - PBQPNum minElem = (*this)[0][c];
>> - for (unsigned r = 1; r < rows; ++r)
>> - if ((*this)[r][c] < minElem) minElem = (*this)[r][c];
>> - return minElem;
>> - }
>> -
>> - //! \brief Subtracts the given scalar from the elements of the
>> given row.
>> - PBQPMatrix& subFromRow(unsigned r, PBQPNum val) {
>> - assert(r < rows && "Row out of bounds");
>> - std::transform(data + (r * cols), data + ((r + 1) * cols),
>> - data + (r * cols),
>> - std::bind2nd(std::minus<PBQPNum>(), val));
>> - return *this;
>> - }
>> -
>> - //! \brief Subtracts the given scalar from the elements of the
>> given column.
>> - PBQPMatrix& subFromCol(unsigned c, PBQPNum val) {
>> - for (unsigned r = 0; r < rows; ++r)
>> - (*this)[r][c] -= val;
>> - return *this;
>> - }
>> -
>> - //! \brief Returns true if this is a zero matrix.
>> - bool isZero() const {
>> - return find_if(data, data + (rows * cols),
>> - std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) ==
>> - data + (rows * cols);
>> - }
>> -
>> -private:
>> - unsigned rows, cols;
>> - PBQPNum *data;
>> -};
>> -
>> -#define EPS (1E-8)
>> -
>> -#ifndef PBQP_TYPE
>> -#define PBQP_TYPE
>> -struct pbqp;
>> -typedef struct pbqp pbqp;
>> -#endif
>> -
>> -/*****************
>> - * PBQP routines *
>> - *****************/
>> -
>> -/* allocate pbqp problem */
>> -pbqp *alloc_pbqp(int num);
>> -
>> -/* add node costs */
>> -void add_pbqp_nodecosts(pbqp *this_,int u, PBQPVector *costs);
>> -
>> -/* add edge mat */
>> -void add_pbqp_edgecosts(pbqp *this_,int u,int v,PBQPMatrix *costs);
>> -
>> -/* solve PBQP problem */
>> -void solve_pbqp(pbqp *this_);
>> -
>> -/* get solution of a node */
>> -int get_pbqp_solution(pbqp *this_,int u);
>> -
>> -/* alloc PBQP */
>> -pbqp *alloc_pbqp(int num);
>> -
>> -/* free PBQP */
>> -void free_pbqp(pbqp *this_);
>> -
>> -/* is optimal */
>> -bool is_pbqp_optimal(pbqp *this_);
>> -
>> -}
>> -#endif
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/AnnotatedGraph.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/AnnotatedGraph.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/AnnotatedGraph.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/AnnotatedGraph.h Thu Aug 6
>> 18:32:48 2009
>> @@ -0,0 +1,170 @@
>> +#ifndef LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H
>> +#define LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H
>> +
>> +#include "GraphBase.h"
>> +
>> +namespace PBQP {
>> +
>> +
>> +template <typename NodeData, typename EdgeData> class AnnotatedEdge;
>> +
>> +template <typename NodeData, typename EdgeData>
>> +class AnnotatedNode : public NodeBase<AnnotatedNode<NodeData,
>> EdgeData>,
>> + AnnotatedEdge<NodeData,
>> EdgeData> > {
>> +private:
>> +
>> + NodeData nodeData; +
>> +public:
>> +
>> + AnnotatedNode(const Vector &costs, const NodeData &nodeData) :
>> + NodeBase<AnnotatedNode<NodeData, EdgeData>,
>> + AnnotatedEdge<NodeData, EdgeData> >(costs),
>> + nodeData(nodeData) {}
>> +
>> + NodeData& getNodeData() { return nodeData; }
>> + const NodeData& getNodeData() const { return nodeData; }
>> +
>> +};
>> +
>> +template <typename NodeData, typename EdgeData>
>> +class AnnotatedEdge : public EdgeBase<AnnotatedNode<NodeData,
>> EdgeData>,
>> + AnnotatedEdge<NodeData,
>> EdgeData> > {
>> +private:
>> +
>> + typedef typename GraphBase<AnnotatedNode<NodeData, EdgeData>,
>> + AnnotatedEdge<NodeData, EdgeData>
>> >::NodeIterator
>> + NodeIterator;
>> +
>> + EdgeData edgeData; +
>> +public:
>> +
>> +
>> + AnnotatedEdge(const NodeIterator &node1Itr, const NodeIterator
>> &node2Itr,
>> + const Matrix &costs, const EdgeData &edgeData) :
>> + EdgeBase<AnnotatedNode<NodeData, EdgeData>,
>> + AnnotatedEdge<NodeData, EdgeData> >(node1Itr,
>> node2Itr, costs),
>> + edgeData(edgeData) {}
>> +
>> + EdgeData& getEdgeData() { return edgeData; }
>> + const EdgeData& getEdgeData() const { return edgeData; }
>> +
>> +};
>> +
>> +template <typename NodeData, typename EdgeData>
>> +class AnnotatedGraph : public GraphBase<AnnotatedNode<NodeData,
>> EdgeData>,
>> + AnnotatedEdge<NodeData,
>> EdgeData> > {
>> +private:
>> +
>> + typedef GraphBase<AnnotatedNode<NodeData, EdgeData>,
>> + AnnotatedEdge<NodeData, EdgeData> > PGraph;
>> +
>> + typedef AnnotatedNode<NodeData, EdgeData> NodeEntry;
>> + typedef AnnotatedEdge<NodeData, EdgeData> EdgeEntry;
>> +
>> +
>> + void copyFrom(const AnnotatedGraph &other) {
>> + if (!other.areNodeIDsValid()) {
>> + other.assignNodeIDs();
>> + }
>> + std::vector<NodeIterator> newNodeItrs(other.getNumNodes());
>> +
>> + for (ConstNodeIterator nItr = other.nodesBegin(), nEnd =
>> other.nodesEnd();
>> + nItr != nEnd; ++nItr) {
>> + newNodeItrs[other.getNodeID(nItr)] = addNode
>> (other.getNodeCosts(nItr));
>> + }
>> +
>> + for (ConstEdgeIterator eItr = other.edgesBegin(), eEnd =
>> other.edgesEnd();
>> + eItr != eEnd; ++eItr) {
>> +
>> + unsigned node1ID = other.getNodeID(other.getEdgeNode1(eItr)),
>> + node2ID = other.getNodeID(other.getEdgeNode2(eItr));
>> +
>> + addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID],
>> + other.getEdgeCosts(eItr), other.getEdgeData(eItr));
>> + }
>> +
>> + }
>> +
>> +public:
>> +
>> + typedef typename PGraph::NodeIterator NodeIterator;
>> + typedef typename PGraph::ConstNodeIterator ConstNodeIterator;
>> + typedef typename PGraph::EdgeIterator EdgeIterator;
>> + typedef typename PGraph::ConstEdgeIterator ConstEdgeIterator;
>> +
>> + AnnotatedGraph() {}
>> +
>> + AnnotatedGraph(const AnnotatedGraph &other) {
>> + copyFrom(other);
>> + }
>> +
>> + AnnotatedGraph& operator=(const AnnotatedGraph &other) {
>> + PGraph::clear();
>> + copyFrom(other);
>> + return *this;
>> + }
>> +
>> + NodeIterator addNode(const Vector &costs, const NodeData &data) {
>> + return PGraph::addConstructedNode(NodeEntry(costs, data));
>> + }
>> +
>> + EdgeIterator addEdge(const NodeIterator &node1Itr,
>> + const NodeIterator &node2Itr,
>> + const Matrix &costs, const EdgeData &data) {
>> + return PGraph::addConstructedEdge(EdgeEntry(node1Itr, node2Itr,
>> + costs, data));
>> + }
>> +
>> + NodeData& getNodeData(const NodeIterator &nodeItr) {
>> + return getNodeEntry(nodeItr).getNodeData();
>> + }
>> +
>> + const NodeData& getNodeData(const NodeIterator &nodeItr) const {
>> + return getNodeEntry(nodeItr).getNodeData();
>> + }
>> +
>> + EdgeData& getEdgeData(const EdgeIterator &edgeItr) {
>> + return getEdgeEntry(edgeItr).getEdgeData();
>> + }
>> +
>> + const EdgeEntry& getEdgeData(const EdgeIterator &edgeItr) const {
>> + return getEdgeEntry(edgeItr).getEdgeData();
>> + }
>> +
>> + SimpleGraph toSimpleGraph() const {
>> + SimpleGraph g;
>> +
>> + if (!PGraph::areNodeIDsValid()) {
>> + PGraph::assignNodeIDs();
>> + }
>> + std::vector<SimpleGraph::NodeIterator> newNodeItrs
>> (PGraph::getNumNodes());
>> +
>> + for (ConstNodeIterator nItr = PGraph::nodesBegin(), +
>> nEnd = PGraph::nodesEnd();
>> + nItr != nEnd; ++nItr) {
>> +
>> + newNodeItrs[getNodeID(nItr)] = g.addNode(getNodeCosts(nItr));
>> + }
>> +
>> + for (ConstEdgeIterator
>> + eItr = PGraph::edgesBegin(), eEnd = PGraph::edgesEnd();
>> + eItr != eEnd; ++eItr) {
>> +
>> + unsigned node1ID = getNodeID(getEdgeNode1(eItr)),
>> + node2ID = getNodeID(getEdgeNode2(eItr));
>> +
>> + g.addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID],
>> + getEdgeCosts(eItr));
>> + }
>> +
>> + return g;
>> + }
>> +
>> +};
>> +
>> +
>> +}
>> +
>> +#endif // LLVM_CODEGEN_PBQP_ANNOTATEDGRAPH_H
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/ExhaustiveSolver.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/ExhaustiveSolver.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/ExhaustiveSolver.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/ExhaustiveSolver.h Thu Aug 6
>> 18:32:48 2009
>> @@ -0,0 +1,93 @@
>> +#ifndef LLVM_CODEGEN_PBQP_EXHAUSTIVESOLVER_H
>> +#define LLVM_CODEGEN_PBQP_EXHAUSTIVESOLVER_H
>> +
>> +#include "Solver.h"
>> +
>> +namespace PBQP {
>> +
>> +class ExhaustiveSolverImpl {
>> +private:
>> +
>> + const SimpleGraph &g;
>> +
>> + PBQPNum getSolutionCost(const Solution &solution) const {
>> + PBQPNum cost = 0.0;
>> + + for (SimpleGraph::ConstNodeIterator
>> + nodeItr = g.nodesBegin(), nodeEnd = g.nodesEnd();
>> + nodeItr != nodeEnd; ++nodeItr) {
>> + + unsigned nodeId = g.getNodeID(nodeItr);
>> +
>> + cost += g.getNodeCosts(nodeItr)[solution.getSelection
>> (nodeId)];
>> + }
>> +
>> + for (SimpleGraph::ConstEdgeIterator
>> + edgeItr = g.edgesBegin(), edgeEnd = g.edgesEnd();
>> + edgeItr != edgeEnd; ++edgeItr) {
>> + + SimpleGraph::ConstNodeIterator n1 = g.getEdgeNode1Itr
>> (edgeItr),
>> + n2 = g.getEdgeNode2Itr
>> (edgeItr);
>> + unsigned sol1 = solution.getSelection(g.getNodeID(n1)),
>> + sol2 = solution.getSelection(g.getNodeID(n2));
>> +
>> + cost += g.getEdgeCosts(edgeItr)[sol1][sol2];
>> + }
>> +
>> + return cost;
>> + }
>> +
>> +public:
>> +
>> + ExhaustiveSolverImpl(const SimpleGraph &g) : g(g) {}
>> +
>> + Solution solve() const {
>> + Solution current(g.getNumNodes(), true), optimal(current);
>> +
>> + PBQPNum bestCost = std::numeric_limits<PBQPNum>::infinity();
>> + bool finished = false;
>> +
>> + while (!finished) {
>> + PBQPNum currentCost = getSolutionCost(current);
>> +
>> + if (currentCost < bestCost) {
>> + optimal = current;
>> + bestCost = currentCost;
>> + }
>> +
>> + // assume we're done.
>> + finished = true;
>> +
>> + for (unsigned i = 0; i < g.getNumNodes(); ++i) {
>> + if (current.getSelection(i) ==
>> + (g.getNodeCosts(g.getNodeItr(i)).getLength() - 1)) {
>> + current.setSelection(i, 0);
>> + }
>> + else {
>> + current.setSelection(i, current.getSelection(i) + 1);
>> + finished = false;
>> + break;
>> + }
>> + }
>> +
>> + }
>> +
>> + optimal.setSolutionCost(bestCost);
>> +
>> + return optimal;
>> + }
>> +
>> +};
>> +
>> +class ExhaustiveSolver : public Solver {
>> +public:
>> + ~ExhaustiveSolver() {}
>> + Solution solve(const SimpleGraph &g) const {
>> + ExhaustiveSolverImpl solver(g);
>> + return solver.solve();
>> + }
>> +};
>> +
>> +}
>> +
>> +#endif // LLVM_CODGEN_PBQP_EXHAUSTIVESOLVER_HPP
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/GraphBase.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/GraphBase.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/GraphBase.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/GraphBase.h Thu Aug 6 18:32:48 2009
>> @@ -0,0 +1,570 @@
>> +#ifndef LLVM_CODEGEN_PBQP_GRAPHBASE_H
>> +#define LLVM_CODEGEN_PBQP_GRAPHBASE_H
>> +
>> +#include "PBQPMath.h"
>> +
>> +#include <list>
>> +#include <vector>
>> +
>> +namespace PBQP {
>> +
>> +// UGLY, but I'm not sure there's a good way around this: We need
>> to be able to
>> +// look up a Node's "adjacent edge list" structure type before the
>> Node type is
>> +// fully constructed. We can enable this by pushing the choice of
>> data type
>> +// out into this traits class.
>> +template <typename Graph>
>> +class NodeBaseTraits {
>> + public:
>> + typedef std::list<typename Graph::EdgeIterator> AdjEdgeList;
>> + typedef typename AdjEdgeList::iterator AdjEdgeIterator;
>> + typedef typename AdjEdgeList::const_iterator
>> ConstAdjEdgeIterator;
>> +};
>> +
>> +/// \brief Base for concrete graph classes. Provides a basic set
>> of graph
>> +/// operations which are useful for PBQP solvers.
>> +template <typename NodeEntry, typename EdgeEntry>
>> +class GraphBase {
>> +private:
>> +
>> + typedef GraphBase<NodeEntry, EdgeEntry> ThisGraphT;
>> +
>> + typedef std::list<NodeEntry> NodeList;
>> + typedef std::list<EdgeEntry> EdgeList;
>> +
>> + NodeList nodeList;
>> + unsigned nodeListSize;
>> +
>> + EdgeList edgeList;
>> + unsigned edgeListSize;
>> +
>> + GraphBase(const ThisGraphT &other) { abort(); }
>> + void operator=(const ThisGraphT &other) { abort(); } + +public:
>> +
>> + /// \brief Iterates over the nodes of a graph.
>> + typedef typename NodeList::iterator NodeIterator;
>> + /// \brief Iterates over the nodes of a const graph.
>> + typedef typename NodeList::const_iterator ConstNodeIterator;
>> + /// \brief Iterates over the edges of a graph.
>> + typedef typename EdgeList::iterator EdgeIterator;
>> + /// \brief Iterates over the edges of a const graph.
>> + typedef typename EdgeList::const_iterator ConstEdgeIterator;
>> +
>> + /// \brief Iterates over the edges attached to a node.
>> + typedef typename NodeBaseTraits<ThisGraphT>::AdjEdgeIterator
>> + AdjEdgeIterator;
>> +
>> + /// \brief Iterates over the edges attached to a node in a const
>> graph.
>> + typedef typename NodeBaseTraits<ThisGraphT>::ConstAdjEdgeIterator
>> + ConstAdjEdgeIterator;
>> +
>> +private:
>> +
>> + typedef std::vector<NodeIterator> IDToNodeMap;
>> +
>> + IDToNodeMap idToNodeMap;
>> + bool nodeIDsValid;
>> +
>> + void invalidateNodeIDs() {
>> + if (nodeIDsValid) {
>> + idToNodeMap.clear();
>> + nodeIDsValid = false;
>> + }
>> + }
>> +
>> + template <typename ItrT>
>> + bool iteratorInRange(ItrT itr, const ItrT &begin, const ItrT
>> &end) {
>> + for (ItrT t = begin; t != end; ++t) {
>> + if (itr == t)
>> + return true;
>> + }
>> +
>> + return false;
>> + }
>> +
>> +protected:
>> +
>> + GraphBase() : nodeListSize(0), edgeListSize(0), nodeIDsValid
>> (false) {}
>> + + NodeEntry& getNodeEntry(const NodeIterator &nodeItr) { return
>> *nodeItr; }
>> + const NodeEntry& getNodeEntry(const ConstNodeIterator &nodeItr)
>> const {
>> + return *nodeItr;
>> + }
>> +
>> + EdgeEntry& getEdgeEntry(const EdgeIterator &edgeItr) { return
>> *edgeItr; }
>> + const EdgeEntry& getEdgeEntry(const ConstEdgeIterator &edgeItr)
>> const {
>> + return *edgeItr;
>> + }
>> +
>> + NodeIterator addConstructedNode(const NodeEntry &nodeEntry) {
>> + ++nodeListSize;
>> +
>> + invalidateNodeIDs();
>> +
>> + NodeIterator newNodeItr = nodeList.insert(nodeList.end(),
>> nodeEntry);
>> +
>> + return newNodeItr;
>> + }
>> +
>> + EdgeIterator addConstructedEdge(const EdgeEntry &edgeEntry) {
>> +
>> + assert((findEdge(edgeEntry.getNode1Itr(), edgeEntry.getNode2Itr
>> ())
>> + == edgeList.end()) && "Attempt to add duplicate edge.");
>> +
>> + ++edgeListSize;
>> +
>> + // Add the edge to the graph.
>> + EdgeIterator edgeItr = edgeList.insert(edgeList.end(),
>> edgeEntry);
>> +
>> + // Get a reference to the version in the graph.
>> + EdgeEntry &newEdgeEntry = getEdgeEntry(edgeItr);
>> +
>> + // Node entries:
>> + NodeEntry &node1Entry = getNodeEntry(newEdgeEntry.getNode1Itr
>> ()),
>> + &node2Entry = getNodeEntry(newEdgeEntry.getNode2Itr
>> ());
>> +
>> + unsigned n1Len = node1Entry.getCosts().getLength(),
>> + n2Len = node2Entry.getCosts().getLength(),
>> + mRows = newEdgeEntry.getCosts().getRows(),
>> + mCols = newEdgeEntry.getCosts().getCols();
>> +
>> + // Sanity check on matrix dimensions.
>> + assert((n1Len == mRows) && (n2Len == mCols) &&
>> + "Matrix dimensions do not match cost vector dimensions.");
>> +
>> + // Create links between nodes and edges.
>> + newEdgeEntry.setNode1ThisEdgeItr(
>> + node1Entry.addAdjEdge(edgeItr));
>> + newEdgeEntry.setNode2ThisEdgeItr(
>> + node2Entry.addAdjEdge(edgeItr));
>> +
>> + return edgeItr;
>> + }
>> +
>> +public:
>> +
>> + /// \brief Returns the number of nodes in this graph.
>> + unsigned getNumNodes() const { return nodeListSize; }
>> +
>> + /// \brief Returns the number of edges in this graph.
>> + unsigned getNumEdges() const { return edgeListSize; } +
>> + /// \brief Return the cost vector for the given node.
>> + Vector& getNodeCosts(const NodeIterator &nodeItr) {
>> + return getNodeEntry(nodeItr).getCosts();
>> + }
>> +
>> + /// \brief Return the cost vector for the give node. + const
>> Vector& getNodeCosts(const ConstNodeIterator &nodeItr) const {
>> + return getNodeEntry(nodeItr).getCosts();
>> + }
>> +
>> + /// \brief Return the degree of the given node.
>> + unsigned getNodeDegree(const NodeIterator &nodeItr) const {
>> + return getNodeEntry(nodeItr).getDegree();
>> + }
>> +
>> + /// \brief Assigns sequential IDs to the nodes, starting at 0,
>> which
>> + /// remain valid until the next addition or removal of a node.
>> + void assignNodeIDs() {
>> + unsigned curID = 0;
>> + idToNodeMap.resize(getNumNodes());
>> + for (NodeIterator nodeItr = nodesBegin(), nodeEnd = nodesEnd();
>> + nodeItr != nodeEnd; ++nodeItr, ++curID) {
>> + getNodeEntry(nodeItr).setID(curID);
>> + idToNodeMap[curID] = nodeItr;
>> + }
>> + nodeIDsValid = true;
>> + }
>> +
>> + /// \brief Assigns sequential IDs to the nodes using the
>> ordering of the
>> + /// given vector.
>> + void assignNodeIDs(const std::vector<NodeIterator>
>> &nodeOrdering) {
>> + assert((getNumNodes() == nodeOrdering.size()) && +
>> "Wrong number of nodes in node ordering.");
>> + idToNodeMap = nodeOrdering;
>> + for (unsigned nodeID = 0; nodeID < idToNodeMap.size(); +
>> +nodeID) {
>> + getNodeEntry(idToNodeMap[nodeID]).setID(nodeID);
>> + }
>> + nodeIDsValid = true;
>> + }
>> +
>> + /// \brief Returns true if valid node IDs are assigned, false
>> otherwise.
>> + bool areNodeIDsValid() const { return nodeIDsValid; }
>> +
>> + /// \brief Return the numeric ID of the given node.
>> + ///
>> + /// Calls to this method will result in an assertion failure if
>> there have
>> + /// been any node additions or removals since the last call to
>> + /// assignNodeIDs().
>> + unsigned getNodeID(const ConstNodeIterator &nodeItr) const {
>> + assert(nodeIDsValid && "Attempt to retrieve invalid ID.");
>> + return getNodeEntry(nodeItr).getID();
>> + }
>> +
>> + /// \brief Returns the iterator associated with the given node ID.
>> + NodeIterator getNodeItr(unsigned nodeID) {
>> + assert(nodeIDsValid && "Attempt to retrieve iterator with
>> invalid ID.");
>> + return idToNodeMap[nodeID];
>> + }
>> +
>> + /// \brief Returns the iterator associated with the given node ID.
>> + ConstNodeIterator getNodeItr(unsigned nodeID) const {
>> + assert(nodeIDsValid && "Attempt to retrieve iterator with
>> invalid ID.");
>> + return idToNodeMap[nodeID];
>> + }
>> +
>> + /// \brief Removes the given node (and all attached edges) from
>> the graph.
>> + void removeNode(const NodeIterator &nodeItr) {
>> + assert(iteratorInRange(nodeItr, nodeList.begin(), nodeList.end
>> ()) &&
>> + "Iterator does not belong to this graph!");
>> +
>> + invalidateNodeIDs();
>> + + NodeEntry &nodeEntry = getNodeEntry(nodeItr);
>> +
>> + // We need to copy this out because it will be destroyed as
>> the edges are
>> + // removed.
>> + typedef std::vector<EdgeIterator> AdjEdgeList;
>> + typedef typename AdjEdgeList::iterator AdjEdgeListItr;
>> +
>> + AdjEdgeList adjEdges;
>> + adjEdges.reserve(nodeEntry.getDegree());
>> + std::copy(nodeEntry.adjEdgesBegin(), nodeEntry.adjEdgesEnd(),
>> + std::back_inserter(adjEdges));
>> +
>> + // Iterate over the copied out edges and remove them from the
>> graph.
>> + for (AdjEdgeListItr itr = adjEdges.begin(), end = adjEdges.end
>> ();
>> + itr != end; ++itr) {
>> + removeEdge(*itr);
>> + }
>> +
>> + // Erase the node from the nodelist.
>> + nodeList.erase(nodeItr);
>> + --nodeListSize;
>> + }
>> +
>> + NodeIterator nodesBegin() { return nodeList.begin(); }
>> + ConstNodeIterator nodesBegin() const { return nodeList.begin(); }
>> + NodeIterator nodesEnd() { return nodeList.end(); }
>> + ConstNodeIterator nodesEnd() const { return nodeList.end(); }
>> +
>> + AdjEdgeIterator adjEdgesBegin(const NodeIterator &nodeItr) {
>> + return getNodeEntry(nodeItr).adjEdgesBegin();
>> + }
>> +
>> + ConstAdjEdgeIterator adjEdgesBegin(const ConstNodeIterator
>> &nodeItr) const {
>> + return getNodeEntry(nodeItr).adjEdgesBegin();
>> + }
>> +
>> + AdjEdgeIterator adjEdgesEnd(const NodeIterator &nodeItr) {
>> + return getNodeEntry(nodeItr).adjEdgesEnd();
>> + }
>> + + ConstAdjEdgeIterator adjEdgesEnd(const ConstNodeIterator
>> &nodeItr) const {
>> + getNodeEntry(nodeItr).adjEdgesEnd();
>> + }
>> +
>> + EdgeIterator findEdge(const NodeIterator &node1Itr,
>> + const NodeIterator &node2Itr) {
>> +
>> + for (AdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr),
>> + adjEdgeEnd = adjEdgesEnd(node1Itr);
>> + adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) {
>> + if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) ||
>> + (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) {
>> + return *adjEdgeItr;
>> + }
>> + }
>> +
>> + return edgeList.end();
>> + }
>> +
>> + ConstEdgeIterator findEdge(const ConstNodeIterator &node1Itr,
>> + const ConstNodeIterator &node2Itr)
>> const {
>> +
>> + for (ConstAdjEdgeIterator adjEdgeItr = adjEdgesBegin(node1Itr),
>> + adjEdgeEnd = adjEdgesEnd(node1Itr);
>> + adjEdgeItr != adjEdgesEnd; ++adjEdgeItr) {
>> + if ((getEdgeNode1Itr(*adjEdgeItr) == node2Itr) ||
>> + (getEdgeNode2Itr(*adjEdgeItr) == node2Itr)) {
>> + return *adjEdgeItr;
>> + }
>> + }
>> +
>> + return edgeList.end();
>> + }
>> +
>> + Matrix& getEdgeCosts(const EdgeIterator &edgeItr) {
>> + return getEdgeEntry(edgeItr).getCosts();
>> + }
>> +
>> + const Matrix& getEdgeCosts(const ConstEdgeIterator &edgeItr)
>> const {
>> + return getEdgeEntry(edgeItr).getCosts();
>> + }
>> +
>> + NodeIterator getEdgeNode1Itr(const EdgeIterator &edgeItr) {
>> + return getEdgeEntry(edgeItr).getNode1Itr();
>> + }
>> +
>> + ConstNodeIterator getEdgeNode1Itr(const ConstEdgeIterator
>> &edgeItr) const {
>> + return getEdgeEntry(edgeItr).getNode1Itr();
>> + }
>> +
>> + NodeIterator getEdgeNode2Itr(const EdgeIterator &edgeItr) {
>> + return getEdgeEntry(edgeItr).getNode2Itr();
>> + }
>> +
>> + ConstNodeIterator getEdgeNode2Itr(const ConstEdgeIterator
>> &edgeItr) const {
>> + return getEdgeEntry(edgeItr).getNode2Itr();
>> + }
>> +
>> + NodeIterator getEdgeOtherNode(const EdgeIterator &edgeItr,
>> + const NodeIterator &nodeItr) {
>> +
>> + EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
>> + if (nodeItr == edgeEntry.getNode1Itr()) {
>> + return edgeEntry.getNode2Itr();
>> + }
>> + //else
>> + return edgeEntry.getNode1Itr();
>> + }
>> +
>> + ConstNodeIterator getEdgeOtherNode(const ConstEdgeIterator
>> &edgeItr,
>> + const ConstNodeIterator
>> &nodeItr) const {
>> +
>> + const EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
>> + if (nodeItr == edgeEntry.getNode1Itr()) {
>> + return edgeEntry.getNode2Itr();
>> + }
>> + //else
>> + return edgeEntry.getNode1Itr();
>> + }
>> +
>> + void removeEdge(const EdgeIterator &edgeItr) {
>> + assert(iteratorInRange(edgeItr, edgeList.begin(), edgeList.end
>> ()) &&
>> + "Iterator does not belong to this graph!");
>> +
>> + --edgeListSize;
>> +
>> + // Get the edge entry.
>> + EdgeEntry &edgeEntry = getEdgeEntry(edgeItr);
>> +
>> + // Get the nodes entry.
>> + NodeEntry &node1Entry(getNodeEntry(edgeEntry.getNode1Itr())),
>> + &node2Entry(getNodeEntry(edgeEntry.getNode2Itr()));
>> +
>> + // Disconnect the edge from the nodes.
>> + node1Entry.removeAdjEdge(edgeEntry.getNode1ThisEdgeItr());
>> + node2Entry.removeAdjEdge(edgeEntry.getNode2ThisEdgeItr());
>> +
>> + // Remove the edge from the graph.
>> + edgeList.erase(edgeItr);
>> + }
>> +
>> + EdgeIterator edgesBegin() { return edgeList.begin(); }
>> + ConstEdgeIterator edgesBegin() const { return edgeList.begin(); }
>> + EdgeIterator edgesEnd() { return edgeList.end(); }
>> + ConstEdgeIterator edgesEnd() const { return edgeList.end(); }
>> +
>> + void clear() {
>> + nodeList.clear();
>> + nodeListSize = 0;
>> + edgeList.clear();
>> + edgeListSize = 0;
>> + idToNodeMap.clear();
>> + }
>> +
>> + template <typename OStream>
>> + void printDot(OStream &os) const {
>> + + assert(areNodeIDsValid() &&
>> + "Cannot print a .dot of a graph unless IDs have been
>> assigned.");
>> + + os << "graph {\n";
>> +
>> + for (ConstNodeIterator nodeItr = nodesBegin(), nodeEnd =
>> nodesEnd();
>> + nodeItr != nodeEnd; ++nodeItr) {
>> +
>> + os << " node" << getNodeID(nodeItr) << " [ label=\""
>> + << getNodeID(nodeItr) << ": " << getNodeCosts(nodeItr) <<
>> "\" ]\n";
>> + }
>> +
>> + os << " edge [ len=" << getNumNodes() << " ]\n";
>> +
>> + for (ConstEdgeIterator edgeItr = edgesBegin(), edgeEnd =
>> edgesEnd();
>> + edgeItr != edgeEnd; ++edgeItr) {
>> +
>> + os << " node" << getNodeID(getEdgeNode1Itr(edgeItr))
>> + << " -- node" << getNodeID(getEdgeNode2Itr(edgeItr))
>> + << " [ label=\"";
>> +
>> + const Matrix &edgeCosts = getEdgeCosts(edgeItr);
>> +
>> + for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
>> + os << edgeCosts.getRowAsVector(i) << "\\n";
>> + }
>> +
>> + os << "\" ]\n";
>> + }
>> +
>> + os << "}\n";
>> + }
>> +
>> + template <typename OStream>
>> + void printDot(OStream &os) {
>> + if (!areNodeIDsValid()) {
>> + assignNodeIDs();
>> + }
>> +
>> + const_cast<const ThisGraphT*>(this)->printDot(os);
>> + }
>> +
>> + template <typename OStream>
>> + void dumpTo(OStream &os) const {
>> + typedef ConstNodeIterator ConstNodeID;
>> + + assert(areNodeIDsValid() &&
>> + "Cannot dump a graph unless IDs have been assigned.");
>> +
>> + for (ConstNodeIterator nItr = nodesBegin(), nEnd = nodesEnd();
>> + nItr != nEnd; ++nItr) {
>> + os << getNodeID(nItr) << "\n";
>> + }
>> +
>> + unsigned edgeNumber = 1;
>> + for (ConstEdgeIterator eItr = edgesBegin(), eEnd = edgesEnd();
>> + eItr != eEnd; ++eItr) {
>> +
>> + os << edgeNumber++ << ": { "
>> + << getNodeID(getEdgeNode1Itr(eItr)) << ", "
>> + << getNodeID(getEdgeNode2Itr(eItr)) << " }\n";
>> + }
>> +
>> + }
>> +
>> + template <typename OStream>
>> + void dumpTo(OStream &os) {
>> + if (!areNodeIDsValid()) {
>> + assignNodeIDs();
>> + }
>> +
>> + const_cast<const ThisGraphT*>(this)->dumpTo(os);
>> + }
>> +
>> +};
>> +
>> +/// \brief Provides a base from which to derive nodes for GraphBase.
>> +template <typename NodeImpl, typename EdgeImpl>
>> +class NodeBase {
>> +private:
>> +
>> + typedef GraphBase<NodeImpl, EdgeImpl> GraphBaseT;
>> + typedef NodeBaseTraits<GraphBaseT> ThisNodeBaseTraits;
>> +
>> +public:
>> + typedef typename GraphBaseT::EdgeIterator EdgeIterator;
>> +
>> +private:
>> + typedef typename ThisNodeBaseTraits::AdjEdgeList AdjEdgeList;
>> +
>> + unsigned degree, id;
>> + Vector costs;
>> + AdjEdgeList adjEdges;
>> +
>> + void operator=(const NodeBase& other) {
>> + assert(false && "Can't assign NodeEntrys.");
>> + }
>> +
>> +public:
>> +
>> + typedef typename ThisNodeBaseTraits::AdjEdgeIterator
>> AdjEdgeIterator;
>> + typedef typename ThisNodeBaseTraits::ConstAdjEdgeIterator
>> + ConstAdjEdgeIterator;
>> +
>> + NodeBase(const Vector &costs) : degree(0), costs(costs) {
>> + assert((costs.getLength() > 0) && "Can't have zero-length cost
>> vector.");
>> + }
>> +
>> + Vector& getCosts() { return costs; }
>> + const Vector& getCosts() const { return costs; }
>> +
>> + unsigned getDegree() const { return degree; }
>> +
>> + void setID(unsigned id) { this->id = id; }
>> + unsigned getID() const { return id; }
>> +
>> + AdjEdgeIterator addAdjEdge(const EdgeIterator &edgeItr) {
>> + ++degree;
>> + return adjEdges.insert(adjEdges.end(), edgeItr);
>> + }
>> +
>> + void removeAdjEdge(const AdjEdgeIterator &adjEdgeItr) {
>> + --degree;
>> + adjEdges.erase(adjEdgeItr);
>> + }
>> +
>> + AdjEdgeIterator adjEdgesBegin() { return adjEdges.begin(); } +
>> ConstAdjEdgeIterator adjEdgesBegin() const { return adjEdges.begin
>> (); }
>> + AdjEdgeIterator adjEdgesEnd() { return adjEdges.end(); }
>> + ConstAdjEdgeIterator adjEdgesEnd() const { return adjEdges.end
>> (); }
>> +
>> +};
>> +
>> +template <typename NodeImpl, typename EdgeImpl>
>> +class EdgeBase {
>> +public:
>> + typedef typename GraphBase<NodeImpl, EdgeImpl>::NodeIterator
>> NodeIterator;
>> + typedef typename GraphBase<NodeImpl, EdgeImpl>::EdgeIterator
>> EdgeIterator;
>> +
>> + typedef typename NodeImpl::AdjEdgeIterator NodeAdjEdgeIterator;
>> +
>> +private:
>> +
>> + NodeIterator node1Itr, node2Itr;
>> + NodeAdjEdgeIterator node1ThisEdgeItr, node2ThisEdgeItr;
>> + Matrix costs;
>> +
>> + void operator=(const EdgeBase &other) {
>> + assert(false && "Can't assign EdgeEntrys.");
>> + }
>> +
>> +public:
>> +
>> + EdgeBase(const NodeIterator &node1Itr, const NodeIterator
>> &node2Itr,
>> + const Matrix &costs) :
>> + node1Itr(node1Itr), node2Itr(node2Itr), costs(costs) {
>> +
>> + assert((costs.getRows() > 0) && (costs.getCols() > 0) &&
>> + "Can't have zero-dimensioned cost matrices");
>> + }
>> +
>> + Matrix& getCosts() { return costs; }
>> + const Matrix& getCosts() const { return costs; }
>> +
>> + const NodeIterator& getNode1Itr() const { return node1Itr; }
>> + const NodeIterator& getNode2Itr() const { return node2Itr; }
>> +
>> + void setNode1ThisEdgeItr(const NodeAdjEdgeIterator
>> &node1ThisEdgeItr) {
>> + this->node1ThisEdgeItr = node1ThisEdgeItr;
>> + }
>> +
>> + const NodeAdjEdgeIterator& getNode1ThisEdgeItr() const {
>> + return node1ThisEdgeItr;
>> + }
>> +
>> + void setNode2ThisEdgeItr(const NodeAdjEdgeIterator
>> &node2ThisEdgeItr) {
>> + this->node2ThisEdgeItr = node2ThisEdgeItr;
>> + }
>> +
>> + const NodeAdjEdgeIterator& getNode2ThisEdgeItr() const {
>> + return node2ThisEdgeItr;
>> + }
>> +
>> +};
>> +
>> +
>> +}
>> +
>> +#endif // LLVM_CODEGEN_PBQP_GRAPHBASE_HPP
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/GraphGenerator.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/GraphGenerator.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/GraphGenerator.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/GraphGenerator.h Thu Aug 6
>> 18:32:48 2009
>> @@ -0,0 +1,195 @@
>> +#ifndef LLVM_CODEGEN_PBQP_GRAPHGENERATOR_H
>> +#define LLVM_CODEGEN_PBQP_GRAPHGENERATOR_H
>> +
>> +#include "PBQPMath.h"
>> +
>> +namespace PBQP {
>> +
>> +unsigned randRange(unsigned min, unsigned max) {
>> + return min + (rand() % (max - min + 1));
>> +}
>> +
>> +class BasicNodeCostsGenerator {
>> +private:
>> +
>> + unsigned maxDegree, minCost, maxCost;
>> +
>> +
>> +public:
>> +
>> + BasicNodeCostsGenerator(unsigned maxDegree, unsigned minCost,
>> + unsigned maxCost) :
>> + maxDegree(maxDegree), minCost(minCost), maxCost(maxCost) { }
>> +
>> + Vector operator()() const {
>> + Vector v(randRange(1, maxDegree));
>> + for (unsigned i = 0; i < v.getLength(); ++i) {
>> + v[i] = randRange(minCost, maxCost);
>> + }
>> + return v;
>> + };
>> +
>> +};
>> +
>> +class FixedDegreeSpillCostGenerator {
>> +private:
>> +
>> + unsigned degree, spillCostMin, spillCostMax;
>> +
>> +public:
>> +
>> + FixedDegreeSpillCostGenerator(unsigned degree, unsigned
>> spillCostMin,
>> + unsigned spillCostMax) :
>> + degree(degree), spillCostMin(spillCostMin), spillCostMax
>> (spillCostMax) { }
>> +
>> + Vector operator()() const {
>> + Vector v(degree, 0);
>> + v[0] = randRange(spillCostMin, spillCostMax);
>> + return v;
>> + }
>> +
>> +};
>> +
>> +class BasicEdgeCostsGenerator {
>> +private:
>> +
>> + unsigned minCost, maxCost;
>> +
>> +public:
>> +
>> + BasicEdgeCostsGenerator(unsigned minCost, unsigned maxCost) :
>> + minCost(minCost), maxCost(maxCost) {}
>> +
>> + Matrix operator()(const SimpleGraph &g,
>> + const SimpleGraph::ConstNodeIterator &n1,
>> + const SimpleGraph::ConstNodeIterator &n2)
>> const {
>> +
>> + Matrix m(g.getNodeCosts(n1).getLength(),
>> + g.getNodeCosts(n2).getLength());
>> +
>> + for (unsigned i = 0; i < m.getRows(); ++i) {
>> + for (unsigned j = 0; j < m.getCols(); ++j) {
>> + m[i][j] = randRange(minCost, maxCost);
>> + }
>> + }
>> +
>> + return m;
>> + }
>> +
>> +};
>> +
>> +class InterferenceCostsGenerator {
>> +public:
>> +
>> + Matrix operator()(const SimpleGraph &g,
>> + const SimpleGraph::ConstNodeIterator &n1,
>> + const SimpleGraph::ConstNodeIterator &n2)
>> const {
>> +
>> + unsigned len = g.getNodeCosts(n1).getLength();
>> +
>> + assert(len == g.getNodeCosts(n2).getLength());
>> +
>> + Matrix m(len, len);
>> +
>> + m[0][0] = 0;
>> + for (unsigned i = 1; i < len; ++i) {
>> + m[i][i] = std::numeric_limits<PBQPNum>::infinity();
>> + }
>> +
>> + return m;
>> + }
>> +};
>> +
>> +class RingEdgeGenerator {
>> +public:
>> +
>> + template <typename EdgeCostsGenerator>
>> + void operator()(SimpleGraph &g, EdgeCostsGenerator
>> &edgeCostsGen) {
>> +
>> + assert(g.areNodeIDsValid() && "Graph must have valid node
>> IDs.");
>> +
>> + if (g.getNumNodes() < 2)
>> + return;
>> +
>> + if (g.getNumNodes() == 2) {
>> + SimpleGraph::NodeIterator n1 = g.getNodeItr(0),
>> + n2 = g.getNodeItr(1);
>> + g.addEdge(n1, n2, edgeCostsGen(g, n1, n2));
>> + return;
>> + }
>> +
>> + // Else |V| > 2:
>> + for (unsigned i = 0; i < g.getNumNodes(); ++i) {
>> + SimpleGraph::NodeIterator
>> + n1 = g.getNodeItr(i),
>> + n2 = g.getNodeItr((i + 1) % g.getNumNodes());
>> + g.addEdge(n1, n2, edgeCostsGen(g, n1, n2));
>> + }
>> + }
>> +
>> +};
>> +
>> +class FullyConnectedEdgeGenerator {
>> +public:
>> + + template <typename EdgeCostsGenerator>
>> + void operator()(SimpleGraph &g, EdgeCostsGenerator
>> &edgeCostsGen) {
>> + assert(g.areNodeIDsValid() && "Graph must have valid node
>> IDs.");
>> + + for (unsigned i = 0; i < g.getNumNodes(); ++i) {
>> + for (unsigned j = i + 1; j < g.getNumNodes(); ++j) {
>> + SimpleGraph::NodeIterator
>> + n1 = g.getNodeItr(i),
>> + n2 = g.getNodeItr(j);
>> + g.addEdge(n1, n2, edgeCostsGen(g, n1, n2));
>> + }
>> + }
>> + }
>> +
>> +};
>> +
>> +class RandomEdgeGenerator {
>> +public:
>> +
>> + template <typename EdgeCostsGenerator>
>> + void operator()(SimpleGraph &g, EdgeCostsGenerator
>> &edgeCostsGen) {
>> + + assert(g.areNodeIDsValid() && "Graph must have valid node
>> IDs.");
>> + + for (unsigned i = 0; i < g.getNumNodes(); ++i) {
>> + for (unsigned j = i + 1; j < g.getNumNodes(); ++j) {
>> + if (rand() % 2 == 0) {
>> + SimpleGraph::NodeIterator
>> + n1 = g.getNodeItr(i),
>> + n2 = g.getNodeItr(j);
>> + g.addEdge(n1, n2, edgeCostsGen(g, n1, n2));
>> + }
>> + }
>> + }
>> + }
>> +
>> +};
>> +
>> +template <typename NodeCostsGenerator,
>> + typename EdgesGenerator,
>> + typename EdgeCostsGenerator>
>> +SimpleGraph createRandomGraph(unsigned numNodes,
>> + NodeCostsGenerator nodeCostsGen,
>> + EdgesGenerator edgeGen,
>> + EdgeCostsGenerator edgeCostsGen) {
>> +
>> + SimpleGraph g;
>> + for (unsigned n = 0; n < numNodes; ++n) {
>> + g.addNode(nodeCostsGen());
>> + }
>> +
>> + g.assignNodeIDs();
>> +
>> + edgeGen(g, edgeCostsGen);
>> +
>> + return g;
>> +}
>> +
>> +}
>> +
>> +#endif // LLVM_CODEGEN_PBQP_GRAPHGENERATOR_H
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/HeuristicSolver.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/HeuristicSolver.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/HeuristicSolver.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/HeuristicSolver.h Thu Aug 6
>> 18:32:48 2009
>> @@ -0,0 +1,799 @@
>> +#ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
>> +#define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
>> +
>> +#include "Solver.h"
>> +#include "AnnotatedGraph.h"
>> +
>> +#include <limits>
>> +#include <iostream>
>> +
>> +namespace PBQP {
>> +
>> +/// \brief Important types for the HeuristicSolverImpl.
>> +/// +/// Declared seperately to allow access to heuristic classes
>> before the solver
>> +/// is fully constructed.
>> +template <typename HeuristicNodeData, typename HeuristicEdgeData>
>> +class HSITypes {
>> +public:
>> +
>> + class NodeData;
>> + class EdgeData;
>> +
>> + typedef AnnotatedGraph<NodeData, EdgeData> SolverGraph;
>> + typedef typename SolverGraph::NodeIterator GraphNodeIterator;
>> + typedef typename SolverGraph::EdgeIterator GraphEdgeIterator;
>> + typedef typename SolverGraph::AdjEdgeIterator
>> GraphAdjEdgeIterator;
>> +
>> + typedef std::list<GraphNodeIterator> NodeList;
>> + typedef typename NodeList::iterator NodeListIterator;
>> +
>> + typedef std::vector<GraphNodeIterator> NodeStack;
>> + typedef typename NodeStack::iterator NodeStackIterator;
>> +
>> + class NodeData {
>> + friend class EdgeData;
>> +
>> + private:
>> +
>> + typedef std::list<GraphEdgeIterator> LinksList;
>> +
>> + unsigned numLinks;
>> + LinksList links, solvedLinks;
>> + NodeListIterator bucketItr;
>> + HeuristicNodeData heuristicData;
>> +
>> + public:
>> +
>> + typedef typename LinksList::iterator AdjLinkIterator;
>> +
>> + private:
>> +
>> + AdjLinkIterator addLink(const GraphEdgeIterator &edgeItr) {
>> + ++numLinks;
>> + return links.insert(links.end(), edgeItr);
>> + }
>> +
>> + void delLink(const AdjLinkIterator &adjLinkItr) {
>> + --numLinks;
>> + links.erase(adjLinkItr);
>> + }
>> +
>> + public:
>> +
>> + NodeData() : numLinks(0) {}
>> +
>> + unsigned getLinkDegree() const { return numLinks; }
>> +
>> + HeuristicNodeData& getHeuristicData() { return heuristicData; }
>> + const HeuristicNodeData& getHeuristicData() const {
>> + return heuristicData;
>> + }
>> +
>> + void setBucketItr(const NodeListIterator &bucketItr) {
>> + this->bucketItr = bucketItr;
>> + }
>> +
>> + const NodeListIterator& getBucketItr() const {
>> + return bucketItr;
>> + }
>> +
>> + AdjLinkIterator adjLinksBegin() {
>> + return links.begin();
>> + }
>> +
>> + AdjLinkIterator adjLinksEnd() {
>> + return links.end();
>> + }
>> +
>> + void addSolvedLink(const GraphEdgeIterator &solvedLinkItr) {
>> + solvedLinks.push_back(solvedLinkItr);
>> + }
>> +
>> + AdjLinkIterator solvedLinksBegin() {
>> + return solvedLinks.begin();
>> + }
>> +
>> + AdjLinkIterator solvedLinksEnd() {
>> + return solvedLinks.end();
>> + }
>> +
>> + };
>> +
>> + class EdgeData {
>> + private:
>> +
>> + SolverGraph &g;
>> + GraphNodeIterator node1Itr, node2Itr;
>> + HeuristicEdgeData heuristicData;
>> + typename NodeData::AdjLinkIterator node1ThisEdgeItr,
>> node2ThisEdgeItr;
>> +
>> + public:
>> +
>> + EdgeData(SolverGraph &g) : g(g) {}
>> +
>> + HeuristicEdgeData& getHeuristicData() { return heuristicData; }
>> + const HeuristicEdgeData& getHeuristicData() const {
>> + return heuristicData;
>> + }
>> +
>> + void setup(const GraphEdgeIterator &thisEdgeItr) {
>> + node1Itr = g.getEdgeNode1Itr(thisEdgeItr);
>> + node2Itr = g.getEdgeNode2Itr(thisEdgeItr);
>> +
>> + node1ThisEdgeItr = g.getNodeData(node1Itr).addLink
>> (thisEdgeItr);
>> + node2ThisEdgeItr = g.getNodeData(node2Itr).addLink
>> (thisEdgeItr);
>> + }
>> +
>> + void unlink() {
>> + g.getNodeData(node1Itr).delLink(node1ThisEdgeItr);
>> + g.getNodeData(node2Itr).delLink(node2ThisEdgeItr);
>> + }
>> +
>> + };
>> +
>> +};
>> +
>> +template <typename Heuristic>
>> +class HeuristicSolverImpl {
>> +public:
>> + // Typedefs to make life easier:
>> + typedef HSITypes<typename Heuristic::NodeData,
>> + typename Heuristic::EdgeData> HSIT;
>> + typedef typename HSIT::SolverGraph SolverGraph;
>> + typedef typename HSIT::NodeData NodeData;
>> + typedef typename HSIT::EdgeData EdgeData;
>> + typedef typename HSIT::GraphNodeIterator GraphNodeIterator;
>> + typedef typename HSIT::GraphEdgeIterator GraphEdgeIterator;
>> + typedef typename HSIT::GraphAdjEdgeIterator GraphAdjEdgeIterator;
>> +
>> + typedef typename HSIT::NodeList NodeList;
>> + typedef typename HSIT::NodeListIterator NodeListIterator;
>> +
>> + typedef std::vector<GraphNodeIterator> NodeStack;
>> + typedef typename NodeStack::iterator NodeStackIterator;
>> +
>> + /*!
>> + * \brief Constructor, which performs all the actual solver work.
>> + */
>> + HeuristicSolverImpl(const SimpleGraph &orig) :
>> + solution(orig.getNumNodes(), true)
>> + {
>> + copyGraph(orig);
>> + simplify();
>> + setup();
>> + computeSolution();
>> + computeSolutionCost(orig);
>> + }
>> +
>> + /*!
>> + * \brief Returns the graph for this solver.
>> + */
>> + SolverGraph& getGraph() { return g; }
>> +
>> + /*!
>> + * \brief Return the solution found by this solver.
>> + */
>> + const Solution& getSolution() const { return solution; }
>> +
>> +private:
>> +
>> + /*!
>> + * \brief Add the given node to the appropriate bucket for its
>> link
>> + * degree.
>> + */
>> + void addToBucket(const GraphNodeIterator &nodeItr) {
>> + NodeData &nodeData = g.getNodeData(nodeItr);
>> +
>> + switch (nodeData.getLinkDegree()) {
>> + case 0: nodeData.setBucketItr(
>> + r0Bucket.insert(r0Bucket.end(), nodeItr));
>> + break;
>> + case 1: nodeData.setBucketItr(
>> + r1Bucket.insert(r1Bucket.end(), nodeItr));
>> + break;
>> + case 2: nodeData.setBucketItr(
>> + r2Bucket.insert(r2Bucket.end(), nodeItr));
>> + break;
>> + default: heuristic.addToRNBucket(nodeItr);
>> + break;
>> + }
>> + }
>> +
>> + /*!
>> + * \brief Remove the given node from the appropriate bucket for
>> its link
>> + * degree.
>> + */
>> + void removeFromBucket(const GraphNodeIterator &nodeItr) {
>> + NodeData &nodeData = g.getNodeData(nodeItr);
>> +
>> + switch (nodeData.getLinkDegree()) {
>> + case 0: r0Bucket.erase(nodeData.getBucketItr()); break;
>> + case 1: r1Bucket.erase(nodeData.getBucketItr()); break;
>> + case 2: r2Bucket.erase(nodeData.getBucketItr()); break;
>> + default: heuristic.removeFromRNBucket(nodeItr); break;
>> + }
>> + }
>> +
>> +public:
>> +
>> + /*!
>> + * \brief Add a link.
>> + */
>> + void addLink(const GraphEdgeIterator &edgeItr) {
>> + g.getEdgeData(edgeItr).setup(edgeItr);
>> +
>> + if ((g.getNodeData(g.getEdgeNode1Itr(edgeItr)).getLinkDegree()
>> > 2) ||
>> + (g.getNodeData(g.getEdgeNode2Itr(edgeItr)).getLinkDegree()
>> > 2)) {
>> + heuristic.handleAddLink(edgeItr);
>> + }
>> + }
>> +
>> + /*!
>> + * \brief Remove link, update info for node.
>> + *
>> + * Only updates information for the given node, since usually
>> the other
>> + * is about to be removed.
>> + */
>> + void removeLink(const GraphEdgeIterator &edgeItr,
>> + const GraphNodeIterator &nodeItr) {
>> +
>> + if (g.getNodeData(nodeItr).getLinkDegree() > 2) {
>> + heuristic.handleRemoveLink(edgeItr, nodeItr);
>> + }
>> + g.getEdgeData(edgeItr).unlink();
>> + }
>> +
>> + /*!
>> + * \brief Remove link, update info for both nodes. Useful for R2
>> only.
>> + */
>> + void removeLinkR2(const GraphEdgeIterator &edgeItr) {
>> + GraphNodeIterator node1Itr = g.getEdgeNode1Itr(edgeItr);
>> +
>> + if (g.getNodeData(node1Itr).getLinkDegree() > 2) {
>> + heuristic.handleRemoveLink(edgeItr, node1Itr);
>> + }
>> + removeLink(edgeItr, g.getEdgeNode2Itr(edgeItr));
>> + }
>> +
>> + /*!
>> + * \brief Removes all links connected to the given node.
>> + */
>> + void unlinkNode(const GraphNodeIterator &nodeItr) {
>> + NodeData &nodeData = g.getNodeData(nodeItr);
>> +
>> + typedef std::vector<GraphEdgeIterator> TempEdgeList;
>> +
>> + TempEdgeList edgesToUnlink;
>> + edgesToUnlink.reserve(nodeData.getLinkDegree());
>> +
>> + // Copy adj edges into a temp vector. We want to destroy them
>> during
>> + // the unlink, and we can't do that while we're iterating over
>> them.
>> + std::copy(nodeData.adjLinksBegin(), nodeData.adjLinksEnd(),
>> + std::back_inserter(edgesToUnlink));
>> +
>> + for (typename TempEdgeList::iterator
>> + edgeItr = edgesToUnlink.begin(), edgeEnd =
>> edgesToUnlink.end();
>> + edgeItr != edgeEnd; ++edgeItr) {
>> +
>> + GraphNodeIterator otherNode = g.getEdgeOtherNode(*edgeItr,
>> nodeItr);
>> +
>> + removeFromBucket(otherNode);
>> + removeLink(*edgeItr, otherNode);
>> + addToBucket(otherNode);
>> + }
>> + }
>> +
>> + /*!
>> + * \brief Push the given node onto the stack to be solved with
>> + * backpropagation.
>> + */
>> + void pushStack(const GraphNodeIterator &nodeItr) {
>> + stack.push_back(nodeItr);
>> + }
>> +
>> + /*!
>> + * \brief Set the solution of the given node.
>> + */
>> + void setSolution(const GraphNodeIterator &nodeItr, unsigned
>> solIndex) {
>> + solution.setSelection(g.getNodeID(nodeItr), solIndex);
>> +
>> + for (GraphAdjEdgeIterator adjEdgeItr = g.adjEdgesBegin(nodeItr),
>> + adjEdgeEnd = g.adjEdgesEnd(nodeItr);
>> + adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) {
>> + GraphEdgeIterator edgeItr(*adjEdgeItr);
>> + GraphNodeIterator adjNodeItr(g.getEdgeOtherNode(edgeItr,
>> nodeItr));
>> + g.getNodeData(adjNodeItr).addSolvedLink(edgeItr);
>> + }
>> + }
>> +
>> +private:
>> +
>> + SolverGraph g;
>> + Heuristic heuristic;
>> + Solution solution;
>> +
>> + NodeList r0Bucket,
>> + r1Bucket,
>> + r2Bucket;
>> +
>> + NodeStack stack;
>> +
>> + // Copy the SimpleGraph into an annotated graph which we can use
>> for reduction.
>> + void copyGraph(const SimpleGraph &orig) {
>> +
>> + assert((g.getNumEdges() == 0) && (g.getNumNodes() == 0) &&
>> + "Graph should be empty prior to solver setup.");
>> +
>> + assert(orig.areNodeIDsValid() &&
>> + "Cannot copy from a graph with invalid node IDs.");
>> +
>> + std::vector<GraphNodeIterator> newNodeItrs;
>> +
>> + for (unsigned nodeID = 0; nodeID < orig.getNumNodes(); +
>> +nodeID) {
>> + newNodeItrs.push_back(
>> + g.addNode(orig.getNodeCosts(orig.getNodeItr(nodeID)),
>> NodeData()));
>> + }
>> +
>> + for (SimpleGraph::ConstEdgeIterator
>> + origEdgeItr = orig.edgesBegin(), origEdgeEnd =
>> orig.edgesEnd();
>> + origEdgeItr != origEdgeEnd; ++origEdgeItr) {
>> +
>> + unsigned id1 = orig.getNodeID(orig.getEdgeNode1Itr
>> (origEdgeItr)),
>> + id2 = orig.getNodeID(orig.getEdgeNode2Itr
>> (origEdgeItr));
>> +
>> + g.addEdge(newNodeItrs[id1], newNodeItrs[id2],
>> + orig.getEdgeCosts(origEdgeItr), EdgeData(g));
>> + }
>> +
>> + // Assign IDs to the new nodes using the ordering from the old
>> graph,
>> + // this will lead to nodes in the new graph getting the same
>> ID as the
>> + // corresponding node in the old graph.
>> + g.assignNodeIDs(newNodeItrs);
>> + }
>> +
>> + // Simplify the annotated graph by eliminating independent edges
>> and trivial
>> + // nodes. + void simplify() {
>> + disconnectTrivialNodes();
>> + eliminateIndependentEdges();
>> + }
>> +
>> + // Eliminate trivial nodes.
>> + void disconnectTrivialNodes() {
>> + for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd =
>> g.nodesEnd();
>> + nodeItr != nodeEnd; ++nodeItr) {
>> +
>> + if (g.getNodeCosts(nodeItr).getLength() == 1) {
>> +
>> + std::vector<GraphEdgeIterator> edgesToRemove;
>> +
>> + for (GraphAdjEdgeIterator adjEdgeItr = g.adjEdgesBegin
>> (nodeItr),
>> + adjEdgeEnd = g.adjEdgesEnd(nodeItr);
>> + adjEdgeItr != adjEdgeEnd; ++adjEdgeItr) {
>> +
>> + GraphEdgeIterator edgeItr = *adjEdgeItr;
>> +
>> + if (g.getEdgeNode1Itr(edgeItr) == nodeItr) {
>> + GraphNodeIterator otherNodeItr = g.getEdgeNode2Itr
>> (edgeItr);
>> + g.getNodeCosts(otherNodeItr) +=
>> + g.getEdgeCosts(edgeItr).getRowAsVector(0);
>> + }
>> + else {
>> + GraphNodeIterator otherNodeItr = g.getEdgeNode1Itr
>> (edgeItr);
>> + g.getNodeCosts(otherNodeItr) +=
>> + g.getEdgeCosts(edgeItr).getColAsVector(0);
>> + }
>> +
>> + edgesToRemove.push_back(edgeItr);
>> + }
>> +
>> + while (!edgesToRemove.empty()) {
>> + g.removeEdge(edgesToRemove.back());
>> + edgesToRemove.pop_back();
>> + }
>> + }
>> + }
>> + }
>> +
>> + void eliminateIndependentEdges() {
>> + std::vector<GraphEdgeIterator> edgesToProcess;
>> +
>> + for (GraphEdgeIterator edgeItr = g.edgesBegin(), edgeEnd =
>> g.edgesEnd();
>> + edgeItr != edgeEnd; ++edgeItr) {
>> + edgesToProcess.push_back(edgeItr);
>> + }
>> +
>> + while (!edgesToProcess.empty()) {
>> + tryToEliminateEdge(edgesToProcess.back());
>> + edgesToProcess.pop_back();
>> + }
>> + }
>> +
>> + void tryToEliminateEdge(const GraphEdgeIterator &edgeItr) {
>> + if (tryNormaliseEdgeMatrix(edgeItr)) {
>> + g.removeEdge(edgeItr); + }
>> + }
>> +
>> + bool tryNormaliseEdgeMatrix(const GraphEdgeIterator &edgeItr) {
>> +
>> + Matrix &edgeCosts = g.getEdgeCosts(edgeItr);
>> + Vector &uCosts = g.getNodeCosts(g.getEdgeNode1Itr(edgeItr)),
>> + &vCosts = g.getNodeCosts(g.getEdgeNode2Itr(edgeItr));
>> +
>> + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) {
>> + PBQPNum rowMin = edgeCosts.getRowMin(r);
>> + uCosts[r] += rowMin;
>> + if (rowMin != std::numeric_limits<PBQPNum>::infinity()) {
>> + edgeCosts.subFromRow(r, rowMin);
>> + }
>> + else {
>> + edgeCosts.setRow(r, 0);
>> + }
>> + }
>> +
>> + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) {
>> + PBQPNum colMin = edgeCosts.getColMin(c);
>> + vCosts[c] += colMin;
>> + if (colMin != std::numeric_limits<PBQPNum>::infinity()) {
>> + edgeCosts.subFromCol(c, colMin);
>> + }
>> + else {
>> + edgeCosts.setCol(c, 0);
>> + }
>> + }
>> +
>> + return edgeCosts.isZero();
>> + }
>> +
>> + void setup() {
>> + setupLinks();
>> + heuristic.initialise(*this);
>> + setupBuckets();
>> + }
>> +
>> + void setupLinks() {
>> + for (GraphEdgeIterator edgeItr = g.edgesBegin(), edgeEnd =
>> g.edgesEnd();
>> + edgeItr != edgeEnd; ++edgeItr) {
>> + g.getEdgeData(edgeItr).setup(edgeItr);
>> + }
>> + }
>> +
>> + void setupBuckets() {
>> + for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd =
>> g.nodesEnd();
>> + nodeItr != nodeEnd; ++nodeItr) {
>> + addToBucket(nodeItr);
>> + }
>> + }
>> +
>> + void computeSolution() {
>> + assert(g.areNodeIDsValid() &&
>> + "Nodes cannot be added/removed during reduction.");
>> +
>> + reduce();
>> + computeTrivialSolutions();
>> + backpropagate();
>> + }
>> +
>> + void printNode(const GraphNodeIterator &nodeItr) {
>> +
>> + std::cerr << "Node " << g.getNodeID(nodeItr) << " (" <<
>> &*nodeItr << "):\n"
>> + << " costs = " << g.getNodeCosts(nodeItr) << "\n"
>> + << " link degree = " << g.getNodeData
>> (nodeItr).getLinkDegree() << "\n"
>> + << " links = [ ";
>> +
>> + for (typename HSIT::NodeData::AdjLinkIterator + aeItr
>> = g.getNodeData(nodeItr).adjLinksBegin(),
>> + aeEnd = g.getNodeData(nodeItr).adjLinksEnd();
>> + aeItr != aeEnd; ++aeItr) {
>> + std::cerr << "(" << g.getNodeID(g.getEdgeNode1Itr(*aeItr))
>> + << ", " << g.getNodeID(g.getEdgeNode2Itr(*aeItr))
>> + << ") ";
>> + }
>> + std::cout << "]\n";
>> + }
>> +
>> + void dumpState() {
>> +
>> + std::cerr << "\n";
>> +
>> + for (GraphNodeIterator nodeItr = g.nodesBegin(), nodeEnd =
>> g.nodesEnd();
>> + nodeItr != nodeEnd; ++nodeItr) {
>> + printNode(nodeItr);
>> + }
>> +
>> + NodeList* buckets[] = { &r0Bucket, &r1Bucket, &r2Bucket };
>> +
>> + for (unsigned b = 0; b < 3; ++b) {
>> + NodeList &bucket = *buckets[b];
>> +
>> + std::cerr << "Bucket " << b << ": [ ";
>> +
>> + for (NodeListIterator nItr = bucket.begin(), nEnd =
>> bucket.end();
>> + nItr != nEnd; ++nItr) {
>> + std::cerr << g.getNodeID(*nItr) << " ";
>> + }
>> +
>> + std::cerr << "]\n";
>> + }
>> +
>> + std::cerr << "Stack: [ ";
>> + for (NodeStackIterator nsItr = stack.begin(), nsEnd = stack.end
>> ();
>> + nsItr != nsEnd; ++nsItr) {
>> + std::cerr << g.getNodeID(*nsItr) << " ";
>> + }
>> + std::cerr << "]\n";
>> + }
>> +
>> + void reduce() {
>> + bool reductionFinished = r1Bucket.empty() && r2Bucket.empty() &&
>> + heuristic.rNBucketEmpty();
>> +
>> + while (!reductionFinished) {
>> +
>> + if (!r1Bucket.empty()) {
>> + processR1();
>> + }
>> + else if (!r2Bucket.empty()) {
>> + processR2();
>> + }
>> + else if (!heuristic.rNBucketEmpty()) {
>> + solution.setProvedOptimal(false);
>> + solution.incRNReductions();
>> + heuristic.processRN();
>> + } + else reductionFinished = true;
>> + }
>> + + };
>> +
>> + void processR1() {
>> +
>> + // Remove the first node in the R0 bucket:
>> + GraphNodeIterator xNodeItr = r1Bucket.front();
>> + r1Bucket.pop_front();
>> +
>> + solution.incR1Reductions();
>> +
>> + //std::cerr << "Applying R1 to " << g.getNodeID(xNodeItr) <<
>> "\n";
>> +
>> + assert((g.getNodeData(xNodeItr).getLinkDegree() == 1) &&
>> + "Node in R1 bucket has degree != 1");
>> +
>> + GraphEdgeIterator edgeItr = *g.getNodeData
>> (xNodeItr).adjLinksBegin();
>> +
>> + const Matrix &edgeCosts = g.getEdgeCosts(edgeItr);
>> +
>> + const Vector &xCosts = g.getNodeCosts(xNodeItr);
>> + unsigned xLen = xCosts.getLength();
>> +
>> + // Duplicate a little code to avoid transposing matrices:
>> + if (xNodeItr == g.getEdgeNode1Itr(edgeItr)) {
>> + GraphNodeIterator yNodeItr = g.getEdgeNode2Itr(edgeItr);
>> + Vector &yCosts = g.getNodeCosts(yNodeItr);
>> + unsigned yLen = yCosts.getLength();
>> +
>> + for (unsigned j = 0; j < yLen; ++j) {
>> + PBQPNum min = edgeCosts[0][j] + xCosts[0];
>> + for (unsigned i = 1; i < xLen; ++i) {
>> + PBQPNum c = edgeCosts[i][j] + xCosts[i];
>> + if (c < min)
>> + min = c;
>> + }
>> + yCosts[j] += min;
>> + }
>> + }
>> + else {
>> + GraphNodeIterator yNodeItr = g.getEdgeNode1Itr(edgeItr);
>> + Vector &yCosts = g.getNodeCosts(yNodeItr);
>> + unsigned yLen = yCosts.getLength();
>> +
>> + for (unsigned i = 0; i < yLen; ++i) {
>> + PBQPNum min = edgeCosts[i][0] + xCosts[0];
>> +
>> + for (unsigned j = 1; j < xLen; ++j) {
>> + PBQPNum c = edgeCosts[i][j] + xCosts[j];
>> + if (c < min)
>> + min = c;
>> + }
>> + yCosts[i] += min;
>> + }
>> + }
>> +
>> + unlinkNode(xNodeItr);
>> + pushStack(xNodeItr);
>> + }
>> +
>> + void processR2() {
>> +
>> + GraphNodeIterator xNodeItr = r2Bucket.front();
>> + r2Bucket.pop_front();
>> +
>> + solution.incR2Reductions();
>> +
>> + // Unlink is unsafe here. At some point it may optimistically
>> more a node
>> + // to a lower-degree list when its degree will later rise, or
>> vice versa,
>> + // violating the assumption that node degrees monotonically
>> decrease
>> + // during the reduction phase. Instead we'll bucket shuffle
>> manually.
>> + pushStack(xNodeItr);
>> +
>> + assert((g.getNodeData(xNodeItr).getLinkDegree() == 2) &&
>> + "Node in R2 bucket has degree != 2");
>> +
>> + const Vector &xCosts = g.getNodeCosts(xNodeItr);
>> +
>> + typename NodeData::AdjLinkIterator tempItr =
>> + g.getNodeData(xNodeItr).adjLinksBegin();
>> +
>> + GraphEdgeIterator yxEdgeItr = *tempItr,
>> + zxEdgeItr = *(++tempItr);
>> +
>> + GraphNodeIterator yNodeItr = g.getEdgeOtherNode(yxEdgeItr,
>> xNodeItr),
>> + zNodeItr = g.getEdgeOtherNode(zxEdgeItr,
>> xNodeItr);
>> +
>> + removeFromBucket(yNodeItr);
>> + removeFromBucket(zNodeItr);
>> +
>> + removeLink(yxEdgeItr, yNodeItr);
>> + removeLink(zxEdgeItr, zNodeItr);
>> +
>> + // Graph some of the costs:
>> + bool flipEdge1 = (g.getEdgeNode1Itr(yxEdgeItr) == xNodeItr),
>> + flipEdge2 = (g.getEdgeNode1Itr(zxEdgeItr) == xNodeItr);
>> +
>> + const Matrix *yxCosts = flipEdge1 ?
>> + new Matrix(g.getEdgeCosts(yxEdgeItr).transpose()) :
>> + &g.getEdgeCosts(yxEdgeItr),
>> + *zxCosts = flipEdge2 ?
>> + new Matrix(g.getEdgeCosts(zxEdgeItr).transpose()) :
>> + &g.getEdgeCosts(zxEdgeItr);
>> +
>> + unsigned xLen = xCosts.getLength(),
>> + yLen = yxCosts->getRows(),
>> + zLen = zxCosts->getRows();
>> +
>> + // Compute delta:
>> + Matrix delta(yLen, zLen);
>> +
>> + for (unsigned i = 0; i < yLen; ++i) {
>> + for (unsigned j = 0; j < zLen; ++j) {
>> + PBQPNum min = (*yxCosts)[i][0] + (*zxCosts)[j][0] + xCosts
>> [0];
>> + for (unsigned k = 1; k < xLen; ++k) {
>> + PBQPNum c = (*yxCosts)[i][k] + (*zxCosts)[j][k] + xCosts
>> [k];
>> + if (c < min) {
>> + min = c;
>> + }
>> + }
>> + delta[i][j] = min;
>> + }
>> + }
>> +
>> + if (flipEdge1)
>> + delete yxCosts;
>> +
>> + if (flipEdge2)
>> + delete zxCosts;
>> +
>> + // Deal with the potentially induced yz edge.
>> + GraphEdgeIterator yzEdgeItr = g.findEdge(yNodeItr, zNodeItr);
>> + if (yzEdgeItr == g.edgesEnd()) {
>> + yzEdgeItr = g.addEdge(yNodeItr, zNodeItr, delta, EdgeData(g));
>> + }
>> + else {
>> + // There was an edge, but we're going to screw with it.
>> Delete the old
>> + // link, update the costs. We'll re-link it later.
>> + removeLinkR2(yzEdgeItr);
>> + g.getEdgeCosts(yzEdgeItr) +=
>> + (yNodeItr == g.getEdgeNode1Itr(yzEdgeItr)) ?
>> + delta : delta.transpose();
>> + }
>> +
>> + bool nullCostEdge = tryNormaliseEdgeMatrix(yzEdgeItr);
>> +
>> + // Nulled the edge, remove it entirely.
>> + if (nullCostEdge) {
>> + g.removeEdge(yzEdgeItr);
>> + }
>> + else {
>> + // Edge remains - re-link it.
>> + addLink(yzEdgeItr);
>> + }
>> +
>> + addToBucket(yNodeItr);
>> + addToBucket(zNodeItr);
>> + }
>> +
>> + void computeTrivialSolutions() {
>> +
>> + for (NodeListIterator r0Itr = r0Bucket.begin(), r0End =
>> r0Bucket.end();
>> + r0Itr != r0End; ++r0Itr) {
>> + GraphNodeIterator nodeItr = *r0Itr;
>> +
>> + solution.incR0Reductions();
>> + setSolution(nodeItr, g.getNodeCosts(nodeItr).minIndex());
>> + }
>> +
>> + }
>> +
>> + void backpropagate() {
>> + while (!stack.empty()) {
>> + computeSolution(stack.back());
>> + stack.pop_back();
>> + }
>> + }
>> +
>> + void computeSolution(const GraphNodeIterator &nodeItr) {
>> +
>> + NodeData &nodeData = g.getNodeData(nodeItr);
>> +
>> + Vector v(g.getNodeCosts(nodeItr));
>> +
>> + // Solve based on existing links.
>> + for (typename NodeData::AdjLinkIterator
>> + solvedLinkItr = nodeData.solvedLinksBegin(),
>> + solvedLinkEnd = nodeData.solvedLinksEnd();
>> + solvedLinkItr != solvedLinkEnd; ++solvedLinkItr) {
>> +
>> + GraphEdgeIterator solvedEdgeItr(*solvedLinkItr);
>> + Matrix &edgeCosts = g.getEdgeCosts(solvedEdgeItr);
>> +
>> + if (nodeItr == g.getEdgeNode1Itr(solvedEdgeItr)) {
>> + GraphNodeIterator adjNode(g.getEdgeNode2Itr(solvedEdgeItr));
>> + unsigned adjSolution =
>> + solution.getSelection(g.getNodeID(adjNode));
>> + v += edgeCosts.getColAsVector(adjSolution);
>> + }
>> + else {
>> + GraphNodeIterator adjNode(g.getEdgeNode1Itr(solvedEdgeItr));
>> + unsigned adjSolution =
>> + solution.getSelection(g.getNodeID(adjNode));
>> + v += edgeCosts.getRowAsVector(adjSolution);
>> + }
>> +
>> + }
>> +
>> + setSolution(nodeItr, v.minIndex());
>> + }
>> +
>> + void computeSolutionCost(const SimpleGraph &orig) {
>> + PBQPNum cost = 0.0;
>> +
>> + for (SimpleGraph::ConstNodeIterator
>> + nodeItr = orig.nodesBegin(), nodeEnd = orig.nodesEnd();
>> + nodeItr != nodeEnd; ++nodeItr) {
>> +
>> + unsigned nodeId = orig.getNodeID(nodeItr);
>> +
>> + cost += orig.getNodeCosts(nodeItr)[solution.getSelection
>> (nodeId)];
>> + }
>> +
>> + for (SimpleGraph::ConstEdgeIterator
>> + edgeItr = orig.edgesBegin(), edgeEnd = orig.edgesEnd();
>> + edgeItr != edgeEnd; ++edgeItr) {
>> +
>> + SimpleGraph::ConstNodeIterator n1 = orig.getEdgeNode1Itr
>> (edgeItr),
>> + n2 = orig.getEdgeNode2Itr
>> (edgeItr);
>> + unsigned sol1 = solution.getSelection(orig.getNodeID(n1)),
>> + sol2 = solution.getSelection(orig.getNodeID(n2));
>> +
>> + cost += orig.getEdgeCosts(edgeItr)[sol1][sol2];
>> + }
>> +
>> + solution.setSolutionCost(cost);
>> + }
>> +
>> +};
>> +
>> +template <typename Heuristic>
>> +class HeuristicSolver : public Solver {
>> +public:
>> + Solution solve(const SimpleGraph &g) const {
>> + HeuristicSolverImpl<Heuristic> solverImpl(g);
>> + return solverImpl.getSolution();
>> + }
>> +};
>> +
>> +}
>> +
>> +#endif // LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/Heuristics/Briggs.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/Heuristics/Briggs.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/Heuristics/Briggs.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/Heuristics/Briggs.h Thu Aug 6
>> 18:32:48 2009
>> @@ -0,0 +1,385 @@
>> +#ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
>> +#define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
>> +
>> +#include "../HeuristicSolver.h"
>> +
>> +#include <set>
>> +
>> +namespace PBQP {
>> +namespace Heuristics {
>> +
>> +class Briggs {
>> + public:
>> +
>> + class NodeData;
>> + class EdgeData;
>> +
>> + private:
>> +
>> + typedef HeuristicSolverImpl<Briggs> Solver;
>> + typedef HSITypes<NodeData, EdgeData> HSIT;
>> + typedef HSIT::SolverGraph SolverGraph;
>> + typedef HSIT::GraphNodeIterator GraphNodeIterator;
>> + typedef HSIT::GraphEdgeIterator GraphEdgeIterator;
>> +
>> + class LinkDegreeComparator {
>> + public:
>> + LinkDegreeComparator() : g(0) {}
>> + LinkDegreeComparator(SolverGraph *g) : g(g) {}
>> +
>> + bool operator()(const GraphNodeIterator &node1Itr,
>> + const GraphNodeIterator &node2Itr) const {
>> + assert((g != 0) && "Graph object not set, cannot access
>> node data.");
>> + unsigned n1Degree = g->getNodeData
>> (node1Itr).getLinkDegree(),
>> + n2Degree = g->getNodeData
>> (node2Itr).getLinkDegree();
>> + if (n1Degree > n2Degree) {
>> + return true;
>> + }
>> + else if (n1Degree < n2Degree) {
>> + return false;
>> + }
>> + // else they're "equal" by degree, differentiate based
>> on ID.
>> + return g->getNodeID(node1Itr) < g->getNodeID(node2Itr);
>> + }
>> +
>> + private:
>> + SolverGraph *g;
>> + };
>> +
>> + class SpillPriorityComparator {
>> + public:
>> + SpillPriorityComparator() : g(0) {}
>> + SpillPriorityComparator(SolverGraph *g) : g(g) {}
>> +
>> + bool operator()(const GraphNodeIterator &node1Itr,
>> + const GraphNodeIterator &node2Itr) const {
>> + assert((g != 0) && "Graph object not set, cannot access
>> node data.");
>> + PBQPNum cost1 =
>> + g->getNodeCosts(node1Itr)[0] /
>> + g->getNodeData(node1Itr).getLinkDegree(),
>> + cost2 =
>> + g->getNodeCosts(node2Itr)[0] /
>> + g->getNodeData(node2Itr).getLinkDegree();
>> +
>> + if (cost1 < cost2) {
>> + return true;
>> + }
>> + else if (cost1 > cost2) {
>> + return false;
>> + }
>> + // else they'er "equal" again, differentiate based on
>> address again.
>> + return g->getNodeID(node1Itr) < g->getNodeID(node2Itr);
>> + }
>> +
>> + private:
>> + SolverGraph *g;
>> + };
>> +
>> + typedef std::set<GraphNodeIterator, LinkDegreeComparator>
>> + RNAllocableNodeList;
>> + typedef RNAllocableNodeList::iterator
>> RNAllocableNodeListIterator;
>> +
>> + typedef std::set<GraphNodeIterator, SpillPriorityComparator>
>> + RNUnallocableNodeList;
>> + typedef RNUnallocableNodeList::iterator
>> RNUnallocableNodeListIterator;
>> +
>> + public:
>> +
>> + class NodeData {
>> + private:
>> + RNAllocableNodeListIterator rNAllocableNodeListItr;
>> + RNUnallocableNodeListIterator rNUnallocableNodeListItr;
>> + unsigned numRegOptions, numDenied, numSafe;
>> + std::vector<unsigned> unsafeDegrees;
>> + bool allocable;
>> +
>> + void addRemoveLink(SolverGraph &g, const GraphNodeIterator
>> &nodeItr,
>> + const GraphEdgeIterator &edgeItr, bool add) {
>> +
>> + //assume we're adding...
>> + unsigned udTarget = 0, dir = 1;
>> +
>> + if (!add) {
>> + udTarget = 1;
>> + dir = -1;
>> + }
>> +
>> + EdgeData &linkEdgeData = g.getEdgeData
>> (edgeItr).getHeuristicData();
>> +
>> + EdgeData::ConstUnsafeIterator edgeUnsafeBegin,
>> edgeUnsafeEnd;
>> +
>> + if (nodeItr == g.getEdgeNode1Itr(edgeItr)) {
>> + numDenied += (dir * linkEdgeData.getWorstDegree());
>> + edgeUnsafeBegin = linkEdgeData.unsafeBegin();
>> + edgeUnsafeEnd = linkEdgeData.unsafeEnd();
>> + }
>> + else {
>> + numDenied += (dir * linkEdgeData.getReverseWorstDegree
>> ());
>> + edgeUnsafeBegin = linkEdgeData.reverseUnsafeBegin();
>> + edgeUnsafeEnd = linkEdgeData.reverseUnsafeEnd();
>> + }
>> +
>> + assert((unsafeDegrees.size() ==
>> + static_cast<unsigned>(
>> + std::distance(edgeUnsafeBegin, edgeUnsafeEnd)))
>> + && "Unsafe array size mismatch.");
>> +
>> + std::vector<unsigned>::iterator unsafeDegreesItr =
>> + unsafeDegrees.begin();
>> +
>> + for (EdgeData::ConstUnsafeIterator edgeUnsafeItr =
>> edgeUnsafeBegin;
>> + edgeUnsafeItr != edgeUnsafeEnd;
>> + ++edgeUnsafeItr, ++unsafeDegreesItr) {
>> +
>> + if ((*edgeUnsafeItr == 1) && (*unsafeDegreesItr ==
>> udTarget)) {
>> + numSafe -= dir;
>> + }
>> + *unsafeDegreesItr += (dir * (*edgeUnsafeItr));
>> + }
>> +
>> + allocable = (numDenied < numRegOptions) || (numSafe > 0);
>> + }
>> +
>> + public:
>> +
>> + void setup(SolverGraph &g, const GraphNodeIterator
>> &nodeItr) {
>> +
>> + numRegOptions = g.getNodeCosts(nodeItr).getLength() - 1;
>> +
>> + numSafe = numRegOptions; // Optimistic, correct below.
>> + numDenied = 0; // Also optimistic.
>> + unsafeDegrees.resize(numRegOptions, 0);
>> +
>> + HSIT::NodeData &nodeData = g.getNodeData(nodeItr);
>> +
>> + for (HSIT::NodeData::AdjLinkIterator
>> + adjLinkItr = nodeData.adjLinksBegin(),
>> + adjLinkEnd = nodeData.adjLinksEnd();
>> + adjLinkItr != adjLinkEnd; ++adjLinkItr) {
>> +
>> + addRemoveLink(g, nodeItr, *adjLinkItr, true);
>> + }
>> + }
>> +
>> + bool isAllocable() const { return allocable; }
>> +
>> + void handleAddLink(SolverGraph &g, const GraphNodeIterator
>> &nodeItr,
>> + const GraphEdgeIterator &adjEdge) {
>> + addRemoveLink(g, nodeItr, adjEdge, true);
>> + }
>> +
>> + void handleRemoveLink(SolverGraph &g, const
>> GraphNodeIterator &nodeItr,
>> + const GraphEdgeIterator &adjEdge) {
>> + addRemoveLink(g, nodeItr, adjEdge, false);
>> + }
>> +
>> + void setRNAllocableNodeListItr(
>> + const RNAllocableNodeListIterator
>> &rNAllocableNodeListItr) {
>> +
>> + this->rNAllocableNodeListItr = rNAllocableNodeListItr;
>> + }
>> +
>> + RNAllocableNodeListIterator getRNAllocableNodeListItr()
>> const {
>> + return rNAllocableNodeListItr;
>> + }
>> +
>> + void setRNUnallocableNodeListItr(
>> + const RNUnallocableNodeListIterator
>> &rNUnallocableNodeListItr) {
>> +
>> + this->rNUnallocableNodeListItr = rNUnallocableNodeListItr;
>> + }
>> +
>> + RNUnallocableNodeListIterator getRNUnallocableNodeListItr
>> () const {
>> + return rNUnallocableNodeListItr;
>> + }
>> +
>> +
>> + };
>> +
>> + class EdgeData {
>> + private:
>> +
>> + typedef std::vector<unsigned> UnsafeArray;
>> +
>> + unsigned worstDegree,
>> + reverseWorstDegree;
>> + UnsafeArray unsafe, reverseUnsafe;
>> +
>> + public:
>> +
>> + EdgeData() : worstDegree(0), reverseWorstDegree(0) {}
>> +
>> + typedef UnsafeArray::const_iterator ConstUnsafeIterator;
>> +
>> + void setup(SolverGraph &g, const GraphEdgeIterator
>> &edgeItr) {
>> + const Matrix &edgeCosts = g.getEdgeCosts(edgeItr);
>> + unsigned numRegs = edgeCosts.getRows() - 1,
>> + numReverseRegs = edgeCosts.getCols() - 1;
>> +
>> + unsafe.resize(numRegs, 0);
>> + reverseUnsafe.resize(numReverseRegs, 0);
>> +
>> + std::vector<unsigned> rowInfCounts(numRegs, 0),
>> + colInfCounts(numReverseRegs, 0);
>> +
>> + for (unsigned i = 0; i < numRegs; ++i) {
>> + for (unsigned j = 0; j < numReverseRegs; ++j) {
>> + if (edgeCosts[i + 1][j + 1] ==
>> + std::numeric_limits<PBQPNum>::infinity()) {
>> + unsafe[i] = 1;
>> + reverseUnsafe[j] = 1;
>> + ++rowInfCounts[i];
>> + ++colInfCounts[j];
>> +
>> + if (colInfCounts[j] > worstDegree) {
>> + worstDegree = colInfCounts[j];
>> + }
>> +
>> + if (rowInfCounts[i] > reverseWorstDegree) {
>> + reverseWorstDegree = rowInfCounts[i];
>> + }
>> + }
>> + }
>> + }
>> + }
>> +
>> + unsigned getWorstDegree() const { return worstDegree; }
>> + unsigned getReverseWorstDegree() const { return
>> reverseWorstDegree; }
>> + ConstUnsafeIterator unsafeBegin() const { return
>> unsafe.begin(); }
>> + ConstUnsafeIterator unsafeEnd() const { return unsafe.end
>> (); }
>> + ConstUnsafeIterator reverseUnsafeBegin() const {
>> + return reverseUnsafe.begin();
>> + }
>> + ConstUnsafeIterator reverseUnsafeEnd() const {
>> + return reverseUnsafe.end();
>> + }
>> + };
>> +
>> + void initialise(Solver &solver) {
>> + this->s = &solver;
>> + g = &s->getGraph();
>> + rNAllocableBucket = RNAllocableNodeList(LinkDegreeComparator
>> (g));
>> + rNUnallocableBucket =
>> + RNUnallocableNodeList(SpillPriorityComparator(g));
>> + + for (GraphEdgeIterator
>> + edgeItr = g->edgesBegin(), edgeEnd = g->edgesEnd();
>> + edgeItr != edgeEnd; ++edgeItr) {
>> +
>> + g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr);
>> + }
>> +
>> + for (GraphNodeIterator
>> + nodeItr = g->nodesBegin(), nodeEnd = g->nodesEnd();
>> + nodeItr != nodeEnd; ++nodeItr) {
>> +
>> + g->getNodeData(nodeItr).getHeuristicData().setup(*g, nodeItr);
>> + }
>> + }
>> +
>> + void addToRNBucket(const GraphNodeIterator &nodeItr) {
>> + NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
>> +
>> + if (nodeData.isAllocable()) {
>> + nodeData.setRNAllocableNodeListItr(
>> + rNAllocableBucket.insert(rNAllocableBucket.begin(),
>> nodeItr));
>> + }
>> + else {
>> + nodeData.setRNUnallocableNodeListItr(
>> + rNUnallocableBucket.insert(rNUnallocableBucket.begin(),
>> nodeItr));
>> + }
>> + }
>> +
>> + void removeFromRNBucket(const GraphNodeIterator &nodeItr) {
>> + NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
>> +
>> + if (nodeData.isAllocable()) {
>> + rNAllocableBucket.erase(nodeData.getRNAllocableNodeListItr());
>> + }
>> + else {
>> + rNUnallocableBucket.erase
>> (nodeData.getRNUnallocableNodeListItr());
>> + }
>> + }
>> +
>> + void handleAddLink(const GraphEdgeIterator &edgeItr) {
>> + // We assume that if we got here this edge is attached to at
>> least
>> + // one high degree node.
>> + g->getEdgeData(edgeItr).getHeuristicData().setup(*g, edgeItr);
>> +
>> + GraphNodeIterator n1Itr = g->getEdgeNode1Itr(edgeItr),
>> + n2Itr = g->getEdgeNode2Itr(edgeItr);
>> + + HSIT::NodeData &n1Data = g->getNodeData(n1Itr),
>> + &n2Data = g->getNodeData(n2Itr);
>> +
>> + if (n1Data.getLinkDegree() > 2) {
>> + n1Data.getHeuristicData().handleAddLink(*g, n1Itr, edgeItr);
>> + }
>> + if (n2Data.getLinkDegree() > 2) {
>> + n2Data.getHeuristicData().handleAddLink(*g, n2Itr, edgeItr);
>> + }
>> + }
>> +
>> + void handleRemoveLink(const GraphEdgeIterator &edgeItr,
>> + const GraphNodeIterator &nodeItr) {
>> + NodeData &nodeData = g->getNodeData(nodeItr).getHeuristicData();
>> + nodeData.handleRemoveLink(*g, nodeItr, edgeItr);
>> + }
>> +
>> + void processRN() {
>> +
>> + /* + std::cerr << "processRN():\n"
>> + << " rNAllocable = [ ";
>> + for (RNAllocableNodeListIterator nItr = rNAllocableBucket.begin
>> (),
>> + nEnd = rNAllocableBucket.end();
>> + nItr != nEnd; ++nItr) {
>> + std::cerr << g->getNodeID(*nItr) << " (" << g->getNodeData
>> (*nItr).getLinkDegree() << ") ";
>> + }
>> + std::cerr << "]\n"
>> + << " rNUnallocable = [ ";
>> + for (RNUnallocableNodeListIterator nItr =
>> rNUnallocableBucket.begin(),
>> + nEnd =
>> rNUnallocableBucket.end();
>> + nItr != nEnd; ++nItr) {
>> + float bCost = g->getNodeCosts(*nItr)[0] / g->getNodeData
>> (*nItr).getLinkDegree();
>> + std::cerr << g->getNodeID(*nItr) << " (" << bCost << ") ";
>> + }
>> + std::cerr << "]\n";
>> + */
>> +
>> + if (!rNAllocableBucket.empty()) {
>> + GraphNodeIterator selectedNodeItr = *rNAllocableBucket.begin
>> ();
>> + //std::cerr << "RN safely pushing " << g->getNodeID
>> (selectedNodeItr) << "\n";
>> + rNAllocableBucket.erase(rNAllocableBucket.begin());
>> + s->pushStack(selectedNodeItr);
>> + s->unlinkNode(selectedNodeItr);
>> + }
>> + else {
>> + GraphNodeIterator selectedNodeItr =
>> *rNUnallocableBucket.begin();
>> + //std::cerr << "RN optimistically pushing " << g->getNodeID
>> (selectedNodeItr) << "\n";
>> + rNUnallocableBucket.erase(rNUnallocableBucket.begin());
>> + s->pushStack(selectedNodeItr);
>> + s->unlinkNode(selectedNodeItr);
>> + }
>> + + }
>> +
>> + bool rNBucketEmpty() const {
>> + return (rNAllocableBucket.empty() && rNUnallocableBucket.empty
>> ());
>> + }
>> +
>> +private:
>> +
>> + Solver *s;
>> + SolverGraph *g;
>> + RNAllocableNodeList rNAllocableBucket;
>> + RNUnallocableNodeList rNUnallocableBucket;
>> +};
>> +
>> +
>> +
>> +}
>> +}
>> +
>> +
>> +#endif // LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/PBQPMath.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/PBQPMath.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/PBQPMath.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/PBQPMath.h Thu Aug 6 18:32:48 2009
>> @@ -0,0 +1,279 @@
>> +#ifndef LLVM_CODEGEN_PBQP_PBQPMATH_H +#define
>> LLVM_CODEGEN_PBQP_PBQPMATH_H
>> +
>> +#include <cassert>
>> +#include <algorithm>
>> +#include <functional>
>> +
>> +namespace PBQP {
>> +
>> +typedef double PBQPNum;
>> +
>> +/// \brief PBQP Vector class.
>> +class Vector {
>> + public:
>> +
>> + /// \brief Construct a PBQP vector of the given size.
>> + explicit Vector(unsigned length) :
>> + length(length), data(new PBQPNum[length]) {
>> + }
>> +
>> + /// \brief Construct a PBQP vector with initializer.
>> + Vector(unsigned length, PBQPNum initVal) :
>> + length(length), data(new PBQPNum[length]) {
>> + std::fill(data, data + length, initVal);
>> + }
>> +
>> + /// \brief Copy construct a PBQP vector.
>> + Vector(const Vector &v) :
>> + length(v.length), data(new PBQPNum[length]) {
>> + std::copy(v.data, v.data + length, data);
>> + }
>> +
>> + /// \brief Destroy this vector, return its memory.
>> + ~Vector() { delete[] data; }
>> +
>> + /// \brief Assignment operator.
>> + Vector& operator=(const Vector &v) {
>> + delete[] data;
>> + length = v.length;
>> + data = new PBQPNum[length];
>> + std::copy(v.data, v.data + length, data);
>> + return *this;
>> + }
>> +
>> + /// \brief Return the length of the vector
>> + unsigned getLength() const throw () {
>> + return length;
>> + }
>> +
>> + /// \brief Element access.
>> + PBQPNum& operator[](unsigned index) {
>> + assert(index < length && "Vector element access out of
>> bounds.");
>> + return data[index];
>> + }
>> +
>> + /// \brief Const element access.
>> + const PBQPNum& operator[](unsigned index) const {
>> + assert(index < length && "Vector element access out of
>> bounds.");
>> + return data[index];
>> + }
>> +
>> + /// \brief Add another vector to this one.
>> + Vector& operator+=(const Vector &v) {
>> + assert(length == v.length && "Vector length mismatch.");
>> + std::transform(data, data + length, v.data, data,
>> std::plus<PBQPNum>()); + return *this;
>> + }
>> +
>> + /// \brief Subtract another vector from this one.
>> + Vector& operator-=(const Vector &v) {
>> + assert(length == v.length && "Vector length mismatch.");
>> + std::transform(data, data + length, v.data, data,
>> std::minus<PBQPNum>()); + return *this;
>> + }
>> +
>> + /// \brief Returns the index of the minimum value in this vector
>> + unsigned minIndex() const {
>> + return std::min_element(data, data + length) - data;
>> + }
>> +
>> + private:
>> + unsigned length;
>> + PBQPNum *data;
>> +};
>> +
>> +/// \brief Output a textual representation of the given vector on
>> the given
>> +/// output stream.
>> +template <typename OStream>
>> +OStream& operator<<(OStream &os, const Vector &v) {
>> + assert((v.getLength() != 0) && "Zero-length vector badness.");
>> +
>> + os << "[ " << v[0];
>> + for (unsigned i = 1; i < v.getLength(); ++i) {
>> + os << ", " << v[i];
>> + }
>> + os << " ]";
>> +
>> + return os;
>> +} +
>> +
>> +/// \brief PBQP Matrix class
>> +class Matrix {
>> + public:
>> +
>> + /// \brief Construct a PBQP Matrix with the given dimensions.
>> + Matrix(unsigned rows, unsigned cols) :
>> + rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
>> + }
>> +
>> + /// \brief Construct a PBQP Matrix with the given dimensions
>> and initial
>> + /// value.
>> + Matrix(unsigned rows, unsigned cols, PBQPNum initVal) :
>> + rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
>> + std::fill(data, data + (rows * cols), initVal);
>> + }
>> +
>> + /// \brief Copy construct a PBQP matrix.
>> + Matrix(const Matrix &m) :
>> + rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) {
>> + std::copy(m.data, m.data + (rows * cols), data); + }
>> +
>> + /// \brief Destroy this matrix, return its memory.
>> + ~Matrix() { delete[] data; }
>> +
>> + /// \brief Assignment operator.
>> + Matrix& operator=(const Matrix &m) {
>> + delete[] data;
>> + rows = m.rows; cols = m.cols;
>> + data = new PBQPNum[rows * cols];
>> + std::copy(m.data, m.data + (rows * cols), data);
>> + return *this;
>> + }
>> +
>> + /// \brief Return the number of rows in this matrix.
>> + unsigned getRows() const throw () { return rows; }
>> +
>> + /// \brief Return the number of cols in this matrix.
>> + unsigned getCols() const throw () { return cols; }
>> +
>> + /// \brief Matrix element access.
>> + PBQPNum* operator[](unsigned r) {
>> + assert(r < rows && "Row out of bounds.");
>> + return data + (r * cols);
>> + }
>> +
>> + /// \brief Matrix element access.
>> + const PBQPNum* operator[](unsigned r) const {
>> + assert(r < rows && "Row out of bounds.");
>> + return data + (r * cols);
>> + }
>> +
>> + /// \brief Returns the given row as a vector.
>> + Vector getRowAsVector(unsigned r) const {
>> + Vector v(cols);
>> + for (unsigned c = 0; c < cols; ++c)
>> + v[c] = (*this)[r][c];
>> + return v; + }
>> +
>> + /// \brief Returns the given column as a vector.
>> + Vector getColAsVector(unsigned c) const {
>> + Vector v(rows);
>> + for (unsigned r = 0; r < rows; ++r)
>> + v[r] = (*this)[r][c];
>> + return v;
>> + }
>> +
>> + /// \brief Reset the matrix to the given value.
>> + Matrix& reset(PBQPNum val = 0) {
>> + std::fill(data, data + (rows * cols), val);
>> + return *this;
>> + }
>> +
>> + /// \brief Set a single row of this matrix to the given value.
>> + Matrix& setRow(unsigned r, PBQPNum val) {
>> + assert(r < rows && "Row out of bounds.");
>> + std::fill(data + (r * cols), data + ((r + 1) * cols), val);
>> + return *this;
>> + }
>> +
>> + /// \brief Set a single column of this matrix to the given
>> value.
>> + Matrix& setCol(unsigned c, PBQPNum val) {
>> + assert(c < cols && "Column out of bounds.");
>> + for (unsigned r = 0; r < rows; ++r)
>> + (*this)[r][c] = val;
>> + return *this;
>> + }
>> +
>> + /// \brief Matrix transpose.
>> + Matrix transpose() const {
>> + Matrix m(cols, rows);
>> + for (unsigned r = 0; r < rows; ++r)
>> + for (unsigned c = 0; c < cols; ++c)
>> + m[c][r] = (*this)[r][c];
>> + return m;
>> + }
>> +
>> + /// \brief Returns the diagonal of the matrix as a vector.
>> + ///
>> + /// Matrix must be square.
>> + Vector diagonalize() const {
>> + assert(rows == cols && "Attempt to diagonalize non-square
>> matrix.");
>> +
>> + Vector v(rows);
>> + for (unsigned r = 0; r < rows; ++r)
>> + v[r] = (*this)[r][r];
>> + return v;
>> + } +
>> + /// \brief Add the given matrix to this one.
>> + Matrix& operator+=(const Matrix &m) {
>> + assert(rows == m.rows && cols == m.cols &&
>> + "Matrix dimensions mismatch.");
>> + std::transform(data, data + (rows * cols), m.data, data,
>> + std::plus<PBQPNum>());
>> + return *this;
>> + }
>> +
>> + /// \brief Returns the minimum of the given row
>> + PBQPNum getRowMin(unsigned r) const {
>> + assert(r < rows && "Row out of bounds");
>> + return *std::min_element(data + (r * cols), data + ((r + 1)
>> * cols));
>> + }
>> +
>> + /// \brief Returns the minimum of the given column
>> + PBQPNum getColMin(unsigned c) const {
>> + PBQPNum minElem = (*this)[0][c];
>> + for (unsigned r = 1; r < rows; ++r)
>> + if ((*this)[r][c] < minElem) minElem = (*this)[r][c];
>> + return minElem;
>> + }
>> +
>> + /// \brief Subtracts the given scalar from the elements of the
>> given row.
>> + Matrix& subFromRow(unsigned r, PBQPNum val) {
>> + assert(r < rows && "Row out of bounds");
>> + std::transform(data + (r * cols), data + ((r + 1) * cols),
>> + data + (r * cols),
>> + std::bind2nd(std::minus<PBQPNum>(), val));
>> + return *this;
>> + }
>> +
>> + /// \brief Subtracts the given scalar from the elements of the
>> given column.
>> + Matrix& subFromCol(unsigned c, PBQPNum val) {
>> + for (unsigned r = 0; r < rows; ++r)
>> + (*this)[r][c] -= val;
>> + return *this;
>> + }
>> +
>> + /// \brief Returns true if this is a zero matrix.
>> + bool isZero() const {
>> + return find_if(data, data + (rows * cols),
>> + std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) ==
>> + data + (rows * cols);
>> + }
>> +
>> + private:
>> + unsigned rows, cols;
>> + PBQPNum *data;
>> +};
>> +
>> +/// \brief Output a textual representation of the given matrix on
>> the given
>> +/// output stream.
>> +template <typename OStream>
>> +OStream& operator<<(OStream &os, const Matrix &m) {
>> +
>> + assert((m.getRows() != 0) && "Zero-row matrix badness.");
>> +
>> + for (unsigned i = 0; i < m.getRows(); ++i) {
>> + os << m.getRowAsVector(i);
>> + }
>> +
>> + return os;
>> +}
>> +
>> +}
>> +
>> +#endif // LLVM_CODEGEN_PBQP_PBQPMATH_HPP
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/SimpleGraph.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/SimpleGraph.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/SimpleGraph.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/SimpleGraph.h Thu Aug 6 18:32:48
>> 2009
>> @@ -0,0 +1,86 @@
>> +#ifndef LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H
>> +#define LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H
>> +
>> +#include "GraphBase.h"
>> +
>> +namespace PBQP {
>> +
>> +class SimpleEdge;
>> +
>> +class SimpleNode : public NodeBase<SimpleNode, SimpleEdge> {
>> +public:
>> + SimpleNode(const Vector &costs) :
>> + NodeBase<SimpleNode, SimpleEdge>(costs) {}
>> +};
>> +
>> +class SimpleEdge : public EdgeBase<SimpleNode, SimpleEdge> {
>> +public:
>> + SimpleEdge(const NodeIterator &node1Itr, const NodeIterator
>> &node2Itr,
>> + const Matrix &costs) :
>> + EdgeBase<SimpleNode, SimpleEdge>(node1Itr, node2Itr, costs) {}
>> +};
>> +
>> +class SimpleGraph : public GraphBase<SimpleNode, SimpleEdge> {
>> +private:
>> +
>> + typedef GraphBase<SimpleNode, SimpleEdge> PGraph;
>> +
>> + void copyFrom(const SimpleGraph &other) {
>> + assert(other.areNodeIDsValid() &&
>> + "Cannot copy from another graph unless IDs have been
>> assigned.");
>> + + std::vector<NodeIterator> newNodeItrs(other.getNumNodes());
>> +
>> + for (ConstNodeIterator nItr = other.nodesBegin(), nEnd =
>> other.nodesEnd();
>> + nItr != nEnd; ++nItr) {
>> + newNodeItrs[other.getNodeID(nItr)] = addNode
>> (other.getNodeCosts(nItr));
>> + }
>> +
>> + for (ConstEdgeIterator eItr = other.edgesBegin(), eEnd =
>> other.edgesEnd();
>> + eItr != eEnd; ++eItr) {
>> +
>> + unsigned node1ID = other.getNodeID(other.getEdgeNode1Itr
>> (eItr)),
>> + node2ID = other.getNodeID(other.getEdgeNode2Itr
>> (eItr));
>> +
>> + addEdge(newNodeItrs[node1ID], newNodeItrs[node2ID],
>> + other.getEdgeCosts(eItr));
>> + }
>> + }
>> +
>> + void copyFrom(SimpleGraph &other) {
>> + if (!other.areNodeIDsValid()) {
>> + other.assignNodeIDs();
>> + }
>> + copyFrom(const_cast<const SimpleGraph&>(other));
>> + }
>> +
>> +public:
>> +
>> + SimpleGraph() {}
>> +
>> +
>> + SimpleGraph(const SimpleGraph &other) : PGraph() {
>> + copyFrom(other);
>> + }
>> +
>> + SimpleGraph& operator=(const SimpleGraph &other) {
>> + clear();
>> + copyFrom(other);
>> + return *this;
>> + }
>> +
>> + NodeIterator addNode(const Vector &costs) {
>> + return PGraph::addConstructedNode(SimpleNode(costs));
>> + }
>> +
>> + EdgeIterator addEdge(const NodeIterator &node1Itr,
>> + const NodeIterator &node2Itr,
>> + const Matrix &costs) {
>> + return PGraph::addConstructedEdge(SimpleEdge(node1Itr,
>> node2Itr, costs));
>> + }
>> +
>> +};
>> +
>> +}
>> +
>> +#endif // LLVM_CODEGEN_PBQP_SIMPLEGRAPH_H
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/Solution.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/Solution.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/Solution.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/Solution.h Thu Aug 6 18:32:48 2009
>> @@ -0,0 +1,74 @@
>> +#ifndef LLVM_CODEGEN_PBQP_SOLUTION_H
>> +#define LLVM_CODEGEN_PBQP_SOLUTION_H
>> +
>> +#include "PBQPMath.h"
>> +
>> +namespace PBQP {
>> +
>> +class Solution {
>> +
>> + friend class SolverImplementation;
>> +
>> +private:
>> +
>> + std::vector<unsigned> selections;
>> + PBQPNum solutionCost;
>> + bool provedOptimal;
>> + unsigned r0Reductions, r1Reductions,
>> + r2Reductions, rNReductions;
>> +
>> +public:
>> +
>> + Solution() :
>> + solutionCost(0.0), provedOptimal(false),
>> + r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions
>> (0) {}
>> +
>> + Solution(unsigned length, bool assumeOptimal) :
>> + selections(length), solutionCost(0.0), provedOptimal
>> (assumeOptimal),
>> + r0Reductions(0), r1Reductions(0), r2Reductions(0), rNReductions
>> (0) {}
>> +
>> + void setProvedOptimal(bool provedOptimal) {
>> + this->provedOptimal = provedOptimal;
>> + }
>> +
>> + void setSelection(unsigned nodeID, unsigned selection) {
>> + selections[nodeID] = selection;
>> + }
>> +
>> + void setSolutionCost(PBQPNum solutionCost) {
>> + this->solutionCost = solutionCost;
>> + }
>> +
>> + void incR0Reductions() { ++r0Reductions; }
>> + void incR1Reductions() { ++r1Reductions; }
>> + void incR2Reductions() { ++r2Reductions; }
>> + void incRNReductions() { ++rNReductions; }
>> +
>> + unsigned numNodes() const { return selections.size(); }
>> +
>> + unsigned getSelection(unsigned nodeID) const {
>> + return selections[nodeID];
>> + }
>> +
>> + PBQPNum getCost() const { return solutionCost; }
>> +
>> + bool isProvedOptimal() const { return provedOptimal; }
>> +
>> + unsigned getR0Reductions() const { return r0Reductions; }
>> + unsigned getR1Reductions() const { return r1Reductions; }
>> + unsigned getR2Reductions() const { return r2Reductions; }
>> + unsigned getRNReductions() const { return rNReductions; }
>> +
>> + bool operator==(const Solution &other) const {
>> + return (selections == other.selections);
>> + }
>> +
>> + bool operator!=(const Solution &other) const {
>> + return !(*this == other);
>> + }
>> +
>> +};
>> +
>> +}
>> +
>> +#endif // LLVM_CODEGEN_PBQP_SOLUTION_H
>>
>> Added: llvm/trunk/lib/CodeGen/PBQP/Solver.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PBQP/Solver.h?rev=78354&view=auto
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PBQP/Solver.h (added)
>> +++ llvm/trunk/lib/CodeGen/PBQP/Solver.h Thu Aug 6 18:32:48 2009
>> @@ -0,0 +1,21 @@
>> +#ifndef LLVM_CODEGEN_PBQP_SOLVER_H
>> +#define LLVM_CODEGEN_PBQP_SOLVER_H
>> +
>> +#include "SimpleGraph.h"
>> +#include "Solution.h"
>> +
>> +namespace PBQP {
>> +
>> +/// \brief Interface for solver classes.
>> +class Solver {
>> +public:
>> +
>> + virtual ~Solver() = 0;
>> + virtual Solution solve(const SimpleGraph &orig) const = 0;
>> +};
>> +
>> +Solver::~Solver() {}
>> +
>> +}
>> +
>> +#endif // LLVM_CODEGEN_PBQP_SOLVER_H
>>
>> Modified: llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp?rev=78354&r1=78353&r2=78354&view=diff
>>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp Thu Aug 6 18:32:48 2009
>> @@ -31,7 +31,9 @@
>> #define DEBUG_TYPE "regalloc"
>> -#include "PBQP.h"
>> +#include "PBQP/HeuristicSolver.h"
>> +#include "PBQP/SimpleGraph.h"
>> +#include "PBQP/Heuristics/Briggs.h"
>> #include "VirtRegMap.h"
>> #include "VirtRegRewriter.h"
>> #include "llvm/CodeGen/LiveIntervalAnalysis.h"
>> @@ -54,42 +56,41 @@
>> using namespace llvm;
>> static RegisterRegAlloc
>> -registerPBQPRepAlloc("pbqp", "PBQP register allocator",
>> - createPBQPRegisterAllocator);
>> +registerPBQPRepAlloc("pbqp", "PBQP register allocator.",
>> + llvm::createPBQPRegisterAllocator);
>> namespace {
>> - //!
>> - //! PBQP based allocators solve the register allocation problem
>> by mapping
>> - //! register allocation problems to Partitioned Boolean Quadratic
>> - //! Programming problems.
>> + ///
>> + /// PBQP based allocators solve the register allocation problem
>> by mapping
>> + /// register allocation problems to Partitioned Boolean Quadratic
>> + /// Programming problems.
>> class VISIBILITY_HIDDEN PBQPRegAlloc : public MachineFunctionPass {
>> public:
>> static char ID;
>> -
>> - //! Construct a PBQP register allocator.
>> + + /// Construct a PBQP register allocator.
>> PBQPRegAlloc() : MachineFunctionPass((intptr_t)&ID) {}
>> - //! Return the pass name.
>> + /// Return the pass name.
>> virtual const char* getPassName() const throw() {
>> return "PBQP Register Allocator";
>> }
>> - //! PBQP analysis usage.
>> - virtual void getAnalysisUsage(AnalysisUsage &AU) const {
>> - AU.setPreservesCFG();
>> - AU.addRequired<LiveIntervals>();
>> - AU.addRequiredTransitive<RegisterCoalescer>();
>> - AU.addRequired<LiveStacks>();
>> - AU.addPreserved<LiveStacks>();
>> - AU.addRequired<MachineLoopInfo>();
>> - AU.addPreserved<MachineLoopInfo>();
>> - AU.addRequired<VirtRegMap>();
>> - MachineFunctionPass::getAnalysisUsage(AU);
>> + /// PBQP analysis usage.
>> + virtual void getAnalysisUsage(AnalysisUsage &au) const {
>> + au.addRequired<LiveIntervals>();
>> + //au.addRequiredID(SplitCriticalEdgesID);
>> + au.addRequired<LiveStacks>();
>> + au.addPreserved<LiveStacks>();
>> + au.addRequired<MachineLoopInfo>();
>> + au.addPreserved<MachineLoopInfo>();
>> + au.addRequired<VirtRegMap>();
>> + MachineFunctionPass::getAnalysisUsage(au);
>> }
>> - //! Perform register allocation
>> + /// Perform register allocation
>> virtual bool runOnMachineFunction(MachineFunction &MF);
>> private:
>> @@ -99,7 +100,7 @@
>> typedef std::vector<AllowedSet> AllowedSetMap;
>> typedef std::set<unsigned> RegSet;
>> typedef std::pair<unsigned, unsigned> RegPair;
>> - typedef std::map<RegPair, PBQPNum> CoalesceMap;
>> + typedef std::map<RegPair, PBQP::PBQPNum> CoalesceMap;
>> typedef std::set<LiveInterval*> LiveIntervalSet;
>> @@ -121,60 +122,60 @@
>> emptyVRegIntervals;
>> - //! Builds a PBQP cost vector.
>> + /// Builds a PBQP cost vector.
>> template <typename RegContainer>
>> - PBQPVector* buildCostVector(unsigned vReg,
>> - const RegContainer &allowed,
>> - const CoalesceMap &cealesces,
>> - PBQPNum spillCost) const;
>> -
>> - //! \brief Builds a PBQP interference matrix.
>> - //!
>> - //! @return Either a pointer to a non-zero PBQP matrix
>> representing the
>> - //! allocation option costs, or a null pointer for a
>> zero matrix.
>> - //!
>> - //! Expects allowed sets for two interfering LiveIntervals.
>> These allowed
>> - //! sets should contain only allocable registers from the
>> LiveInterval's
>> - //! register class, with any interfering pre-colored registers
>> removed.
>> + PBQP::Vector buildCostVector(unsigned vReg,
>> + const RegContainer &allowed,
>> + const CoalesceMap &cealesces,
>> + PBQP::PBQPNum spillCost) const;
>> +
>> + /// \brief Builds a PBQP interference matrix.
>> + ///
>> + /// @return Either a pointer to a non-zero PBQP matrix
>> representing the
>> + /// allocation option costs, or a null pointer for a
>> zero matrix.
>> + ///
>> + /// Expects allowed sets for two interfering LiveIntervals.
>> These allowed
>> + /// sets should contain only allocable registers from the
>> LiveInterval's
>> + /// register class, with any interfering pre-colored registers
>> removed.
>> template <typename RegContainer>
>> - PBQPMatrix* buildInterferenceMatrix(const RegContainer
>> &allowed1,
>> - const RegContainer
>> &allowed2) const;
>> + PBQP::Matrix* buildInterferenceMatrix(const RegContainer
>> &allowed1,
>> + const RegContainer
>> &allowed2) const;
>> - //!
>> - //! Expects allowed sets for two potentially coalescable
>> LiveIntervals,
>> - //! and an estimated benefit due to coalescing. The allowed
>> sets should
>> - //! contain only allocable registers from the LiveInterval's
>> register
>> - //! classes, with any interfering pre-colored registers removed.
>> + ///
>> + /// Expects allowed sets for two potentially coalescable
>> LiveIntervals,
>> + /// and an estimated benefit due to coalescing. The allowed
>> sets should
>> + /// contain only allocable registers from the LiveInterval's
>> register
>> + /// classes, with any interfering pre-colored registers removed.
>> template <typename RegContainer>
>> - PBQPMatrix* buildCoalescingMatrix(const RegContainer &allowed1,
>> - const RegContainer &allowed2,
>> - PBQPNum cBenefit) const;
>> -
>> - //! \brief Finds coalescing opportunities and returns them as
>> a map.
>> - //!
>> - //! Any entries in the map are guaranteed coalescable, even if
>> their
>> - //! corresponding live intervals overlap.
>> + PBQP::Matrix* buildCoalescingMatrix(const RegContainer
>> &allowed1,
>> + const RegContainer
>> &allowed2,
>> + PBQP::PBQPNum cBenefit)
>> const;
>> +
>> + /// \brief Finds coalescing opportunities and returns them as
>> a map.
>> + ///
>> + /// Any entries in the map are guaranteed coalescable, even if
>> their
>> + /// corresponding live intervals overlap.
>> CoalesceMap findCoalesces();
>> - //! \brief Finds the initial set of vreg intervals to allocate.
>> + /// \brief Finds the initial set of vreg intervals to allocate.
>> void findVRegIntervalsToAlloc();
>> - //! \brief Constructs a PBQP problem representation of the
>> register
>> - //! allocation problem for this function.
>> - //!
>> - //! @return a PBQP solver object for the register allocation
>> problem.
>> - pbqp* constructPBQPProblem();
>> + /// \brief Constructs a PBQP problem representation of the
>> register
>> + /// allocation problem for this function.
>> + ///
>> + /// @return a PBQP solver object for the register allocation
>> problem.
>> + PBQP::SimpleGraph constructPBQPProblem();
>> - //! \brief Adds a stack interval if the given live interval
>> has been
>> - //! spilled. Used to support stack slot coloring.
>> + /// \brief Adds a stack interval if the given live interval
>> has been
>> + /// spilled. Used to support stack slot coloring.
>> void addStackInterval(const LiveInterval
>> *spilled,MachineRegisterInfo* mri);
>> - //! \brief Given a solved PBQP problem maps this solution back
>> to a register
>> - //! assignment.
>> - bool mapPBQPToRegAlloc(pbqp *problem);
>> + /// \brief Given a solved PBQP problem maps this solution back
>> to a register
>> + /// assignment.
>> + bool mapPBQPToRegAlloc(const PBQP::Solution &solution);
>> - //! \brief Postprocessing before final spilling. Sets basic
>> block "live in"
>> - //! variables.
>> + /// \brief Postprocessing before final spilling. Sets basic
>> block "live in"
>> + /// variables.
>> void finalizeAlloc() const;
>> };
>> @@ -184,17 +185,17 @@
>> template <typename RegContainer>
>> -PBQPVector* PBQPRegAlloc::buildCostVector(unsigned vReg,
>> - const RegContainer
>> &allowed,
>> - const CoalesceMap
>> &coalesces,
>> - PBQPNum spillCost) const {
>> +PBQP::Vector PBQPRegAlloc::buildCostVector(unsigned vReg,
>> + const RegContainer
>> &allowed,
>> + const CoalesceMap
>> &coalesces,
>> + PBQP::PBQPNum
>> spillCost) const {
>> typedef typename RegContainer::const_iterator AllowedItr;
>> // Allocate vector. Additional element (0th) used for spill option
>> - PBQPVector *v = new PBQPVector(allowed.size() + 1);
>> + PBQP::Vector v(allowed.size() + 1, 0);
>> - (*v)[0] = spillCost;
>> + v[0] = spillCost;
>> // Iterate over the allowed registers inserting coalesce
>> benefits if there
>> // are any.
>> @@ -212,14 +213,14 @@
>> continue;
>> // We have a coalesce - insert the benefit.
>> - (*v)[ai + 1] = -cmItr->second;
>> + v[ai + 1] = -cmItr->second;
>> }
>> return v;
>> }
>> template <typename RegContainer>
>> -PBQPMatrix* PBQPRegAlloc::buildInterferenceMatrix(
>> +PBQP::Matrix* PBQPRegAlloc::buildInterferenceMatrix(
>> const RegContainer &allowed1, const RegContainer &allowed2)
>> const {
>> typedef typename RegContainer::const_iterator
>> RegContainerIterator;
>> @@ -232,7 +233,8 @@
>> // that the spill option (element 0,0) has zero cost, since we
>> can allocate
>> // both intervals to memory safely (the cost for each individual
>> allocation
>> // to memory is accounted for by the cost vectors for each live
>> interval).
>> - PBQPMatrix *m = new PBQPMatrix(allowed1.size() + 1, allowed2.size
>> () + 1);
>> + PBQP::Matrix *m =
>> + new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0);
>> // Assume this is a zero matrix until proven otherwise. Zero
>> matrices occur
>> // between interfering live ranges with non-overlapping register
>> sets (e.g.
>> @@ -262,7 +264,7 @@
>> // If the row/column regs are identical or alias insert an
>> infinity.
>> if ((reg1 == reg2) || tri->areAliases(reg1, reg2)) {
>> - (*m)[ri][ci] = std::numeric_limits<PBQPNum>::infinity();
>> + (*m)[ri][ci] = std::numeric_limits<PBQP::PBQPNum>::infinity
>> ();
>> isZeroMatrix = false;
>> }
>> @@ -284,9 +286,9 @@
>> }
>> template <typename RegContainer>
>> -PBQPMatrix* PBQPRegAlloc::buildCoalescingMatrix(
>> +PBQP::Matrix* PBQPRegAlloc::buildCoalescingMatrix(
>> const RegContainer &allowed1, const RegContainer &allowed2,
>> - PBQPNum cBenefit) const {
>> + PBQP::PBQPNum cBenefit) const {
>> typedef typename RegContainer::const_iterator
>> RegContainerIterator;
>> @@ -295,7 +297,8 @@
>> // for the LiveIntervals which are (potentially) to be coalesced.
>> The amount
>> // -cBenefit will be placed in any element representing the same
>> register
>> // for both intervals.
>> - PBQPMatrix *m = new PBQPMatrix(allowed1.size() + 1, allowed2.size
>> () + 1);
>> + PBQP::Matrix *m =
>> + new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0);
>> // Reset costs to zero.
>> m->reset(0);
>> @@ -497,10 +500,11 @@
>> }
>> }
>> -pbqp* PBQPRegAlloc::constructPBQPProblem() {
>> +PBQP::SimpleGraph PBQPRegAlloc::constructPBQPProblem() {
>> typedef std::vector<const LiveInterval*> LIVector;
>> typedef std::vector<unsigned> RegVector;
>> + typedef std::vector<PBQP::SimpleGraph::NodeIterator> NodeVector;
>> // This will store the physical intervals for easy reference.
>> LIVector physIntervals;
>> @@ -532,10 +536,11 @@
>> }
>> // Get the set of potential coalesces.
>> - CoalesceMap coalesces(findCoalesces());
>> + CoalesceMap coalesces;//(findCoalesces());
>> // Construct a PBQP solver for this problem
>> - pbqp *solver = alloc_pbqp(vregIntervalsToAlloc.size());
>> + PBQP::SimpleGraph problem;
>> + NodeVector problemNodes(vregIntervalsToAlloc.size());
>> // Resize allowedSets container appropriately.
>> allowedSets.resize(vregIntervalsToAlloc.size());
>> @@ -596,13 +601,13 @@
>> // Set the spill cost to the interval weight, or epsilon if the
>> // interval weight is zero
>> - PBQPNum spillCost = (li->weight != 0.0) ?
>> - li->weight : std::numeric_limits<PBQPNum>::min();
>> + PBQP::PBQPNum spillCost = (li->weight != 0.0) ?
>> + li->weight : std::numeric_limits<PBQP::PBQPNum>::min();
>> // Build a cost vector for this interval.
>> - add_pbqp_nodecosts(solver, node,
>> - buildCostVector(li->reg, allowedSets[node],
>> coalesces,
>> - spillCost));
>> + problemNodes[node] =
>> + problem.addNode(
>> + buildCostVector(li->reg, allowedSets[node], coalesces,
>> spillCost));
>> }
>> @@ -618,7 +623,7 @@
>> CoalesceMap::const_iterator cmItr =
>> coalesces.find(RegPair(li->reg, li2->reg));
>> - PBQPMatrix *m = 0;
>> + PBQP::Matrix *m = 0;
>> if (cmItr != coalesces.end()) {
>> m = buildCoalescingMatrix(allowedSets[node1], allowedSets
>> [node2],
>> @@ -629,14 +634,29 @@
>> }
>> if (m != 0) {
>> - add_pbqp_edgecosts(solver, node1, node2, m);
>> + problem.addEdge(problemNodes[node1],
>> + problemNodes[node2],
>> + *m);
>> +
>> delete m;
>> }
>> }
>> }
>> + problem.assignNodeIDs();
>> +
>> + assert(problem.getNumNodes() == allowedSets.size());
>> + for (unsigned i = 0; i < allowedSets.size(); ++i) {
>> + assert(problem.getNodeItr(i) == problemNodes[i]);
>> + }
>> +/*
>> + std::cerr << "Allocating for " << problem.getNumNodes() << "
>> nodes, "
>> + << problem.getNumEdges() << " edges.\n";
>> +
>> + problem.printDot(std::cerr);
>> +*/
>> // We're done, PBQP problem constructed - return it.
>> - return solver;
>> + return problem;
>> }
>> void PBQPRegAlloc::addStackInterval(const LiveInterval *spilled,
>> @@ -659,7 +679,9 @@
>> stackInterval.MergeRangesInAsValue(rhsInterval, vni);
>> }
>> -bool PBQPRegAlloc::mapPBQPToRegAlloc(pbqp *problem) {
>> +bool PBQPRegAlloc::mapPBQPToRegAlloc(const PBQP::Solution
>> &solution) {
>> +
>> + static unsigned round = 0;
>> // Set to true if we have any spills
>> bool anotherRoundNeeded = false;
>> @@ -667,10 +689,56 @@
>> // Clear the existing allocation.
>> vrm->clearAllVirt();
>> + CoalesceMap coalesces;//(findCoalesces());
>> +
>> + for (unsigned i = 0; i < node2LI.size(); ++i) {
>> + if (solution.getSelection(i) == 0) {
>> + continue;
>> + }
>> +
>> + unsigned iSel = solution.getSelection(i);
>> + unsigned iAlloc = allowedSets[i][iSel - 1];
>> +
>> + for (unsigned j = i + 1; j < node2LI.size(); ++j) {
>> +
>> + if (solution.getSelection(j) == 0) {
>> + continue;
>> + }
>> +
>> + unsigned jSel = solution.getSelection(j);
>> + unsigned jAlloc = allowedSets[j][jSel - 1];
>> + + if ((iAlloc != jAlloc) && !tri->areAliases(iAlloc,
>> jAlloc)) {
>> + continue;
>> + }
>> +
>> + if (node2LI[i]->overlaps(*node2LI[j])) {
>> + if (coalesces.find(RegPair(node2LI[i]->reg, node2LI[j]-
>> >reg)) == coalesces.end()) {
>> + DEBUG(errs() << "In round " << ++round << ":\n"
>> + << "Bogusness in " << mf->getFunction()->getName()
>> << "!\n"
>> + << "Live interval " << i << " (reg" << node2LI[i]-
>> >reg << ") and\n"
>> + << "Live interval " << j << " (reg" << node2LI[j]-
>> >reg << ")\n"
>> + << " were allocated registers " << iAlloc <<
>> " (index " << iSel << ") and "
>> + << jAlloc << "(index " << jSel + <<
>> ") respectively in a graph of " << solution.numNodes() << " nodes.\n"
>> + << "li[i]->empty() = " << node2LI[i]->empty() << "\n"
>> + << "li[j]->empty() = " << node2LI[j]->empty() << "\n"
>> + << "li[i]->overlaps(li[j]) = " << node2LI[i]-
>> >overlaps(*node2LI[j]) << "\n"
>> + << "coalesce = " << (coalesces.find(RegPair(node2LI
>> [i]->reg, node2LI[j]->reg)) != coalesces.end()) << "\n");
>> + + DEBUG(errs() << "solution.getCost() = " <<
>> solution.getCost() << "\n");
>> + exit(1);
>> + }
>> + }
>> + }
>> + }
>> +
>> +
>> // Iterate over the nodes mapping the PBQP solution to a register
>> assignment.
>> for (unsigned node = 0; node < node2LI.size(); ++node) {
>> unsigned virtReg = node2LI[node]->reg,
>> - allocSelection = get_pbqp_solution(problem, node);
>> + allocSelection = solution.getSelection(node);
>> +
>> // If the PBQP solution is non-zero it's a physical register...
>> if (allocSelection != 0) {
>> @@ -731,11 +799,12 @@
>> // First allocate registers for the empty intervals.
>> for (LiveIntervalSet::const_iterator
>> - itr = emptyVRegIntervals.begin(), end =
>> emptyVRegIntervals.end();
>> + itr = emptyVRegIntervals.begin(), end = emptyVRegIntervals.end();
>> itr != end; ++itr) {
>> LiveInterval *li = *itr;
>> unsigned physReg = vrm->getRegAllocPref(li->reg);
>> +
>> if (physReg == 0) {
>> const TargetRegisterClass *liRC = mri->getRegClass(li->reg);
>> physReg = *liRC->allocation_order_begin(*mf);
>> @@ -766,8 +835,8 @@
>> continue;
>> }
>> - // Ignore unallocated vregs:
>> if (reg == 0) {
>> + // Filter out zero regs - they're for intervals that were
>> spilled.
>> continue;
>> }
>> @@ -806,8 +875,7 @@
>> vrm = &getAnalysis<VirtRegMap>();
>> - DEBUG(errs() << "PBQP Register Allocating for " - << mf-
>> >getFunction()->getName() << "\n");
>> + DEBUG(errs() << "PBQP2 Register Allocating for " << mf-
>> >getFunction()->getName() << "\n");
>> // Allocator main loop:
>> //
>> @@ -832,15 +900,19 @@
>> unsigned round = 0;
>> while (!pbqpAllocComplete) {
>> - DOUT << " PBQP Regalloc round " << round << ":\n";
>> -
>> - pbqp *problem = constructPBQPProblem();
>> + DEBUG(errs() << " PBQP Regalloc round " << round << ":\n");
>> - solve_pbqp(problem);
>> -
>> - pbqpAllocComplete = mapPBQPToRegAlloc(problem);
>> -
>> - free_pbqp(problem);
>> + PBQP::SimpleGraph problem = constructPBQPProblem();
>> + PBQP::HeuristicSolver<PBQP::Heuristics::Briggs> solver;
>> + problem.assignNodeIDs();
>> + PBQP::Solution solution = solver.solve(problem);
>> +/*
>> + std::cerr << "Solution:\n";
>> + for (unsigned i = 0; i < solution.numNodes(); ++i) {
>> + std::cerr << " " << i << " -> " << solution.getSelection
>> (i) << "\n";
>> + }
>> +*/
>> + pbqpAllocComplete = mapPBQPToRegAlloc(solution);
>> ++round;
>> }
>> @@ -855,7 +927,7 @@
>> node2LI.clear();
>> allowedSets.clear();
>> - DOUT << "Post alloc VirtRegMap:\n" << *vrm << "\n";
>> + DEBUG(errs() << "Post alloc VirtRegMap:\n" << *vrm << "\n");
>> // Run rewriter
>> std::auto_ptr<VirtRegRewriter> rewriter(createVirtRegRewriter());
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
> ; ModuleID = 'strtol.bc'
> target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-f32:32:32"
> target triple = "pic16-"
> @ptr = global i8* inttoptr (i64 160 to i8*), align 1 ; <i8**>
> [#uses=1]
> @main.auto.str = internal global [3 x i8] zeroinitializer ; <[3 x
> i8]*> [#uses=1]
> @.str = private constant [3 x i8] c"11\00" ; <[3 x i8]*> [#uses=1]
> @main.auto.pEnd = internal global i8* null ; <i8**> [#uses=1]
> @main.auto.li = internal global i32 0 ; <i32*> [#uses=2]
> @strtol.auto.a = internal global i32 0 ; <i32*> [#uses=4]
> @strtol.auto.c = internal global i8 0 ; <i8*> [#uses=10]
> @strtol.auto.sign = internal global i8 0 ; <i8*> [#uses=3]
>
> define i16 @main() nounwind {
> entry:
> %retval = alloca i16 ; <i16*> [#uses=2]
> store i16 0, i16* %retval
> call void @llvm.memcpy.i16(i8* getelementptr ([3 x i8]*
> @main.auto.str, i32 0, i32 0), i8* getelementptr ([3 x i8]* @.str,
> i32 0, i32 0), i16 3, i32 1)
> %call = call i32 @strtol(i8* getelementptr ([3 x i8]*
> @main.auto.str, i32 0, i32 0), i8** @main.auto.pEnd, i16 10) ;
> <i32> [#uses=1]
> store i32 %call, i32* @main.auto.li
> %tmp = load i32* @main.auto.li ; <i32> [#uses=1]
> %sub = sub i32 %tmp, 10 ; <i32> [#uses=1]
> %conv = trunc i32 %sub to i8 ; <i8> [#uses=1]
> %tmp1 = load i8** @ptr ; <i8*> [#uses=1]
> store i8 %conv, i8* %tmp1
> %0 = load i16* %retval ; <i16> [#uses=1]
> ret i16 %0
> }
>
> declare void @llvm.memcpy.i16(i8* nocapture, i8* nocapture, i16,
> i32) nounwind
>
> define i32 @strtol(i8* %s, i8** %endptr, i16 %base) nounwind {
> entry:
> br label %do.body
>
> do.body: ; preds = %do.body, %entry
> %indvar11 = phi i16 [ 0, %entry ], [ %tmp, %do.body ] ; <i16>
> [#uses=4]
> %s.addr.0 = getelementptr i8* %s, i16 %indvar11 ; <i8*> [#uses=1]
> %tmp = add i16 %indvar11, 1 ; <i16> [#uses=2]
> %ptrincdec = getelementptr i8* %s, i16 %tmp ; <i8*> [#uses=3]
> %tmp1 = load i8* %s.addr.0 ; <i8> [#uses=2]
> store i8 %tmp1, i8* @strtol.auto.c
> %call = tail call i8 @isspace(i8 %tmp1) nounwind ; <i8> [#uses=1]
> %tobool = icmp eq i8 %call, 0 ; <i1> [#uses=1]
> br i1 %tobool, label %do.end, label %do.body
>
> do.end: ; preds = %do.body
> store i32 0, i32* @strtol.auto.a
> store i8 0, i8* @strtol.auto.sign
> %tmp3 = load i8* @strtol.auto.c ; <i8> [#uses=3]
> switch i8 %tmp3, label %if.end16 [
> i8 45, label %if.then
> i8 43, label %if.then12
> ]
>
> if.then: ; preds = %do.end
> store i8 1, i8* @strtol.auto.sign
> %s.addr.0.sum13 = add i16 %indvar11, 2 ; <i16> [#uses=1]
> %ptrincdec6 = getelementptr i8* %s, i16 %s.addr.0.sum13 ; <i8*>
> [#uses=1]
> %tmp7 = load i8* %ptrincdec ; <i8> [#uses=3]
> store i8 %tmp7, i8* @strtol.auto.c
> br label %if.end16
>
> if.then12: ; preds = %do.end
> %s.addr.0.sum = add i16 %indvar11, 2 ; <i16> [#uses=1]
> %ptrincdec14 = getelementptr i8* %s, i16 %s.addr.0.sum ; <i8*>
> [#uses=1]
> %tmp15 = load i8* %ptrincdec ; <i8> [#uses=3]
> store i8 %tmp15, i8* @strtol.auto.c
> br label %if.end16
>
> if.end16: ; preds = %if.then12, %if.then, %do.end
> %tmp57.rle16 = phi i8 [ %tmp15, %if.then12 ], [ %tmp7, %if.then ],
> [ %tmp3, %do.end ] ; <i8> [#uses=1]
> %tmp17 = phi i8 [ %tmp15, %if.then12 ], [ %tmp7, %if.then ],
> [ %tmp3, %do.end ] ; <i8> [#uses=1]
> %s.addr.1 = phi i8* [ %ptrincdec6, %if.then ], [ %ptrincdec14,
> %if.then12 ], [ %ptrincdec, %do.end ] ; <i8*> [#uses=4]
> %cmp19 = icmp eq i8 %tmp17, 48 ; <i1> [#uses=1]
> br i1 %cmp19, label %if.then21, label %if.end51
>
> if.then21: ; preds = %if.end16
> %ptrincdec23 = getelementptr i8* %s.addr.1, i16 1 ; <i8*> [#uses=3]
> %tmp24 = load i8* %s.addr.1 ; <i8> [#uses=4]
> store i8 %tmp24, i8* @strtol.auto.c
> switch i16 %base, label %if.end51 [
> i16 0, label %land.lhs.true
> i16 16, label %land.lhs.true
> ]
>
> land.lhs.true: ; preds = %if.then21, %if.then21
> switch i8 %tmp24, label %if.else44 [
> i8 120, label %if.end51.thread
> i8 88, label %if.end51.thread
> ]
>
> if.end51.thread: ; preds = %land.lhs.true, %land.lhs.true
> %ptrincdec42 = getelementptr i8* %s.addr.1, i16 2 ; <i8*> [#uses=1]
> %tmp43 = load i8* %ptrincdec23 ; <i8> [#uses=2]
> store i8 %tmp43, i8* @strtol.auto.c
> br label %for.cond.preheader
>
> if.else44: ; preds = %land.lhs.true
> %cmp46 = icmp eq i16 %base, 0 ; <i1> [#uses=1]
> %.base = select i1 %cmp46, i16 8, i16 %base ; <i16> [#uses=1]
> br label %for.cond.preheader
>
> if.end51: ; preds = %if.then21, %if.end16
> %tmp57.rle15 = phi i8 [ %tmp57.rle16, %if.end16 ], [ %tmp24,
> %if.then21 ] ; <i8> [#uses=2]
> %s.addr.2 = phi i8* [ %s.addr.1, %if.end16 ], [ %ptrincdec23,
> %if.then21 ] ; <i8*> [#uses=2]
> %cmp53 = icmp eq i16 %base, 0 ; <i1> [#uses=1]
> br i1 %cmp53, label %if.then55, label %for.cond.preheader
>
> if.then55: ; preds = %if.end51
> br label %for.cond.preheader
>
> for.cond.preheader: ; preds = %if.then55, %if.end51, %if.else44,
> %if.end51.thread
> %tmp57.rle14 = phi i8 [ %tmp57.rle15, %if.then55 ], [ %tmp43,
> %if.end51.thread ], [ %tmp24, %if.else44 ], [ %tmp57.rle15,
> %if.end51 ] ; <i8> [#uses=1]
> %base.addr.1.ph = phi i16 [ %.base, %if.else44 ], [ 16,
> %if.end51.thread ], [ 10, %if.then55 ], [ %base, %if.end51 ] ;
> <i16> [#uses=2]
> %s.addr.3.ph = phi i8* [ %ptrincdec23, %if.else44 ],
> [ %ptrincdec42, %if.end51.thread ], [ %s.addr.2, %if.then55 ],
> [ %s.addr.2, %if.end51 ] ; <i8*> [#uses=2]
> %conv86 = sext i16 %base.addr.1.ph to i32 ; <i32> [#uses=1]
> br label %for.cond
>
> for.cond: ; preds = %if.end83, %for.cond.preheader
> %tmp57 = phi i8 [ %tmp57.rle14, %for.cond.preheader ], [ %tmp92,
> %if.end83 ] ; <i8> [#uses=1]
> %indvar = phi i16 [ 0, %for.cond.preheader ], [ %indvar.next,
> %if.end83 ] ; <i16> [#uses=3]
> %s.addr.3 = getelementptr i8* %s.addr.3.ph, i16 %indvar ; <i8*>
> [#uses=1]
> %call58 = tail call i8 @isalpha(i8 %tmp57) nounwind ; <i8> [#uses=1]
> %tobool59 = icmp eq i8 %call58, 0 ; <i1> [#uses=1]
> %tmp61 = load i8* @strtol.auto.c ; <i8> [#uses=2]
> br i1 %tobool59, label %if.else65, label %if.then60
>
> if.then60: ; preds = %for.cond
> %call62 = tail call i8 @toupper(i8 %tmp61) nounwind ; <i8> [#uses=1]
> %add = add i8 %call62, -55 ; <i8> [#uses=1]
> br label %if.end76
>
> if.else65: ; preds = %for.cond
> %call67 = tail call i8 @isdigit(i8 %tmp61) nounwind ; <i8> [#uses=1]
> %tobool68 = icmp eq i8 %call67, 0 ; <i1> [#uses=1]
> br i1 %tobool68, label %for.end, label %if.then69
>
> if.then69: ; preds = %if.else65
> %tmp70 = load i8* @strtol.auto.c ; <i8> [#uses=1]
> %sub72 = add i8 %tmp70, -48 ; <i8> [#uses=1]
> br label %if.end76
>
> if.end76: ; preds = %if.then69, %if.then60
> %tmp87 = phi i8 [ %add, %if.then60 ], [ %sub72, %if.then69 ] ;
> <i8> [#uses=3]
> store i8 %tmp87, i8* @strtol.auto.c
> %conv78 = sext i8 %tmp87 to i16 ; <i16> [#uses=1]
> %cmp80 = icmp slt i16 %conv78, %base.addr.1.ph ; <i1> [#uses=1]
> br i1 %cmp80, label %if.end83, label %for.end
>
> if.end83: ; preds = %if.end76
> %tmp84 = load i32* @strtol.auto.a ; <i32> [#uses=1]
> %mul = mul i32 %tmp84, %conv86 ; <i32> [#uses=1]
> %conv88 = sext i8 %tmp87 to i32 ; <i32> [#uses=1]
> %add89 = add i32 %conv88, %mul ; <i32> [#uses=1]
> store i32 %add89, i32* @strtol.auto.a
> %tmp92 = load i8* %s.addr.3 ; <i8> [#uses=2]
> store i8 %tmp92, i8* @strtol.auto.c
> %indvar.next = add i16 %indvar, 1 ; <i16> [#uses=1]
> br label %for.cond
>
> for.end: ; preds = %if.end76, %if.else65
> %tobool94 = icmp eq i8** %endptr, null ; <i1> [#uses=1]
> br i1 %tobool94, label %if.end98, label %if.then95
>
> if.then95: ; preds = %for.end
> %s.addr.3.sum = add i16 %indvar, -1 ; <i16> [#uses=1]
> %sub.ptr = getelementptr i8* %s.addr.3.ph, i16 %s.addr.3.sum ;
> <i8*> [#uses=1]
> store i8* %sub.ptr, i8** %endptr
> br label %if.end98
>
> if.end98: ; preds = %if.then95, %for.end
> %tmp99 = load i8* @strtol.auto.sign ; <i8> [#uses=1]
> %tobool100 = icmp eq i8 %tmp99, 0 ; <i1> [#uses=1]
> %tmp102 = load i32* @strtol.auto.a ; <i32> [#uses=2]
> %neg = sub i32 0, %tmp102 ; <i32> [#uses=1]
> %retval.0 = select i1 %tobool100, i32 %tmp102, i32 %neg ; <i32>
> [#uses=1]
> ret i32 %retval.0
> }
>
> define i8 @isalpha(i8 %c) nounwind {
> entry:
> %c.off = add i8 %c, -97 ; <i8> [#uses=1]
> %or.cond = icmp ugt i8 %c.off, 25 ; <i1> [#uses=1]
> br i1 %or.cond, label %lor.rhs, label %lor.end
>
> lor.rhs: ; preds = %entry
> %call = tail call i8 @isupper(i8 %c) nounwind ; <i8> [#uses=1]
> %tobool = icmp ne i8 %call, 0 ; <i1> [#uses=1]
> %phitmp = zext i1 %tobool to i8 ; <i8> [#uses=1]
> ret i8 %phitmp
>
> lor.end: ; preds = %entry
> ret i8 1
> }
>
> define i8 @isdigit(i8 %c) nounwind {
> entry:
> %cmp = icmp sgt i8 %c, 57 ; <i1> [#uses=1]
> br i1 %cmp, label %land.end, label %land.rhs
>
> land.rhs: ; preds = %entry
> %cmp4 = icmp sgt i8 %c, 47 ; <i1> [#uses=1]
> %phitmp = zext i1 %cmp4 to i8 ; <i8> [#uses=1]
> ret i8 %phitmp
>
> land.end: ; preds = %entry
> ret i8 0
> }
>
> define i8 @isspace(i8 %c) nounwind {
> entry:
> %cmp = icmp eq i8 %c, 32 ; <i1> [#uses=1]
> br i1 %cmp, label %lor.end, label %lor.rhs
>
> lor.rhs: ; preds = %entry
> %cmp4 = icmp sgt i8 %c, 13 ; <i1> [#uses=1]
> br i1 %cmp4, label %lor.end, label %land.rhs
>
> land.rhs: ; preds = %lor.rhs
> %cmp8 = icmp sgt i8 %c, 8 ; <i1> [#uses=1]
> %phitmp = zext i1 %cmp8 to i8 ; <i8> [#uses=1]
> ret i8 %phitmp
>
> lor.end: ; preds = %lor.rhs, %entry
> %0 = phi i8 [ 1, %entry ], [ 0, %lor.rhs ] ; <i8> [#uses=1]
> ret i8 %0
> }
>
> define i8 @toupper(i8 %c) nounwind {
> entry:
> %and = and i8 %c, -33 ; <i8> [#uses=1]
> %c.off = add i8 %c, -97 ; <i8> [#uses=1]
> %or.cond = icmp ugt i8 %c.off, 25 ; <i1> [#uses=1]
> %c.and = select i1 %or.cond, i8 %c, i8 %and ; <i8> [#uses=1]
> ret i8 %c.and
> }
>
> define i8 @isupper(i8 %c) nounwind {
> entry:
> %cmp = icmp sgt i8 %c, 90 ; <i1> [#uses=1]
> br i1 %cmp, label %land.end, label %land.rhs
>
> land.rhs: ; preds = %entry
> %cmp4 = icmp sgt i8 %c, 64 ; <i1> [#uses=1]
> %phitmp = zext i1 %cmp4 to i8 ; <i8> [#uses=1]
> ret i8 %phitmp
>
> land.end: ; preds = %entry
> ret i8 0
> }
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list