[llvm-commits] CVS: llvm/lib/Reoptimizer/BinInterface/select.cpp
Anand Shukla
ashukla at cs.uiuc.edu
Sat May 31 17:08:01 PDT 2003
Changes in directory llvm/lib/Reoptimizer/BinInterface:
select.cpp updated: 1.3 -> 1.4
---
Log message:
First version of working bininterface API/implementation
---
Diffs of the changes:
Index: llvm/lib/Reoptimizer/BinInterface/select.cpp
diff -u llvm/lib/Reoptimizer/BinInterface/select.cpp:1.3 llvm/lib/Reoptimizer/BinInterface/select.cpp:1.4
--- llvm/lib/Reoptimizer/BinInterface/select.cpp:1.3 Thu Apr 10 18:12:35 2003
+++ llvm/lib/Reoptimizer/BinInterface/select.cpp Sat May 31 17:07:49 2003
@@ -1,33 +1,22 @@
-//*****************************************************************************
-// SPARC Binary Manipulation Interface
+//===--------llvm/Reoptimizer/BinInterface/select.cpp-------------*- C++ -*--=//
//
// Register Allocator
-//
-// Interface Definition
-//
-//
-// 2002 Cameron Buschardt
-//*****************************************************************************
-
-
+//===----------------------------------------------------------------------===//
+#include "llvm/Reoptimizer/BinInterface/analyze.h" // SPARC analysis library
+#include "llvm/Reoptimizer/BinInterface/sparcbin.h" // Prototype for this class
+#include "llvm/Reoptimizer/BinInterface/sparcpriv.h"// Private definitions
+#include "llvm/Reoptimizer/BinInterface/sparcdis.h" // sparc disassembler
+#include "llvm/Reoptimizer/BinInterface/bitmath.h" // binary math routines
+#include "llvm/Reoptimizer/BinInterface/sparc9.h" // SPARC9 opcode definitions
+#include "llvm/Reoptimizer/BinInterface/regmask.h" // Register mask allocator
#include <stdio.h>
#include <stdlib.h>
-#include "salloc.h" // Stack allocator class
-#include "fvector.h" // fast vector (sits on stack allocator)
-#include "analyze.h" // SPARC analysis library
-#include "sparcbin.h" // Prototype for this class
-#include "sparcpriv.h" // Private definitions
-#include "regmask.h" // Register mask allocator
-
-#include "llvm/Reoptimizer/BinInterface/sparcdis.h" // prototype for sparc disassembler
-#include "llvm/Reoptimizer/BinInterface/bitmath.h" // header of optimized binary math routines
-#include "llvm/Reoptimizer/BinInterface/sparc9.h" // SPARC 9 opcode definitions
+#include <vector>
+#include <assert.h>
-#include <vector> // Use STL pair class
using std::pair;
-#include <assert.h>
//*****************************************************************************
// select(regalloc & regs)
@@ -41,111 +30,137 @@
{
regs.touched_regs = 0; // mask containing all the touched registers
regs.liveout_regs = 0; // mask of JUST liveout registers
-
+ regs.livein_regs = 0;
+
unsigned max_midx= 0; // maximal stack index that we access
// don't assign vreg of 0.
- int free_vreg = 1, s,k,i,p; // first free
+ unsigned int free_vreg = 1, s,k,i,p; // first free
// This table stores the Virtual Registers that were
// assigned to each SSA node
- fvector<unsigned> & ssa_to_vreg = regs.ssa_to_vreg;
+ vector<unsigned> & ssa_to_vreg = regs.ssa_to_vreg;
// This table has the live-range and register assignments
// for a given virtual register
- fvector<vreginfo> & vregs = regs.vregs;
+ vector<vreginfo> & vregs = regs.vregs;
// Mark everyone as having no register assigned
- ssa_to_vreg.inc(itable.size());
- for (k = 0; k<ssa_to_vreg.size(); k++)
+ //ssa_to_vreg.inc(itable.size());
+ ssa_to_vreg.resize(itable.size());
+ for (unsigned k = 0; k<itable.size(); k++)
ssa_to_vreg[k] = 0;
// Condense PHI nodes and assign virtual registers
// to PHI's ONLY
- for (s=0;s<sections.size();s++)
- for (i = begin(s); i!=end(s); i=next(i))
- {
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
-
- if (flags & IF_PHI)
- {
- for (int p=0; p< instr->phi.params->size(); p++)
- {
- int id = (*instr->phi.params)[p];
- ssa_to_vreg[id] = free_vreg;
- }
- ssa_to_vreg[i] = free_vreg;
- free_vreg++;
- }
- }
+ for (s=0;s<sections.size();s++){
+ for (i = begin(s); i!=end(s); i=next(i)){
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+
+ if (flags & IF_PHI){
+ //printf("In PHI\n");
+ for (unsigned int p=0; p< instr->phi.params->size(); p++){
+ int id = (*instr->phi.params)[p];
+ ssa_to_vreg[id] = free_vreg;
+ printf("PHI Id=%d ssa=%d vreg=%d\n", i, id, ssa_to_vreg[id]);
+ }
+ ssa_to_vreg[i] = free_vreg;
+
+ free_vreg++;
+ }
+ }
+ }
// size the vreg structures and initialize
- vregs.inc(itable.size());
- for (p = 0 ; p < free_vreg; p++)
- vregs[p].uses = vregs[p].lastuse = vregs[p].mreg = 0;
-
+ // vregs.inc(free_vreg);
+ vregs.resize(itable.size());
+ for(int x = 0, e = itable.size(); x < e; x++)
+ vregs[x].uses = vregs[x].lastuse =
+ vregs[x].mreg = 0;
+
+ for (s=0;s<sections.size();s++){
+ for (i = begin(s); i!=end(s); i=next(i)){
+ printf("SSA: %d vreg: %d\n", i, ssa_to_vreg[i]);
+ }
+ }
+
// Assign Vregs to non-phi parameters. Calculate usage information
// for ALL virtual registers. Also calculate liveout reg set
- for (s=0;s<sections.size();s++)
- for (int i = begin(s); i!=end(s); i=next(i))
- {
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
-
- if (!ssa_to_vreg[i]) //not got a vreg yet?
- {
- // allocate one
- ssa_to_vreg[i] = free_vreg;
- vregs.inc(1);
-
- vregs[free_vreg].uses =
- vregs[free_vreg].lastuse =
- vregs[free_vreg].mreg = 0;
-
- free_vreg++;
- }
-
- if (flags & IF_REGSHUFFLE)
- {
- fvector<shufflepair> * v = instr->regshuffle.shuffles;
- for (int z=0;z<v->size();z++)
- {
- int gen = (*v)[z].gen;
- int vr = ssa_to_vreg[gen];
- vregs[vr].uses++;
- vregs[vr].lastuse = i;
- regs.liveout_regs |= (1 << (*v)[z].reg); //liveout reg
- }
- continue;
- }
-
- // note since PHI nodes have been collapsed
- // through the vreg assignment. we don't need to process them! =p
- // Livein nodes are also skipped
- if (flags & (IF_ALUOP | IF_BR))
- {
- if (flags & IF_R_RS1) // do we read from RS1?
- {
- int id = ssa_to_vreg[instr->alu.genrs1];
- vregs[id].uses++;
- vregs[id].lastuse = i;
- }
- if (flags & IF_R_RS2) // do we read from RS2?
- {
- int id = ssa_to_vreg[instr->alu.genrs2];
- vregs[id].uses++;
- vregs[id].lastuse = i;
- }
- if (flags & IF_R_RD) // do we read from RD?
- {
- int id = ssa_to_vreg[instr->alu.genrd];
- vregs[id].uses++;
- vregs[id].lastuse = i;
- }
- }
- }
-
+ for (s=0;s<sections.size();s++){
+ for (unsigned int i = begin(s); i!=end(s); i=next(i)){
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+
+ if (!ssa_to_vreg[i]){ //not got a vreg yet?
+ // allocate one
+ assert(free_vreg < itable.size());
+ ssa_to_vreg[i] = free_vreg;
+ //vregs.inc(1);
+
+ vregs[free_vreg].uses =
+ vregs[free_vreg].lastuse =
+ vregs[free_vreg].mreg = 0;
+
+ printf("Assigned vreg to ssa=%d\n",i);
+ free_vreg++;
+ }
+
+ if (flags & IF_REGSHUFFLE){
+ //So this is a use, so mark the use for the associated
+ //ssa id
+ vector<shufflepair> * v = instr->regshuffle.shuffles;
+ for (unsigned int z=0; z<v->size(); z++){
+ int gen = (*v)[z].gen; //SSA id
+ //check if ssa-id still exists
+ if(itable[gen] == NULL)
+ continue;
+ int vr = ssa_to_vreg[gen];
+ //assert vr exists
+ //--Anand
+ assert(vr && "There should be a vr!");
+ vregs[vr].uses++;
+ vregs[vr].lastuse = i;
+ regs.liveout_regs |= (1 << (*v)[z].reg); //liveout reg
+ }
+ continue;
+ }
+
+ // note since PHI nodes have been collapsed
+ // through the vreg assignment. we don't need to process them! =p
+ // Livein nodes are also skipped
+ if (flags & (IF_ALUOP | IF_BR)){
+ if (flags & IF_R_RS1){ // do we read from RS1?
+ int id;
+ if(flags & IF_BR){
+ if(flags & IF_BRINTERNAL)
+ id = ssa_to_vreg[instr->ibranch.genrs1];
+ else
+ id = ssa_to_vreg[instr->ebranch.genrs1];
+ }
+ else
+ id = ssa_to_vreg[instr->alu.genrs1];
+
+ vregs[id].uses++;
+ vregs[id].lastuse = i;
+ }
+
+ if (flags & IF_R_RS2){ // do we read from RS2?
+ int id = ssa_to_vreg[instr->alu.genrs2];
+ vregs[id].uses++;
+ vregs[id].lastuse = i;
+ }
+
+ if (flags & IF_R_RD){ // do we read from RD?
+ int id = ssa_to_vreg[instr->alu.genrd];
+ vregs[id].uses++;
+ vregs[id].lastuse = i;
+ }
+
+ }
+ printf("i = %d vreg=%d free-reg=%d\n", i, ssa_to_vreg[i],free_vreg);
+ }
+ }
// register allocation state
//
@@ -153,10 +168,14 @@
// as well as the 32 generic spill slots (used for
// shuffle instructions)
//
- regmask freeregs(alloca,ROUNDUP32(itable.size())+32);
+ //regmask freeregs(alloca,ROUNDUP32(itable.size())+32);
+ regmask freeregs(ROUNDUP32(itable.size())+32);
+
unsigned hwregs[32]; // vreg index in that register
- freeregs.set32(R_ALLOCREGS); // mark candidate registers free
+
+ //Do not allocate g0, o6(SP), i6(FP)
+ freeregs.set32(R_ALLOCREGS);// mark candidate registers free
for (s = 0; s< 32; s++)
hwregs[s] = 0;
@@ -172,140 +191,193 @@
// Mark that register not free
freeregs.grabreg(mreg);
regs.touched_regs |= (1<<mreg);
+ regs.livein_regs |= (1<<mreg);
hwregs[mreg] = ssa_to_vreg[livein[p]];
- }
+ //mark last use as end of section trace --Anand
+ vregs[ssa_to_vreg[livein[p]]].lastuse = end(SECTION_TRACE);
+
+ printf("liveInId=%d vreg=%d hwreg=%d\n",livein[p], ssa_to_vreg[livein[p]], mreg);
+ }
+
+ //Allocate regs which have been "pinned" down
+ for(std::vector<unsigned int>::iterator VI = pinned.begin(),
+ VE = pinned.end();
+ VI != VE; ++VI){
+ unsigned int outReg =RD_FLD(itable[*VI]->instr, INSTR_RD);
+ vregs[ssa_to_vreg[*VI]].mreg = outReg;
+
+ freeregs.grabreg(outReg);
+ regs.touched_regs |= (1<<outReg);
+ hwregs[outReg] = ssa_to_vreg[*VI];
+ printf("pinned down: id=%d mreg=%d\n", *VI, outReg);
+ }
+
// grab our spill registers
regs.spillreg = freeregs.allocreg32();
- for (int z=0;z<32;z++)
- {
- regs.memspills[z] = freeregs.allocmemreg();
-
- unsigned midx = VREG_GETMEM(regs.memspills[z]);
- if (midx > max_midx)
- max_midx = midx;
+ for (int z=0;z<32;z++){
+ regs.memspills[z] = freeregs.allocmemreg();
+
+ unsigned midx = VREG_GETMEM(regs.memspills[z]);
+ if (midx > max_midx)
+ max_midx = midx;
}
// Iterate across instructions
- for (s=0;s<sections.size();s++)
- for (i = begin(s); i!=end(s); i=next(i))
- {
- // Find what registers this instruction depends on.
- int rs1; // this register will contain the rs1 value
- int rs2; // this register will contain the rs2 value
- int rd; // this register will contain the rd value
-
- instruction * instr = itable[i];
- unsigned flags = instr->flags;
-
-
- // make sure this is ACTUALLY an instruction and not a phi node
- if (! (flags & (IF_ALUOP | IF_BR)))
- continue;
-
- unsigned ins = instr->instr;
- // mask off and replace rs1
- if (flags & IF_R_RS1)
- {
- int vid = ssa_to_vreg[instr->alu.genrs1];
- if (vregs[vid].lastuse == i)
- {
- freeregs.freereg(vregs[vid].mreg);
-
- if (VREG_ISREG(vregs[vid].mreg))
- hwregs[vregs[vid].mreg] = 0;
- }
- }
-
- if (flags & IF_R_RS2)
- {
- int vid = ssa_to_vreg[instr->alu.genrs2];
- if (vregs[vid].lastuse == i)
- {
- freeregs.freereg(vregs[vid].mreg);
- if (VREG_ISREG(vregs[vid].mreg))
- hwregs[vregs[vid].mreg] = 0;
- }
- }
-
- if (flags & IF_R_RD)
- {
- int vid = ssa_to_vreg[instr->alu.genrd];
- if (vregs[vid].lastuse == i)
- {
- freeregs.freereg(vregs[vid].mreg);
- if (VREG_ISREG(vregs[vid].mreg))
- hwregs[vregs[vid].mreg] = 0;
- }
- }
-
- if (flags & IF_W_RD)
- {
- int id = ssa_to_vreg[i];
- int dreg = freeregs.allocreg();
-
-
- if (VREG_ISMEM(dreg))
- {
- unsigned midx = VREG_GETMEM(dreg);
-
- if (midx > max_midx)
- max_midx = midx;
-
- // Select a live range to spill
- unsigned min_cnt = 0xFFFFFFFF;
- unsigned min_idx = 0;
-
- for (int j = 0; j < 32; j++)
- {
- if (!hwregs[j])
- continue;
-
- vreginfo & v = vregs[hwregs[j]];
- if (v.uses < min_cnt)
- {
- min_cnt = v.uses;
- min_idx = j;
- }
- }
-
- // mincnt/minidx now contain the smallest allocated
-
- if (min_cnt < vregs[id].uses)
- {
- // spill using this register
- int oid = hwregs[min_idx];
- vregs[id].mreg = min_idx;
-
- assert(min_idx < 32);
- hwregs[min_idx] = id;
- vregs[oid].mreg = dreg;
- }
- else
- {
- // no spill
- vregs[id].mreg = dreg;
- }
- }
- else
- {
- regs.touched_regs |= (1<<dreg);
- assert(dreg < 32);
- hwregs[dreg] = id;
- vregs[id].mreg = dreg;
- }
-
- vregs[id].mreg = dreg;
- }
- }
-
+ for (s=0;s<sections.size();s++){
+ for (i = begin(s); i!=end(s); i=next(i)){
+ // Find what registers this instruction depends on.
+ int rs1; // this register will contain the rs1 value
+ int rs2; // this register will contain the rs2 value
+ int rd; // this register will contain the rd value
+
+ instruction * instr = itable[i];
+ unsigned flags = instr->flags;
+
+ // make sure this is ACTUALLY an instruction and not a phi node
+ if (! (flags & (IF_ALUOP | IF_BR)))
+ continue;
+
+ unsigned ins = instr->instr;
+ // mask off and replace rs1
+ if (flags & IF_R_RS1){
+ int vid;
+ if(flags & IF_BR){
+ if(flags & IF_BRINTERNAL)
+ vid = ssa_to_vreg[instr->ibranch.genrs1];
+ else
+ vid = ssa_to_vreg[instr->ebranch.genrs1];
+ }
+ else
+ vid = ssa_to_vreg[instr->alu.genrs1];
+
+ //if this is last use, free up the machine reg
+ if (vregs[vid].lastuse == i && vregs[vid].mreg != 0){
+ freeregs.freereg(vregs[vid].mreg);
+
+ if (VREG_ISREG(vregs[vid].mreg))
+ hwregs[vregs[vid].mreg] = 0;
+ }
+ }
+
+ if (flags & IF_R_RS2){
+ int vid = ssa_to_vreg[instr->alu.genrs2];
+ if (vregs[vid].lastuse == i && vregs[vid].mreg != 0){
+ freeregs.freereg(vregs[vid].mreg);
+ if (VREG_ISREG(vregs[vid].mreg))
+ hwregs[vregs[vid].mreg] = 0;
+ }
+ }
+
+ if (flags & IF_R_RD){
+ int vid = ssa_to_vreg[instr->alu.genrd];
+ if (vregs[vid].lastuse == i && vregs[vid].mreg != 0){
+ freeregs.freereg(vregs[vid].mreg);
+ if (VREG_ISREG(vregs[vid].mreg))
+ hwregs[vregs[vid].mreg] = 0;
+ }
+ }
+
+ if ((flags & IF_W_RD) || ((flags & IF_RS1_RS2_DEFINED) &&
+ !(flags & IF_BR))){
+ assert((!(flags & IF_RS1_RS2_DEFINED) ||
+ (flags & IF_RS1_RS2_DEFINED) && !(flags & IF_LIVEOUT)) &&
+ "liveout for new instructions not implemented");
+
+ bool skipIteration = false;
+ //make sure this instruction is not in pinned
+ for(std::vector<unsigned int>::iterator VI = pinned.begin(),
+ VE = pinned.end(); VI != VE; ++VI){
+ if(*VI == i){
+ skipIteration = true;
+ break;
+ }
+ }
+
+ if(vregs[ssa_to_vreg[i]].mreg)
+ skipIteration = true;
+
+ if(skipIteration){
+ printf("Before skipping\n");
+ sparc_print(instr->instr);
+ printf("\nSSAid:%u vreg:%u mreg:%u\n", i, ssa_to_vreg[i],
+ vregs[ssa_to_vreg[i]].mreg);
+ continue;
+ }
+
+ int id = ssa_to_vreg[i];
+ int dreg = freeregs.allocreg();
+
+
+ printf("instr----\n");
+ sparc_print(instr->instr);
+ printf("\nid = %d \t dreg = %d \t free= %x\n", i, dreg,
+ freeregs.free32());
+
+ if (VREG_ISMEM(dreg)){
+ //printf("Here\n");
+ //assert(0);
+ unsigned midx = VREG_GETMEM(dreg);
+
+ if (midx > max_midx)
+ max_midx = midx;
+
+ // Select a live range to spill
+ unsigned min_cnt = 0xFFFFFFFF;
+ unsigned min_idx = 0;
+
+ //select register with minimal usage
+ //Problem: it used global usage count
+ //and not usage count from HERE ON
+ for (int j = 0; j < 32; j++){
+ if (!hwregs[j])
+ continue;
+
+ vreginfo & v = vregs[hwregs[j]];
+ if (v.uses < min_cnt){
+ min_cnt = v.uses;
+ min_idx = j;
+ }
+ }
+
+ // mincnt/minidx now contain the smallest allocated
+
+ if (min_cnt < vregs[id].uses){
+ // spill using this register
+ int oid = hwregs[min_idx];
+ vregs[id].mreg = min_idx;
+
+ //printf("Min idx = %d\n", min_idx);
+
+ assert(min_idx < 32);
+ hwregs[min_idx] = id;
+ vregs[oid].mreg = dreg;
+ }
+ else{
+ // no spill
+ vregs[id].mreg = dreg;
+ }
+ }
+ else{
+ regs.touched_regs |= (1<<dreg);
+ assert(dreg < 32);
+ hwregs[dreg] = id;
+ vregs[id].mreg = dreg;
+ }
+
+ vregs[id].mreg = dreg;
+ }
+ }
+ }
+
// print register assignment
- /*for (int x=0;x<ssa_to_vreg.size();x++)
- {
- int id = ssa_to_vreg[x];
- printf("l%d: -> v%d reg=%d\n", x,id, vregs[id].mreg);
- }*/
-
+ for (s=0;s<sections.size();s++){
+ for (unsigned int i = begin(s); i!=end(s); i=next(i)){
+ printf("l%d: -> v%d reg=%d\n", i,ssa_to_vreg[i],
+ vregs[ssa_to_vreg[i]].mreg);
+ }
+ }
+
// calculate amount of stack space needed
regs.stack_size = max_midx+8;
}
More information about the llvm-commits
mailing list