diff --git a/include/BasicBlock.h b/include/BasicBlock.h index ffbb7a4..acd0cd2 100644 --- a/include/BasicBlock.h +++ b/include/BasicBlock.h @@ -122,7 +122,10 @@ public: { edges[0].ip = ip; } + void RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode); private: + bool FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at); + void ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode); bool isEndOfPath(int latch_node_idx) const; Function *Parent; diff --git a/src/dataflow.cpp b/src/dataflow.cpp index 6e2692e..291b898 100644 --- a/src/dataflow.cpp +++ b/src/dataflow.cpp @@ -397,129 +397,137 @@ void Function::liveRegAnalysis (std::bitset<32> &in_liveOut) } } +/* Check remaining instructions of the BB for all uses + * of register regi, before any definitions of the + * register */ +bool BB::FindUseBeforeDef(eReg regi, int defRegIdx, iICODE start_at) +{ + if ((regi == rDI) && (flg & DI_REGVAR)) + return true; + if ((regi == rSI) && (flg & SI_REGVAR)) + return true; + if (distance(start_at,end())>1) /* several instructions */ + { + iICODE ticode=end(); + auto hl_range=make_iterator_range(start_at,end()) | filtered(ICODE::select_high_level); + auto checked_icode=hl_range.begin(); + ++checked_icode; + for (; checked_icode != hl_range.end(); checked_icode++) + { + if (checked_icode->type != HIGH_LEVEL) // Only check uses of HIGH_LEVEL icodes + continue; + /* if used, get icode index */ + if ((checked_icode->du.use & duReg[regi]).any()) + start_at->du1.recordUse(defRegIdx,checked_icode.base()); + /* if defined, stop finding uses for this reg */ + if ((checked_icode->du.def & duReg[regi]).any()) + { + ticode=checked_icode.base(); + break; + } + } + if(ticode==end()) + ticode=(++riICODE(rbegin())).base(); + + /* Check if last definition of this register */ + if ((not (ticode->du.def & duReg[regi]).any()) and (liveOut & duReg[regi]).any()) + start_at->du.lastDefRegi |= duReg[regi]; + } + else /* only 1 instruction in this basic block */ + { + /* Check if last definition of this register */ + if ((liveOut & duReg[regi]).any()) + start_at->du.lastDefRegi |= duReg[regi]; + } + return false; +} +/* Find target icode for HLI_CALL icodes to procedures + * that are functions. The target icode is in the + * next basic block (unoptimized code) or somewhere else + * on optimized code. */ +void BB::ProcessUseDefForFunc(eReg regi, int defRegIdx, iICODE picode) +{ + if ((picode->hl()->opcode == HLI_CALL) && + (picode->hl()->call.proc->flg & PROC_IS_FUNC)) + { + BB *tbb = this->edges[0].BBptr; + auto target_instructions = tbb->instructions | filtered(ICODE::select_high_level); + for (auto iter=target_instructions.begin(); iter!=target_instructions.end(); ++iter) + { + /* if used, get icode index */ + if ((iter->du.use & duReg[regi]).any()) + picode->du1.recordUse(defRegIdx,iter.base()); + /* if defined, stop finding uses for this reg */ + if ((iter->du.def & duReg[regi]).any()) + break; + } + + /* 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.used(defRegIdx) && (tbb->liveOut & duReg[regi]).any()) + picode->du.lastDefRegi |= duReg[regi]; + } +} +/* If not used within this bb or in successors of this + * bb (ie. not in liveOut), then register is useless, + * thus remove it. Also check that this is not a return + * from a library function (routines such as printf + * return an integer, which is normally not taken into + * account by the programmer). */ +void BB::RemoveUnusedDefs(eReg regi, int defRegIdx, iICODE picode) +{ + if (picode->valid() and not picode->du1.used(defRegIdx) and + (not (picode->du.lastDefRegi & duReg[regi]).any()) && + (not ((picode->hl()->opcode == HLI_CALL) && + (picode->hl()->call.proc->flg & PROC_ISLIB)))) + { + if (! (this->liveOut & duReg[regi]).any()) /* not liveOut */ + { + bool res = picode->removeDefRegi (regi, defRegIdx+1,&Parent->localId); + if (res == true) + { + + /* Backpatch any uses of this instruction, within + * the same BB, if the instruction was invalidated */ + rICODE the_rest(begin(),picode); + for ( ICODE &back_patch_at : the_rest|reversed) + { + back_patch_at.du1.remove(0,picode); + } + } + } + else /* liveOut */ + picode->du.lastDefRegi |= duReg[regi]; + } +} + void BB::genDU1() { - eReg regi; /* Register that was defined */ - int k, defRegIdx, useIdx; - iICODE picode, ticode,lastInst; - BB *tbb; /* Target basic block */ - bool res; - //COND_EXPR *e /* Process each register definition of a HIGH_LEVEL icode instruction. * Note that register variables should not be considered registers. */ assert(0!=Parent); - lastInst = this->end(); - ICODE::TypeFilter zq; - auto all_high_levels = instructions | filtered(zq); + ICODE::TypeFilter select_high_level; + auto all_high_levels = instructions | filtered(select_high_level); printf("\n"); for (auto picode=all_high_levels.begin(); picode!=all_high_levels.end(); ++picode) { -// if (picode->type != HIGH_LEVEL) -// continue; - regi = rUNDEF; - defRegIdx = 0; + int defRegIdx = 0; // foreach defined register - bitset<32> processed=0; - for (k = 0; k < INDEX_BX_SI; k++) + for (int k = 0; k < INDEX_BX_SI; k++) { if (not picode->du.def.test(k)) continue; - //printf("Processing reg") - processed |= duReg[k]; - regi = (eReg)(k + 1); /* defined register */ + eReg regi = (eReg)(k + 1); /* Register that was defined */ picode->du1.regi[defRegIdx] = regi; - /* Check remaining instructions of the BB for all uses - * of register regi, before any definitions of the - * register */ - if ((regi == rDI) && (flg & DI_REGVAR)) + if(FindUseBeforeDef(regi,defRegIdx, picode.base())) continue; - if ((regi == rSI) && (flg & SI_REGVAR)) - continue; - if (distance(picode,all_high_levels.end())>1) /* several instructions */ - { - useIdx = 0; - for (auto ricode = ++iICODE(picode.base()); ricode != lastInst; ricode++) - { - ticode=ricode; - 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.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 (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 ((this->liveOut & duReg[regi]).any()) - picode->du.lastDefRegi |= duReg[regi]; - } - /* Find target icode for HLI_CALL icodes to procedures - * that are functions. The target icode is in the - * next basic block (unoptimized code) or somewhere else - * on optimized code. */ - if ((picode->hl()->opcode == HLI_CALL) && - (picode->hl()->call.proc->flg & PROC_IS_FUNC)) - { - tbb = this->edges[0].BBptr; - for (ticode = tbb->begin(); ticode != tbb->end(); ticode++) - { - if (ticode->type != HIGH_LEVEL) - continue; - /* if used, get icode index */ - if ((ticode->du.use & duReg[regi]).any()) - picode->du1.recordUse(defRegIdx,ticode); - /* if defined, stop finding uses for this reg */ - if ((ticode->du.def & duReg[regi]).any()) - break; - } + ProcessUseDefForFunc(regi, defRegIdx,picode.base()); + RemoveUnusedDefs(regi, defRegIdx, picode.base()); - /* 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.used(defRegIdx) && (tbb->liveOut & duReg[regi]).any()) - picode->du.lastDefRegi |= duReg[regi]; - } - - /* If not used within this bb or in successors of this - * bb (ie. not in liveOut), then register is useless, - * thus remove it. Also check that this is not a return - * from a library function (routines such as printf - * return an integer, which is normally not taken into - * account by the programmer). */ - if (picode->valid() and not picode->du1.used(defRegIdx) and - (not (picode->du.lastDefRegi & duReg[regi]).any()) && - (not ((picode->hl()->opcode == HLI_CALL) && - (picode->hl()->call.proc->flg & PROC_ISLIB)))) - { - if (! (this->liveOut & duReg[regi]).any()) /* not liveOut */ - { - 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 */ - for (auto back_patch_at = riICODE(picode.base()); back_patch_at != rend(); back_patch_at++) - { - back_patch_at->du1.remove(0,picode.base()); - } - } - else /* liveOut */ - picode->du.lastDefRegi |= duReg[regi]; - } defRegIdx++; /* Check if all defined registers have been processed */ @@ -533,16 +541,13 @@ void Function::genDU1 () { /* Traverse tree in dfsLast order */ assert(m_dfsLast.size()==numBBs); - for(BB *pbb : m_dfsLast) + for(BB *pbb : m_dfsLast | filtered(BB::ValidFunctor())) { - if (pbb->flg & INVALID_BB) - continue; pbb->genDU1(); } } - /* Substitutes the rhs (or lhs if rhs not possible) of ticode for the rhs * of picode. */ void LOCAL_ID::forwardSubs (COND_EXPR *lhs, COND_EXPR *rhs, iICODE picode, iICODE ticode, int &numHlIcodes) const diff --git a/src/locident.cpp b/src/locident.cpp index 18df39b..7dd5477 100644 --- a/src/locident.cpp +++ b/src/locident.cpp @@ -12,7 +12,7 @@ bool LONGID_TYPE::srcDstRegMatch(iICODE a, iICODE b) const { return (a->ll()->src().getReg2()==l) and (b->ll()->dst.getReg2()==h); } - + ID::ID() : type(TYPE_UNKNOWN),illegal(false),loc(STK_FRAME),hasMacro(false) { @@ -278,7 +278,7 @@ int LOCAL_ID::newLongStk(hlType t, int offH, int offL) int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, iICODE atOffset) { size_t idx; - LLOperand *pmH, *pmL; + const LLOperand *pmH, *pmL; LLInst &p_ll(*pIcode->ll()); if (f == LOW_FIRST) { @@ -334,7 +334,8 @@ int LOCAL_ID::newLong(opLoc sd, iICODE pIcode, hlFirst f, iICODE ix,operDu du, i * rhs, lhs : return expressions if successful. */ boolT checkLongEq (LONG_STKID_TYPE longId, iICODE pIcode, int i, Function * pProc, Assignment &asgn, iICODE atOffset) { - LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc; /* pointers to LOW_LEVEL icodes */ + /* pointers to LOW_LEVEL icodes */ + const LLOperand *pmHdst, *pmLdst, *pmHsrc, *pmLsrc; pmHdst = &pIcode->ll()->dst; pmLdst = &atOffset->ll()->dst;