ICODE::DU1 idx[][] is now an array of structures containing vectors<iICODE>, seems that while changing that some dataflow issues were fixed

This commit is contained in:
Artur K 2012-02-28 16:38:36 +01:00
parent 3cb26d99d2
commit fbf8cc3a7a
8 changed files with 239 additions and 200 deletions

View File

@ -110,6 +110,7 @@ static BB * Create(Int start, Int ip, byte nodeType, Int numOutEdges, Function *
Function *getParent() { return Parent; }
void writeBB(Int lev, Function *pProc, Int *numLoc);
BB *rmJMP(Int marker, BB *pBB);
void genDU1();
private:
Function *Parent;

View File

@ -253,9 +253,8 @@ struct DU_ICODE
std::bitset<32> def; // For Registers: position in bitset is reg index
//dword def; // For Registers: position in dword is reg index
//dword def; // For Registers: position in dword is reg index
//dword lastDefRegi; // Bit set if last def of this register in BB
std::bitset<32> use; // For Registers: position in dword is reg index
std::bitset<32> lastDefRegi;
std::bitset<32> lastDefRegi;// Bit set if last def of this register in BB
};
@ -338,6 +337,11 @@ struct LLInst : public llvm::MCInst
{
return (dst.regi==dest);
}
void set(llIcode op,uint32_t flags)
{
opcode = op;
flg =flags;
}
};
/* Icode definition: LOW_LEVEL and HIGH_LEVEL */
@ -345,9 +349,53 @@ struct ICODE
{
struct DU1
{
struct DefUse
{
int Reg; // used register
int DefLoc;
std::vector<std::list<ICODE>::iterator > useLoc; // use locations [MAX_USES]
};
struct Use
{
int Reg; // used register
std::vector<std::list<ICODE>::iterator> uses; // use locations [MAX_USES]
void removeUser(std::list<ICODE>::iterator us)
{
// ic is no no longer an user
auto iter=std::find(uses.begin(),uses.end(),us);
if(iter==uses.end())
return;
uses.erase(iter);
assert("Same user more then once!" && uses.end()==std::find(uses.begin(),uses.end(),us));
}
};
Int numRegsDef; /* # registers defined by this inst */
byte regi[MAX_REGS_DEF]; /* registers defined by this inst */
Int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
Use idx[MAX_REGS_DEF];
//Int idx[MAX_REGS_DEF][MAX_USES]; /* inst that uses this def */
bool used(int regIdx)
{
return not idx[regIdx].uses.empty();
}
int numUses(int regIdx)
{
return idx[regIdx].uses.size();
}
void recordUse(int regIdx,std::list<ICODE>::iterator location)
{
idx[regIdx].uses.push_back(location);
}
void remove(int regIdx,int use_idx)
{
idx[regIdx].uses.erase(idx[regIdx].uses.begin()+use_idx);
}
void remove(int regIdx,std::list<ICODE>::iterator ic)
{
Use &u(idx[regIdx]);
u.removeUser(ic);
}
};
icodeType type; /* Icode type */
bool invalid; /* Has no HIGH_LEVEL equivalent */
@ -382,8 +430,9 @@ struct ICODE
void setJCond(COND_EXPR *cexp);
void emitGotoLabel(Int indLevel);
void copyDU(const ICODE &duIcode, operDu _du, operDu duDu);
bool valid() {return not invalid;}
public:
boolT removeDefRegi(byte regi, Int thisDefIdx, LOCAL_ID *locId);
bool removeDefRegi(byte regi, Int thisDefIdx, LOCAL_ID *locId);
void checkHlCall();
};

View File

@ -101,10 +101,14 @@ struct ID
} id;
ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false)
{
name[0]=0;
macro[0]=0;
memset(&id,0,sizeof(id));
}
ID(hlType t, frameType f) : type(t),illegal(false),hasMacro(false)
{
name[0]=0;
macro[0]=0;
memset(&id,0,sizeof(id));
loc=f;
}

View File

