-
Notifications
You must be signed in to change notification settings - Fork 0
Updated ruleBlockIfNoExit to better select branch if both are noexit. #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1323,6 +1323,20 @@ void BlockGraph::restoreXmlBody(List::const_iterator &iter,List::const_iterator | |
| } | ||
| } | ||
|
|
||
| int4 BlockGraph::getInnerBlockDepth(void) | ||
|
|
||
| { | ||
| int4 depth; | ||
| int4 maxDepth = 0; | ||
| for(int4 i=0;i<list.size();++i){ | ||
| depth = list[i]->getBlockDepth(); | ||
| if(depth>maxDepth){ | ||
| maxDepth=depth; | ||
| } | ||
| } | ||
| return maxDepth; | ||
| } | ||
|
|
||
| /// This is currently just a wrapper around the FlowBlock::restoreXml() | ||
| /// that sets of the BlockMap resolver | ||
| /// \param el is the root \<block> tag | ||
|
|
@@ -2505,6 +2519,12 @@ bool BlockBasic::isDoNothing(void) const | |
| return hasOnlyMarkers(); | ||
| } | ||
|
|
||
| int4 BlockBasic::getOpSize(void) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| { | ||
| return op.size(); | ||
| } | ||
|
|
||
| /// In terms of machine instructions, a basic block always covers a range of addresses, | ||
| /// from its first instruction to its last. This method establishes that range. | ||
| /// \param beg is the address of the first instruction in the block | ||
|
|
@@ -2747,6 +2767,13 @@ FlowBlock *BlockList::getSplitPoint(void) | |
| return getBlock(getSize()-1)->getSplitPoint(); | ||
| } | ||
|
|
||
| int4 BlockList::getBlockDepth(void) | ||
|
|
||
| { | ||
| // list join block together but don't increase block depth | ||
| return getInnerBlockDepth(); | ||
| } | ||
|
|
||
| void BlockList::printHeader(ostream &s) const | ||
|
|
||
| { | ||
|
|
@@ -2831,6 +2858,13 @@ void BlockCondition::saveXmlHeader(ostream &s) const | |
| a_v(s,"opcode",nm); | ||
| } | ||
|
|
||
| int4 BlockCondition::getBlockDepth(void) | ||
|
|
||
| { | ||
| // conditions join block together but don't increase block depth | ||
| return getInnerBlockDepth(); | ||
| } | ||
|
|
||
| void BlockIf::markUnstructured(void) | ||
|
|
||
| { | ||
|
|
@@ -3185,6 +3219,18 @@ FlowBlock *BlockSwitch::nextFlowAfter(const FlowBlock *bl) const | |
| return getParent()->nextFlowAfter(this); | ||
| } | ||
|
|
||
| int4 BlockSwitch::getBlockDepth(void){ | ||
| int4 i; | ||
| int4 maxDepth=0; | ||
| for(i=0;i<caseblocks.size();++i){ | ||
| int4 depth=caseblocks[i].block->getBlockDepth(); | ||
| if(depth>maxDepth){ | ||
| maxDepth=depth; | ||
| } | ||
| } | ||
| return maxDepth+2; // +1 for switch block and +1 for case/default block | ||
| } | ||
|
Comment on lines
+3222
to
+3232
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function's implementation can be improved for readability and consistency.
int4 BlockSwitch::getBlockDepth(void)
{
int4 maxDepth = 0;
for (const auto &caseblock : caseblocks) {
const int4 depth = caseblock.block->getBlockDepth();
if (depth > maxDepth) {
maxDepth = depth;
}
}
return maxDepth + 2; // +1 for switch block and +1 for case/default block
} |
||
|
|
||
| BlockMap::BlockMap(const BlockMap &op2) | ||
|
|
||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -181,6 +181,7 @@ public: | |
| /// \param enditer marks the end of the XML tags | ||
| /// \param resolver is used to recover FlowBlock objects based on XML references | ||
| virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver) {} | ||
| virtual int4 getBlockDepth(void) {return 0;} ///< Return the depth in code block of \b this | ||
| void saveXmlEdges(ostream &s) const; ///< Save edge information to an XML stream | ||
| void restoreXmlEdges(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver); | ||
| void saveXml(ostream &s) const; ///< Write out \b this to an XML stream | ||
|
|
@@ -299,6 +300,8 @@ public: | |
| virtual void finalizePrinting(const Funcdata &data) const; | ||
| virtual void saveXmlBody(ostream &s) const; | ||
| virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver); | ||
| virtual int4 getInnerBlockDepth(); ///< Return max depth of child blocks | ||
| virtual int4 getBlockDepth() {return getInnerBlockDepth()+1;} | ||
| void restoreXml(const Element *el,const AddrSpaceManager *m); ///< Restore \b this BlockGraph from an XML stream | ||
| void addEdge(FlowBlock *begin,FlowBlock *end); ///< Add a directed edge between component FlowBlocks | ||
| void addLoopEdge(FlowBlock *begin,int4 outindex); ///< Mark a given edge as a \e loop edge | ||
|
|
@@ -401,6 +404,7 @@ public: | |
| list<PcodeOp *>::const_iterator beginOp(void) const { return op.begin(); } ///< Return an iterator to the beginning of the PcodeOps | ||
| list<PcodeOp *>::const_iterator endOp(void) const { return op.end(); } ///< Return an iterator to the end of the PcodeOps | ||
| bool emptyOp(void) const { return op.empty(); } ///< Return \b true if \b block contains no operations | ||
| int4 getOpSize(void); ///< Number of PcodeOps contained in \b this block | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The int4 getOpSize(void) const; ///< Number of PcodeOps contained in \b this block |
||
| static bool noInterveningStatement(PcodeOp *first,int4 path,PcodeOp *last); | ||
| }; | ||
|
|
||
|
|
@@ -501,6 +505,7 @@ public: | |
| virtual PcodeOp *lastOp(void) const; | ||
| virtual bool negateCondition(bool toporbottom); | ||
| virtual FlowBlock *getSplitPoint(void); | ||
| virtual int4 getBlockDepth(void); | ||
| }; | ||
|
|
||
| /// \brief Two conditional blocks combined into one conditional using BOOL_AND or BOOL_OR | ||
|
|
@@ -530,6 +535,7 @@ public: | |
| virtual bool isComplex(void) const { return getBlock(0)->isComplex(); } | ||
| virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const; | ||
| virtual void saveXmlHeader(ostream &s) const; | ||
| virtual int4 getBlockDepth(void); | ||
| }; | ||
|
|
||
| /// \brief A basic "if" block | ||
|
|
@@ -675,6 +681,7 @@ public: | |
| virtual void emit(PrintLanguage *lng) const { lng->emitBlockSwitch(this); } | ||
| virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const; | ||
| virtual void finalizePrinting(const Funcdata &data) const; | ||
| virtual int4 getBlockDepth(void); | ||
| }; | ||
|
|
||
| /// \brief Helper class for resolving cross-references while deserializing BlockGraph objects | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1463,6 +1463,7 @@ bool CollapseStructure::ruleBlockIfNoExit(FlowBlock *bl) | |
| { | ||
| FlowBlock *clauseblock; | ||
| int4 i; | ||
| int4 bestIndex=-1; | ||
|
|
||
| if (bl->sizeOut() != 2) return false; // Must be binary condition | ||
| if (bl->isSwitchOut()) return false; | ||
|
|
@@ -1480,15 +1481,56 @@ bool CollapseStructure::ruleBlockIfNoExit(FlowBlock *bl) | |
| // bl->setGotoBranch(i); | ||
| // return true; | ||
| // } | ||
| if (bestIndex==-1){ | ||
| bestIndex=i; | ||
| }else{ // both match | ||
| bestIndex = selectBestNoExit(bl->getOut(0),bl->getOut(1)); | ||
| } | ||
| } | ||
| if(bestIndex==-1) return false; // no match | ||
| clauseblock = bl->getOut(bestIndex); | ||
| if (bestIndex==0) { // clause must be true out of bl | ||
| if (bl->negateCondition(true)) | ||
| dataflow_changecount += 1; | ||
| } | ||
| graph.newBlockIf(bl,clauseblock); | ||
| return true; | ||
| } | ||
|
|
||
| if (i==0) { // clause must be true out of bl | ||
| if (bl->negateCondition(true)) | ||
| dataflow_changecount += 1; | ||
| /// Select the best of two NoExit branch to be collapsed by ruleBlockIfNoExit. | ||
| /// \param clause0 is the first NoExit branch | ||
| /// \param clause1 is the second NoExit branch | ||
| /// \return the index of the selected branch (0 or 1) | ||
| int4 CollapseStructure::selectBestNoExit(FlowBlock *clause0,FlowBlock *clause1) | ||
|
|
||
| { | ||
| // select lowest block depth | ||
| int4 depth0 = clause0->getBlockDepth(); | ||
| int4 depth1 = clause1->getBlockDepth(); | ||
| if (depth0<depth1)return 0; | ||
| if (depth1<depth0)return 1; | ||
|
|
||
| // same depth, prefer non return | ||
| bool isRet0 = clause0->lastOp()!=(PcodeOp *)0 && clause0->lastOp()->isStandardReturn(); | ||
| bool isRet1 = clause1->lastOp()!=(PcodeOp *)0 && clause1->lastOp()->isStandardReturn(); | ||
|
Comment on lines
+1514
to
+1515
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For better code clarity and to adhere to modern C++ standards, it's recommended to use bool isRet0 = clause0->lastOp() != nullptr && clause0->lastOp()->isStandardReturn();
bool isRet1 = clause1->lastOp() != nullptr && clause1->lastOp()->isStandardReturn(); |
||
| if(isRet0 && !isRet1) return 1; | ||
| if(isRet1 && !isRet0) return 0; | ||
|
|
||
| // prefer block containing only return op | ||
| if(isRet0){ // both are return | ||
| FlowBlock* fb; | ||
| if(clause0->getType()==FlowBlock::t_copy){ | ||
| fb = ((BlockCopy*)clause0)->subBlock(0); | ||
| if(fb->getType()==FlowBlock::t_basic && ((BlockBasic*)fb)->getOpSize()==1) return 0; | ||
| } | ||
| if(clause1->getType()==FlowBlock::t_copy){ | ||
| fb = ((BlockCopy*)clause1)->subBlock(0); | ||
| if(fb->getType()==FlowBlock::t_basic && ((BlockBasic*)fb)->getOpSize()==1) return 1; | ||
| } | ||
|
Comment on lines
+1521
to
1529
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This block of code can be improved for safety and clarity:
Additionally, if(clause0->getType()==FlowBlock::t_copy){
FlowBlock* fb = static_cast<BlockCopy*>(clause0)->subBlock(0);
if(fb->getType()==FlowBlock::t_basic && static_cast<BlockBasic*>(fb)->getOpSize()==1) return 0;
}
if(clause1->getType()==FlowBlock::t_copy){
FlowBlock* fb = static_cast<BlockCopy*>(clause1)->subBlock(0);
if(fb->getType()==FlowBlock::t_basic && static_cast<BlockBasic*>(fb)->getOpSize()==1) return 1;
} |
||
| graph.newBlockIf(bl,clauseblock); | ||
| return true; | ||
| } | ||
| return false; | ||
|
|
||
| // fall back to previous behavior | ||
| return 0; | ||
| } | ||
|
|
||
| /// Try to find a while/do structure, starting with a given FlowBlock. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation of this loop can be made more concise and readable by using a range-based for loop. Also, the indentation for
maxDepth=depth;seems to be off (using a tab instead of spaces), which affects code consistency. Declaringdepthinside the loop scope is also better practice.