[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

Sanjiv Gupta sanjiv.gupta at microchip.com
Tue Aug 11 21:57:30 PDT 2009


Evan Cheng wrote:
> I somehow doubt PBQP is very good fit for a single register target.
>
> Evan
>   
Well, it has been working for us and slightly better than the default one.
Eventually what I feel that we will need to write one of our own, but 
currently pbqp is just fine for us.
To give you more food for thought, here is some data that we got on our 
own tests.

codegen with default regalloc:

Number of tests passed: 425
Total code size is: 234624
Total data size is: 21547

While the results with PBQP are as:

Number of tests passed: 425
Total code size is: 230584
Total data size is: 21278

- Sanjiv




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