@ -48,18 +48,14 @@ void ICODE::setRegDU (byte regi, operDu du_in)
case eDEF:
du.def |= duReg[regi];
du1.numRegsDef++;
// printf("%s du.def |= %x\n",__FUNCTION__,duReg[regi]);
break;
case eUSE:
du.use |= duReg[regi];
// printf("%s du.use |= %x\n",__FUNCTION__,duReg[regi]);
break;
case USE_DEF:
du.def |= duReg[regi];
du1.numRegsDef++;
// printf("%s du.def |= %x\n",__FUNCTION__,duReg[regi]);
// printf("%s du.use |= %x\n",__FUNCTION__,duReg[regi]);
du.use |= duReg[regi];
du1.numRegsDef++;
break;
case NONE: /* do nothing */
break;

View File

@ -273,14 +273,15 @@ void Function::liveRegAnalysis (std::bitset<32> &in_liveOut)
/* liveOut for this procedure */
liveOut = in_liveOut;
change = TRUE;
change = true;
while (change)
{
/* Process nodes in reverse postorder order */
change = FALSE;
for (i = numBBs; i > 0; i--)
change = false;
//for (i = numBBs; i > 0; i--)
for(auto iBB=m_dfsLast.rbegin(); iBB!=m_dfsLast.rend(); ++iBB)
{
pbb = m_dfsLast[i-1];
pbb = *iBB;//m_dfsLast[i-1];
if (pbb->flg & INVALID_BB) /* Do not process invalid BBs */
continue;
@ -361,7 +362,7 @@ void Function::liveRegAnalysis (std::bitset<32> &in_liveOut)
/* Check if live sets have been modified */
if ((prevLiveIn != pbb->liveIn) || (prevLiveOut != pbb->liveOut))
change = TRUE;
change = true;
}
}
@ -382,35 +383,26 @@ void Function::liveRegAnalysis (std::bitset<32> &in_liveOut)
}
}
/* Generates the du chain of each instruction in a basic block */
void Function::genDU1 ()
void BB::genDU1()
{
byte regi; /* Register that was defined */
Int i, k, defRegIdx, useIdx;
iICODE picode, ticode,lastInst;/* Current and target bb */
BB * pbb, *tbb; /* Current and target basic block */
Int k, defRegIdx, useIdx;
iICODE picode, ticode,lastInst;
BB *tbb; /* Target basic block */
bool res;
//COND_EXPR *exp, *lhs;
/* Traverse tree in dfsLast order */
assert(m_dfsLast.size()==numBBs);
for (i = 0; i < numBBs; i++)
{
pbb = m_dfsLast[i];
if (pbb->flg & INVALID_BB)
continue;
//COND_EXPR *e
/* Process each register definition of a HIGH_LEVEL icode instruction.
* Note that register variables should not be considered registers.
*/
lastInst = pbb->end2();
for (picode = pbb->begin2(); picode != lastInst; picode++)
assert(0!=Parent);
lastInst = this->end2();
for (picode = this->begin2(); picode != lastInst; picode++)
{
if (picode->type != HIGH_LEVEL)
continue;
regi = 0;
defRegIdx = 0;
// foreach defined register
for (k = 0; k < INDEXBASE; k++)
{
if (not picode->du.def.test(k))
@ -431,27 +423,24 @@ void Function::genDU1 ()
for (auto ricode = ++iICODE(picode); ricode != lastInst; ricode++)
{
ticode=ricode;
/* Only check uses of HIGH_LEVEL icodes */
if (ricode->type == HIGH_LEVEL)
{
if (ricode->type != HIGH_LEVEL) // Only check uses of HIGH_LEVEL icodes
continue;
/* if used, get icode index */
if ((ricode->du.use & duReg[regi]).any())
picode->du1.idx[defRegIdx][useIdx++] = ricode->loc_ip;
picode->du1.recordUse(defRegIdx,ricode);
/* if defined, stop finding uses for this reg */
if ((ricode->du.def & duReg[regi]).any())
break;
}
}
/* Check if last definition of this register */
if ((not (ticode->du.def & duReg[regi]).any()) and (pbb->liveOut & duReg[regi]).any())
if ((not (ticode->du.def & duReg[regi]).any()) and (this->liveOut & duReg[regi]).any())
picode->du.lastDefRegi |= duReg[regi];
}
else /* only 1 instruction in this basic block */
{
/* Check if last definition of this register */
if ((pbb->liveOut & duReg[regi]).any())
if ((this->liveOut & duReg[regi]).any())
picode->du.lastDefRegi |= duReg[regi];
}
@ -462,16 +451,14 @@ void Function::genDU1 ()
if ((picode->ic.hl.opcode == HLI_CALL) &&
(picode->ic.hl.oper.call.proc->flg & PROC_IS_FUNC))
{
tbb = pbb->edges[0].BBptr;
useIdx = 0;
tbb = this->edges[0].BBptr;
for (ticode = tbb->begin2(); ticode != tbb->end2(); ticode++)
{
if (ticode->type != HIGH_LEVEL)
continue;
/* if used, get icode index */
if ((ticode->du.use & duReg[regi]).any())
picode->du1.idx[defRegIdx][useIdx++] = ticode->loc_ip;
picode->du1.recordUse(defRegIdx,ticode);
/* if defined, stop finding uses for this reg */
if ((ticode->du.def & duReg[regi]).any())
break;
@ -480,8 +467,7 @@ void Function::genDU1 ()
/* if not used in this basic block, check if the
* register is live out, if so, make it the last
* definition of this register */
if ((picode->du1.idx[defRegIdx][useIdx] == 0) &&
(tbb->liveOut & duReg[regi]).any())
if ( picode->du1.used(defRegIdx) && (tbb->liveOut & duReg[regi]).any())
picode->du.lastDefRegi |= duReg[regi];
}
@ -491,36 +477,25 @@ void Function::genDU1 ()
* from a library function (routines such as printf
* return an integer, which is normally not taken into
* account by the programmer). */
if ((picode->invalid == FALSE) &&
(picode->du1.idx[defRegIdx][0] == 0) &&
if (picode->valid() and not picode->du1.used(defRegIdx) and
(not (picode->du.lastDefRegi & duReg[regi]).any()) &&
//(! ((picode->ic.hl.opcode != HLI_CALL) &&
(not ((picode->ic.hl.opcode == HLI_CALL) &&
(picode->ic.hl.oper.call.proc->flg & PROC_ISLIB))))
{
if (! (pbb->liveOut & duReg[regi]).any()) /* not liveOut */
if (! (this->liveOut & duReg[regi]).any()) /* not liveOut */
{
res = picode->removeDefRegi (regi, defRegIdx+1,&localId);
res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId);
if (res != true)
{
defRegIdx++;
continue;
}
/* Backpatch any uses of this instruction, within
* the same BB, if the instruction was invalidated */
if (res == TRUE)
for (auto ticode = riICODE(picode); ticode != pbb->rend2(); ticode++)
for (auto ticode = riICODE(picode); ticode != this->rend2(); ticode++)
{
for (int n = 0; n < MAX_USES; n++)
{
if (ticode->du1.idx[0][n] == picode->loc_ip)
{
if (n < MAX_USES - 1)
{
memmove (&ticode->du1.idx[0][n],
&ticode->du1.idx[0][n+1],
(size_t)((MAX_USES - n - 1) * sizeof(Int)));
n--;
}
ticode->du1.idx[0][MAX_USES - 1] = 0;
}
}
ticode->du1.remove(0,picode);
}
}
else /* liveOut */
@ -529,12 +504,29 @@ void Function::genDU1 ()
defRegIdx++;
/* Check if all defined registers have been processed */
if ((defRegIdx >= picode->du1.numRegsDef) ||
(defRegIdx == MAX_REGS_DEF))
if ((defRegIdx >= picode->du1.numRegsDef) || (defRegIdx == MAX_REGS_DEF))
break;
}
}
}
/* Generates the du chain of each instruction in a basic block */
void Function::genDU1 ()
{
byte regi; /* Register that was defined */
Int i, k, defRegIdx, useIdx;
iICODE picode, ticode,lastInst;/* Current and target bb */
BB * pbb, *tbb; /* Current and target basic block */
bool res;
//COND_EXPR *exp, *lhs;
/* Traverse tree in dfsLast order */
assert(m_dfsLast.size()==numBBs);
for(BB *pbb : m_dfsLast)
{
if (pbb->flg & INVALID_BB)
continue;
pbb->genDU1();
}
}
@ -605,7 +597,7 @@ static void forwardSubsLong (Int longIdx, COND_EXPR *exp, ICODE * picode,
/* Returns whether the elements of the expression rhs are all x-clear from
* instruction f up to instruction t. */
static boolT xClear (COND_EXPR *rhs, iICODE f, Int t, iICODE lastBBinst, Function * pproc)
static boolT xClear (COND_EXPR *rhs, iICODE f, iICODE t, iICODE lastBBinst, Function * pproc)
{
iICODE i;
boolT res;
@ -620,7 +612,7 @@ static boolT xClear (COND_EXPR *rhs, iICODE f, Int t, iICODE lastBBinst, Functio
if (rhs->expr.ident.idType == REGISTER)
{
regi= pproc->localId.id_arr[rhs->expr.ident.idNode.regiIdx].id.regi;
for (i = ++iICODE(f); (i != lastBBinst) && (i->loc_ip < t); i++)
for (i = ++iICODE(f); (i != lastBBinst) && (i!=t); i++)
if ((i->type == HIGH_LEVEL) && ( not i->invalid ))
{
if ((i->du.def & duReg[regi]).any())
@ -728,8 +720,7 @@ void Function::findExps()
/* Check for only one use of this register. If this is
* the last definition of the register in this BB, check
* that it is not liveOut from this basic block */
if ((picode->du1.idx[0][0] != 0) &&
(picode->du1.idx[0][1] == 0))
if (picode->du1.numUses(0)==1)
{
/* Check that this register is not liveOut, if it
* is the last definition of the register */
@ -741,15 +732,14 @@ void Function::findExps()
case HLI_ASSIGN:
/* Replace rhs of current icode into target
* icode expression */
ticode = Icode.begin();
advance(ticode,picode->du1.idx[0][0]);
ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi & duReg[regi]).any() &&
((ticode->ic.hl.opcode != HLI_CALL) &&
(ticode->ic.hl.opcode != HLI_RET)))
continue;
if (xClear (picode->ic.hl.oper.asgn.rhs, picode,
picode->du1.idx[0][0], lastInst, this))
picode->du1.idx[0].uses[0], lastInst, this))
{
switch (ticode->ic.hl.opcode) {
case HLI_ASSIGN:
@ -782,8 +772,7 @@ void Function::findExps()
break;
case HLI_POP:
ticode = Icode.begin();
advance(ticode,picode->du1.idx[0][0]);
ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi & duReg[regi]).any() &&
((ticode->ic.hl.opcode != HLI_CALL) &&
(ticode->ic.hl.opcode != HLI_RET)))
@ -818,8 +807,7 @@ void Function::findExps()
break;
case HLI_CALL:
ticode = Icode.begin();
advance(ticode,picode->du1.idx[0][0]);
ticode = picode->du1.idx[0].uses.front();
switch (ticode->ic.hl.opcode) {
case HLI_ASSIGN:
exp = COND_EXPR::idFunc (
@ -877,19 +865,15 @@ void Function::findExps()
else if (picode->du1.numRegsDef == 2) /* long regs */
{
/* Check for only one use of these registers */
if ((picode->du1.idx[0][0] != 0) &&
(picode->du1.idx[0][1] == 0) &&
(picode->du1.idx[1][0] != 0) &&
(picode->du1.idx[1][1] == 0))
if ((picode->du1.numUses(0) == 1) and (picode->du1.numUses(1) == 1))
{
switch (picode->ic.hl.opcode) {
case HLI_ASSIGN:
/* Replace rhs of current icode into target
* icode expression */
if (picode->du1.idx[0][0] == picode->du1.idx[1][0])
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
{
ticode = Icode.begin();
advance(ticode,picode->du1.idx[0][0]);
ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi & duReg[regi]).any() &&
((ticode->ic.hl.opcode != HLI_CALL) &&
(ticode->ic.hl.opcode != HLI_RET)))
@ -924,10 +908,9 @@ void Function::findExps()
break;
case HLI_POP:
if (picode->du1.idx[0][0] == picode->du1.idx[1][0])
if (picode->du1.idx[0].uses[0] == picode->du1.idx[1].uses[0])
{
ticode = Icode.begin();
advance(ticode,picode->du1.idx[0][0]);
ticode = picode->du1.idx[0].uses.front();
if ((picode->du.lastDefRegi & duReg[regi]).any() &&
((ticode->ic.hl.opcode != HLI_CALL) &&
(ticode->ic.hl.opcode != HLI_RET)))
@ -956,8 +939,7 @@ void Function::findExps()
break;
case HLI_CALL: /* check for function return */
ticode = Icode.begin();
advance(ticode,picode->du1.idx[0][0]);
ticode = picode->du1.idx[0].uses.front();
switch (ticode->ic.hl.opcode)
{
case HLI_ASSIGN:
@ -1069,13 +1051,11 @@ void Function::findExps()
* assign it to the corresponding registers */
if ((picode->ic.hl.opcode == HLI_CALL) &&
((picode->ic.hl.oper.call.proc->flg & PROC_ISLIB) !=
PROC_ISLIB) && (picode->du1.idx[0][0] == 0) &&
PROC_ISLIB) && (not picode->du1.used(0)) &&
(picode->du1.numRegsDef > 0))
{
exp = COND_EXPR::idFunc (picode->ic.hl.oper.call.proc,
picode->ic.hl.oper.call.args);
lhs = COND_EXPR::idID (&picode->ic.hl.oper.call.proc->retVal,
&localId, picode/*picode->loc_ip*/);
exp = COND_EXPR::idFunc (picode->ic.hl.oper.call.proc, picode->ic.hl.oper.call.args);
lhs = COND_EXPR::idID (&picode->ic.hl.oper.call.proc->retVal, &localId, picode);
picode->setAsgn(lhs, exp);
}
}

View File

@ -90,19 +90,30 @@ void ICODE ::invalidate()
}
/* Removes the defined register regi from the lhs subtree. If all registers
* of this instruction are unused, the instruction is invalidated (ie.
* removed) */
boolT ICODE::removeDefRegi (byte regi, Int thisDefIdx, LOCAL_ID *locId)
/* Removes the defined register regi from the lhs subtree.
* If all registers
* of this instruction are unused, the instruction is invalidated (ie. removed)
*/
bool ICODE::removeDefRegi (byte regi, Int thisDefIdx, LOCAL_ID *locId)
{
Int numDefs;
numDefs = du1.numRegsDef;
// if (numDefs == thisDefIdx)
// {
// for ( ; numDefs > 0; numDefs--)
// {
// if ((du1.idx[numDefs-1][0] != 0)||(du.lastDefRegi.any()))
// break;
// }
// }
if (numDefs == thisDefIdx)
{
for ( ; numDefs > 0; numDefs--)
{
if ((du1.idx[numDefs-1][0] != 0)||(du.lastDefRegi.any()))
if (du1.used(numDefs-1)||(du.lastDefRegi[regi]))
break;
}
}
@ -478,14 +489,12 @@ void ICODE::writeDU(Int idx)
printf ("# regs defined = %d\n", du1.numRegsDef);
for (i = 0; i < MAX_REGS_DEF; i++)
{
if (du1.idx[i][0] != 0)
if (du1.used(i))
{
printf ("%d: du1[%d][] = ", idx, i);
for (j = 0; j < MAX_USES; j++)
for(std::list<ICODE>::iterator j : du1.idx[i].uses)
{
if (du1.idx[i][j] == 0)
break;
printf ("%d ", du1.idx[i][j]);
printf ("%d ", j->loc_ip);
}
printf ("\n");
}

View File

@ -154,8 +154,7 @@ void Function::FollowCtrl(CALL_GRAPH * pcallGraph, STATE *pstate)
if (Icode.end()!=labLoc)
{ /* Synthetic jump */
_Icode.type = LOW_LEVEL;
_Icode.ic.ll.opcode = iJMP;
_Icode.ic.ll.flg = I | SYNTHETIC | NO_OPS;
_Icode.ic.ll.set(iJMP,I | SYNTHETIC | NO_OPS);
_Icode.ic.ll.src.SetImmediateOp(labLoc->GetLlLabel());
_Icode.ic.ll.label = SynthLab++;
}
@ -882,6 +881,7 @@ static void setBits(int16 type, dword start, dword len)
/* DU bit definitions for each reg value - including index registers */
std::bitset<32> duReg[] = { 0x00,
//AH AL . . AX, BH
0x11001, 0x22002, 0x44004, 0x88008, /* word regs */
0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800, /* seg regs */