Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • opensrc/SMPStaticAnalyzer
1 result
Show changes
Commits on Source (1)
......@@ -12210,6 +12210,8 @@ bool SMPFunction::AnalyzeCompoundConditionalStatements(void) {
}
else {
// Perform the requested cloning and clear the cloning work list.
this->CloningMap.clear();
this->CloningReverseMap.clear();
for (pair<int, pair<int, int> > CloningWorkListItem : this->SPARKCloningWorkList) {
int StartBlockNum = CloningWorkListItem.first;
int UnlinkBlockNum = CloningWorkListItem.second.first;
......@@ -12222,16 +12224,29 @@ bool SMPFunction::AnalyzeCompoundConditionalStatements(void) {
bool SaneAfterCloning = this->AuditTCFG();
// Pred/succ links are not complete until UpdateAfterCloning() executes when we clone more than 1 block.
// assert(SaneAfterCloning || (1 < this->CloningMap.size()));
this->UpdateAfterCloning();
bool SaneAfterCloningUpdate = this->AuditTCFG();
assert(SaneAfterCloningUpdate);
} // end for all items in SPARKCloningWorkList
if (this->TCFGBlocks.size() > this->TCFGDomSoFar.GetNumBits()) {
Structured = false;
break;
}
this->UpdateAfterCloning();
bool SaneAfterCloningUpdate = this->AuditTCFG();
assert(SaneAfterCloningUpdate);
}
this->SPARKCloningWorkList.clear();
} // end if (CloningNeeded)
 
} while (Structured && CloningNeeded);
 
if (this->TCFGBlocks.size() > this->TCFGDomSoFar.GetNumBits()) {
SMP_msg("ERROR: SPARK: Unstructured due to TCFG size bloat after cloning ");
this->DumpFuncNameAndAddr();
this->PrintedSPARKUnstructuredMsg = true;
this->DumpDotCFG();
Structured = false;
}
 
return Structured;
} // end of SMPFunction::AnalyzeCompoundConditionalStatements()
......@@ -12509,6 +12524,8 @@ bool SMPFunction::AnalyzeConditionalStatements(void) {
break;
}
// Perform the requested cloning and clear the cloning work list.
this->CloningMap.clear();
this->CloningReverseMap.clear();
for (pair<int, pair<int, int> > CloningWorkListItem : this->SPARKCloningWorkList) {
int StartBlockNum = CloningWorkListItem.first;
int UnlinkBlockNum = CloningWorkListItem.second.first;
......@@ -12521,10 +12538,15 @@ bool SMPFunction::AnalyzeConditionalStatements(void) {
bool SaneAfterCloning = this->AuditTCFG();
// Pred/succ links are not complete until UpdateAfterCloning() executes when we clone more than 1 block or exit the loop.
// assert(SaneAfterCloning || (1 < this->CloningMap.size()));
this->UpdateAfterCloning();
bool SaneAfterCloningUpdate = this->AuditTCFG();
assert(SaneAfterCloningUpdate);
}
if (this->TCFGBlocks.size() > this->TCFGDomSoFar.GetNumBits()) {
StructuredConditional = false;
break;
}
this->UpdateAfterCloning();
bool SaneAfterCloningUpdate = this->AuditTCFG();
assert(SaneAfterCloningUpdate);
this->SPARKCloningWorkList.clear();
}
} while (CloningNeeded);
......@@ -12542,6 +12564,15 @@ bool SMPFunction::AnalyzeConditionalStatements(void) {
}
StructuredConditional = false;
}
if (this->TCFGBlocks.size() > this->TCFGDomSoFar.GetNumBits()) {
SMP_msg("ERROR: SPARK: Unstructured due to TCFG size bloat after cloning ");
this->DumpFuncNameAndAddr();
this->PrintedSPARKUnstructuredMsg = true;
this->DumpDotCFG();
StructuredConditional = false;
}
return StructuredConditional;
} // end of SMPFunction::AnalyzeConditionalStatements()
 
......@@ -13685,13 +13716,25 @@ int SMPFunction::FindConditionalFollowNode4(const int HeadBlockNum, bool &IfThen
// Side entrances into both FTBlock and NFTBlock. Cloning can structure it.
// The FTBlock and NFTBlock already have convergence at their DomFrontiers, just have dominance problem.
// We can relax the NoDeadEnds requirement and clone through dead ends later.
SMP_msg("INFO: SPARK: Cloning doubly from %d and %d to %d would solve DomFrontier non-convergence for HeadBlock %d NoDeadEnds %d ", FTBlockNum, NFTBlockNum, FollowBlockNum, HeadBlockNum, NoDeadEnds);
this->DumpFuncNameAndAddr();
this->DumpDotCFG();
this->ResetTCFGVisitedBlocks();
// this->MarkBlocksAndClone(FTBlockNum, FollowBlockNum);
// this->MarkBlocksAndClone(NFTBlockNum, FollowBlockNum);
FollowBlockNum = SMP_BLOCKNUM_UNINIT; // Not cloning yet
set<int> BlockNumsToClone;
set<int> BlockNumsToClone2;
bool SafeCloning = this->IsCloningSafe(NFTBlockNum, FollowBlockNum, BlockNumsToClone);
if (SafeCloning) { // see if second cloning will also be safe.
this->ResetTCFGVisitedBlocks();
SafeCloning = this->IsCloningSafe(FTBlockNum, FollowBlockNum, BlockNumsToClone2);
if (SafeCloning) {
pair<int, int> UnlinkLimitPair(HeadBlockNum, FollowBlockNum);
pair<int, pair<int, int> > CloningWorkListItem(NFTBlockNum, UnlinkLimitPair);
this->SPARKCloningWorkList.push_back(CloningWorkListItem);
pair<int, int> UnlinkLimitPair2(HeadBlockNum, FollowBlockNum);
pair<int, pair<int, int> > CloningWorkListItem2(FTBlockNum, UnlinkLimitPair2);
this->SPARKCloningWorkList.push_back(CloningWorkListItem2);
SMP_msg("INFO: SPARK: Cloning doubly from %d and %d to %d would solve DomFrontier non-convergence for HeadBlock %d NoDeadEnds %d ShortCircuitFlag %d ", FTBlockNum, NFTBlockNum, FollowBlockNum, HeadBlockNum, NoDeadEnds, ShortCircuit);
this->DumpFuncNameAndAddr();
this->DumpDotCFG();
}
}
}
else {
if (!this->PrintedSPARKUnstructuredMsg) {
......@@ -13787,7 +13830,6 @@ bool SMPFunction::SolveConditionalDomFrontierProblemViaCloning(const int HeadBlo
this->DumpDotCFG();
this->ResetTCFGVisitedBlocks();
FollowBlockNum = NFTDomFrontierBlockNum;
// this->MarkBlocksAndClone(FTDomFrontierBlockNum, FollowBlockNum);
CloningStructuresConditional = true;
}
}
......@@ -13797,7 +13839,6 @@ bool SMPFunction::SolveConditionalDomFrontierProblemViaCloning(const int HeadBlo
this->DumpDotCFG();
this->ResetTCFGVisitedBlocks();
FollowBlockNum = FTDomFrontierBlockNum;
// this->MarkBlocksAndClone(NFTDomFrontierBlockNum, FollowBlockNum);
CloningStructuresConditional = true;
}
else if (GoodFTCount && GoodNFTCount && (NewFTDomFrontierBlockNum == NewNFTDomFrontierBlockNum)) {
......@@ -13807,8 +13848,6 @@ bool SMPFunction::SolveConditionalDomFrontierProblemViaCloning(const int HeadBlo
this->DumpDotCFG();
this->ResetTCFGVisitedBlocks();
FollowBlockNum = NewFTDomFrontierBlockNum;
// this->MarkBlocksAndClone(FTDomFrontierBlockNum, FollowBlockNum);
// this->MarkBlocksAndClone(NFTDomFrontierBlockNum, FollowBlockNum);
CloningStructuresConditional = true;
}
 
......@@ -13868,9 +13907,9 @@ bool SMPFunction::IsCloningSafe(const int StartTCFGBlockNum, const int LimitTCFG
// Push cloned blocks onto end of TCFGBlocks.
// Update ClonedShadowCFGBlocks in lockstep with TCFGBlocks.
void SMPFunction::MarkBlocksAndClone(const int StartingBlockNum, const int UnlinkBlockNum, const int LimitBlockNum, const int InnermostLoopNum, bool FirstIter) {
size_t FirstClonedBlockIndex = 0;
if (FirstIter) {
this->CloningMap.clear();
this->CloningReverseMap.clear();
FirstClonedBlockIndex = this->TCFGBlocks.size();
}
 
bool InsideLoop = (0 <= InnermostLoopNum);
......@@ -13964,8 +14003,9 @@ void SMPFunction::MarkBlocksAndClone(const int StartingBlockNum, const int Unlin
}
}
}
else if (!this->CloningMap.empty()) {
// We are finished cloning on this subpath. Update the JumpFollowNodesMap.
if (!this->CloningMap.empty() && FirstIter) {
// We are finished cloning on this path. Update the JumpFollowNodesMap.
// Update JumpFollowNodesMap. For a current pair <jumpblocknum, targetblocknum> we have four possibilities:
// 1. Neither block was cloned; do nothing
// 2. Only targetblock was cloned; if jumpblocknum==unlinkblocknum, handled in FirstIter code above, else cannot be structured.
......@@ -14018,6 +14058,46 @@ void SMPFunction::MarkBlocksAndClone(const int StartingBlockNum, const int Unlin
} // end for all CloneMapItems
CloneMapItems.clear();
}
// Update block numbers only in the short-circuit blocks that were just cloned.
// This step is needed now because of the double-cloning possibility. If we have
// two items in the SPARKCloningWorkList, we need to keep track of block numbers
// at each step, not just after renumbering all blocks in UpdateAfterCloning().
for (size_t ClonedBlockIndex = FirstClonedBlockIndex; ClonedBlockIndex < this->TCFGBlocks.size(); ++ClonedBlockIndex) {
STARSCFGBlock *ClonedCFGBlock = this->GetClonedCFGBlockByNum(ClonedBlockIndex);
STARSCondExpr *CurrExpr = ClonedCFGBlock->GetExpr();
if (nullptr != CurrExpr) {
CurrExpr->ResetAllExprsVisited(); // prepare to avoid redundant updates
}
} // end for all ClonedBlockIndex values only
for (size_t ClonedBlockIndex = FirstClonedBlockIndex; ClonedBlockIndex < this->TCFGBlocks.size(); ++ClonedBlockIndex) {
STARSCFGBlock *ClonedCFGBlock = this->GetClonedCFGBlockByNum(ClonedBlockIndex);
bool ExprHeadBlock = ClonedCFGBlock->IsExprHeadBlock();
bool UpdateBlockNums = (ClonedCFGBlock->IsCoalesced() || ExprHeadBlock);
if (UpdateBlockNums) {
// Part of short circuit expr; need to adjust Left, right, CoalescedInto, FT and NFT block numbers.
// This is the entire purpose of maintaining a cloned ShadowCFG. When
// a short-circuit expr is cloned, it appears in two places in the CFG
// and has two different FTBlock #'s and two different NFTBlock #'s in the TCFG.
// Because all exprs were deep-copied on creation, we have to recurse through subexprs.
this->UpdateCFGExprBlockNums(ClonedCFGBlock->GetExpr());
// Update CoalescedBlockNum when not in the Head block.
if (!ExprHeadBlock) {
map<int, int>::const_iterator CloningMapIter = this->CloningMap.find(ClonedCFGBlock->GetCoalescedBlockNum());
assert(CloningMapIter != this->CloningMap.cend());
int NewCoalescedBlockNum = CloningMapIter->second;
ClonedCFGBlock->SetCoalescedBlockNum(NewCoalescedBlockNum);
}
// Update MyCFGBlock pointer, even though it seems to only be used to access the GetFunc()
// method, which works fine without updating.
STARSCFGBlock *NewCFGBlock = this->GetClonedCFGBlockByNum(ClonedBlockIndex);
assert(nullptr != NewCFGBlock);
ClonedCFGBlock->GetExpr()->SetCFGBlock(NewCFGBlock);
}
} // end for all ClonedBlockIndex values only
}
 
return;
......@@ -14257,12 +14337,14 @@ void SMPFunction::UpdateCFGExprBlockNums(STARSCondExpr *CurrExpr) {
if (!CurrExpr->IsVisited()) {
int FTBlockNum = CurrExpr->GetFallThroughBlockNum();
int NFTBlockNum = CurrExpr->GetNonFallThroughBlockNum();
// For an if-then, the LimitBlockNum on the cloning could be the FTBlockNum or NFTBlockNum,
// so it might not be found in the CloningMap. We could be more robust by actually matching
// the FTBlockNum or NFTBlockNum that is missing from the CloningMap to a LimitBlockNum in
// the SPARKCloningWorkList, and asserting that it must be found in the work list or the CloningMap.
map<int, int>::iterator CloneMapIter = this->CloningMap.find(FTBlockNum);
assert(this->CloningMap.end() != CloneMapIter);
int NewFTBlockNum = CloneMapIter->second;
int NewFTBlockNum = (this->CloningMap.end() != CloneMapIter) ? CloneMapIter->second : FTBlockNum;
CloneMapIter = this->CloningMap.find(NFTBlockNum);
assert(this->CloningMap.end() != CloneMapIter);
int NewNFTBlockNum = CloneMapIter->second;
int NewNFTBlockNum = (this->CloningMap.end() != CloneMapIter) ? CloneMapIter->second : NFTBlockNum;
CurrExpr->SetFTBlockNum(NewFTBlockNum);
CurrExpr->SetNFTBlockNum(NewNFTBlockNum);
// Likewise, update the Left and Right blocknums in the expression.
......@@ -14334,6 +14416,11 @@ bool SMPFunction::AuditTCFG(void) const {
} // end for all successors
} // end for all TCFGBlocks
 
if (this->TCFGBlocks.size() > this->TCFGDomSoFar.GetNumBits()) {
Sane = false;
SMP_msg("ERROR: TCFG: Block count %zu has grown larger than TCFGDomSoFar size %zu \n", this->TCFGBlocks.size(), this->TCFGDomSoFar.GetNumBits());
}
return Sane;
} // end of SMPFunction::AuditTCFG()
 
......@@ -22186,6 +22273,41 @@ void SMPFunction::DumpDotCFG(void) {
}
SMP_fprintf(DotFile, "}\n");
(void)SMP_fclose(DotFile);
// Dump out the ClonedShadowCFG so we can check its sanity against the TCFG.
string DotFileNameC(global_STARS_program->GetRootFileName());
DotFileNameC += ".STARSC."; // add T for TCFG file
string FuncNameC("func");
FuncNameC += string(FuncBuf);
DotFileNameC += FuncNameC;
DotFileNameC += FileExtension;
FILE *DotFileC = SMP_fopen(DotFileNameC.c_str(), "w");
if (nullptr == DotFileC) {
SMP_msg("ERROR: Cannot open dot file %s for ShadowCFG dump.\n", DotFileNameC.c_str());
return;
}
SMP_fprintf(DotFileC, "digraph %s {\n", FuncNameC.c_str());
for (STARSCFGBlock *CurrBlock : this->ClonedShadowCFGBlocks) {
int CurrBlockNum = CurrBlock->GetBlockNum();
STARSTransCFGBlock *CurrTCFGBlock = this->GetTCFGBlockByNum((size_t)CurrBlockNum);
if (CurrTCFGBlock->GetNumSuccessors() > 0) {
if (CurrBlock->IsExprHeadBlock()) { // just print FT and NFT blocks; coalesced expr blocks are omitted
int FTBlockNum = CurrBlock->GetExpr()->GetFallThroughBlockNum();
int NFTBlockNum = CurrBlock->GetExpr()->GetNonFallThroughBlockNum();
SMP_fprintf(DotFileC, " %d -> %d\n", CurrBlockNum, FTBlockNum);
SMP_fprintf(DotFileC, " %d -> %d\n", CurrBlockNum, NFTBlockNum);
}
else if (!CurrBlock->IsCoalesced()) { // just print TCFG
for (STARSTransCFGBlock *SuccBlock : CurrTCFGBlock->GetConstSuccList()) {
SMP_fprintf(DotFileC, " %d -> %d\n", CurrBlockNum, SuccBlock->GetNumber());
}
}
}
}
SMP_fprintf(DotFileC, "}\n");
(void)SMP_fclose(DotFileC);
}
 
return;