Static Value-Flow Analysis
Loading...
Searching...
No Matches
SVFGOPT.cpp
Go to the documentation of this file.
1//===- SVFGOPT.cpp -- SVFG optimizer------------------------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2017> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23/*
24 * @file: SVFGOPT.cpp
25 * @author: yesen
26 * @date: 31/03/2014
27 * @version: 1.0
28 *
29 * @section LICENSE
30 *
31 * @section DESCRIPTION
32 *
33 */
34
35#include "Util/Options.h"
36#include "Graphs/SVFGOPT.h"
37#include "Graphs/SVFGStat.h"
38
39using namespace SVF;
40using namespace SVFUtil;
41
42static std::string KeepAllSelfCycle = "all";
43static std::string KeepContextSelfCycle = "context";
44static std::string KeepNoneSelfCycle = "none";
45
46
48{
50
52 dump("SVFG_before_opt");
53
54 DBOUT(DGENERAL, outs() << SVFUtil::pasMsg("\tSVFG Optimisation\n"));
55
57
60
63
64}
75
86
91{
92 SVFGNodeSet candidates;
93 for (SVFGNodeIDToNodeMapTy::iterator it = SVFG::begin(), eit = SVFG::end();
94 it!=eit; ++it)
95 {
96 SVFGNode* node = it->second;
100 candidates.insert(node);
101 }
102
104 for (SVFGNodeSet::const_iterator it = candidates.begin(), eit = candidates.end();
105 it!=eit; ++it)
106 {
107 SVFGNode* node = *it;
108 if (FormalParmSVFGNode* fp = SVFUtil::dyn_cast<FormalParmSVFGNode>(node))
109 {
111 nodesToBeDeleted.insert(fp);
112 }
113 else if (ActualRetSVFGNode* ar = SVFUtil::dyn_cast<ActualRetSVFGNode>(node))
114 {
116 nodesToBeDeleted.insert(ar);
117 }
118 else if (SVFUtil::isa<ActualParmSVFGNode, FormalRetSVFGNode>(node))
119 {
120 nodesToBeDeleted.insert(node);
121 }
122 else if (SVFUtil::isa<ActualINSVFGNode, FormalOUTSVFGNode>(node))
123 {
125 nodesToBeDeleted.insert(node);
126 }
127 else if (SVFUtil::isa<ActualOUTSVFGNode, FormalINSVFGNode>(node))
128 {
129 if(keepActualOutFormalIn == false)
130 nodesToBeDeleted.insert(node);
131 }
132 }
133
134 for (SVFGNodeSet::iterator it = nodesToBeDeleted.begin(), eit = nodesToBeDeleted.end(); it != eit; ++it)
135 {
136 SVFGNode* node = *it;
137 if (canBeRemoved(node))
138 {
139 if (SVFUtil::isa<ActualOUTSVFGNode, FormalINSVFGNode>(node))
141
142 removeAllEdges(node);
143 removeSVFGNode(node);
144 }
145 }
146}
147
152{
153 assert((SVFUtil::isa<FormalParmSVFGNode, ActualRetSVFGNode>(svfgNode))
154 && "expecting a formal param or actual ret svfg node");
155
157 NodeID phiId = phi->getId();
159 for (SVFGNode::const_iterator it = svfgNode->OutEdgeBegin(), eit = svfgNode->OutEdgeEnd();
160 it != eit; ++it)
161 {
162 const SVFGEdge* outEdge = *it;
163 SVFGNode* dstNode = outEdge->getDstNode();
165 if (const CallDirSVFGEdge* callEdge = SVFUtil::dyn_cast<CallDirSVFGEdge>(outEdge))
166 addCallEdge(phiId, dstId, callEdge->getCallSiteId());
167 else if (const RetDirSVFGEdge* retEdge = SVFUtil::dyn_cast<RetDirSVFGEdge>(outEdge))
168 addRetEdge(phiId, dstId, retEdge->getCallSiteId());
169 else
171 }
172
174 if (FormalParmSVFGNode* fp = SVFUtil::dyn_cast<FormalParmSVFGNode>(svfgNode))
175 {
176 for (SVFGNode::iterator it = svfgNode->InEdgeBegin(), eit = svfgNode->InEdgeEnd();
177 it != eit; ++it)
178 {
179 ActualParmSVFGNode* ap = SVFUtil::cast<ActualParmSVFGNode>((*it)->getSrcNode());
181 // connect actual param's def node to phi node
183 }
184 }
185 else if (ActualRetSVFGNode* ar = SVFUtil::dyn_cast<ActualRetSVFGNode>(svfgNode))
186 {
187 for (SVFGNode::iterator it = svfgNode->InEdgeBegin(), eit = svfgNode->InEdgeEnd();
188 it != eit; ++it)
189 {
190 FormalRetSVFGNode* fr = SVFUtil::cast<FormalRetSVFGNode>((*it)->getSrcNode());
191 addInterPHIOperands(phi, fr->getRet());
192 // connect formal return's def node to phi node
193 addRetEdge(getDef(fr->getRet()), phiId, getCallSiteID(ar->getCallSite(), fr->getFun()));
194 }
195 }
196
198}
199
205{
206 assert(node->getInEdges().size() == 1 && "actual-in/formal-out can only have one incoming edge as its def size");
207
208 SVFGNode* def = nullptr;
210
213 for (; it != eit; ++it)
214 {
215 const IndirectSVFGEdge* inEdge = SVFUtil::cast<IndirectSVFGEdge>(*it);
216 inPointsTo = inEdge->getPointsTo();
217
218 def = inEdge->getSrcNode();
219 if (SVFUtil::isa<ActualINSVFGNode>(node))
220 setActualINDef(node->getId(), def->getId());
221 else if (SVFUtil::isa<FormalOUTSVFGNode>(node))
222 setFormalOUTDef(node->getId(), def->getId());
223 }
224
225 it = node->OutEdgeBegin(), eit = node->OutEdgeEnd();
226 for (; it != eit; ++it)
227 {
228 const IndirectSVFGEdge* outEdge = SVFUtil::cast<IndirectSVFGEdge>(*it);
230 intersection &= outEdge->getPointsTo();
231
232 if (intersection.empty())
233 continue;
234
235 SVFGNode* dstNode = outEdge->getDstNode();
236 if (const CallIndSVFGEdge* callEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(outEdge))
237 addCallIndirectSVFGEdge(def->getId(), dstNode->getId(), callEdge->getCallSiteId(), intersection);
238 else if (const RetIndSVFGEdge* retEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(outEdge))
239 addRetIndirectSVFGEdge(def->getId(), dstNode->getId(), retEdge->getCallSiteId(), intersection);
240 else
241 assert(false && "expecting an inter-procedural SVFG edge");
242 }
243
244 removeAllEdges(node);
245}
246
251{
254 for (; inIt != inEit; ++inIt)
255 {
256 const IndirectSVFGEdge* inEdge = SVFUtil::cast<IndirectSVFGEdge>(*inIt);
257 NodeID srcId = inEdge->getSrcID();
258
261 for (; outIt != outEit; ++outIt)
262 {
263 const IndirectSVFGEdge* outEdge = SVFUtil::cast<IndirectSVFGEdge>(*outIt);
264
265 NodeBS intersection = inEdge->getPointsTo();
266 intersection &= outEdge->getPointsTo();
267 if (intersection.empty())
268 continue;
269
270 NodeID dstId = outEdge->getDstID();
271 if (const RetIndSVFGEdge* retEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(inEdge))
272 {
274 }
275 else if (const CallIndSVFGEdge* callEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(inEdge))
276 {
278 }
279 else
280 {
282 }
283 }
284 }
285
286 removeAllEdges(node);
287}
288
293{
294 bool hasInCallRet = false;
295 bool hasOutCallRet = false;
296
299 for (; edgeIt != edgeEit; ++edgeIt)
300 {
301 if (SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(*edgeIt))
302 {
303 hasInCallRet = true;
304 break;
305 }
306 }
307
308 edgeIt = node->OutEdgeBegin();
309 edgeEit = node->OutEdgeEnd();
310 for (; edgeIt != edgeEit; ++edgeIt)
311 {
312 if (SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(*edgeIt))
313 {
314 hasOutCallRet = true;
315 break;
316 }
317 }
318
320 return true;
321 else
322 return false;
323}
324
335{
338 return true;
341 {
345 if (isConnectingTwoCallSites(node))
346 return false;
347
348 if (const ActualINSVFGNode* ai = SVFUtil::dyn_cast<ActualINSVFGNode>(node))
349 {
350 return (actualInOfIndCS(ai) == false);
351 }
352 else if (const ActualOUTSVFGNode* ao = SVFUtil::dyn_cast<ActualOUTSVFGNode>(node))
353 {
354 return (actualOutOfIndCS(ao) == false && isDefOfAInFOut(node) == false);
355 }
356 else if (const FormalINSVFGNode* fi = SVFUtil::dyn_cast<FormalINSVFGNode>(node))
357 {
358 return (formalInOfAddressTakenFunc(fi) == false && isDefOfAInFOut(node) == false);
359 }
360 else if (const FormalOUTSVFGNode* fo = SVFUtil::dyn_cast<FormalOUTSVFGNode>(node))
361 {
362 return (formalOutOfAddressTakenFunc(fo) == false);
363 }
364 }
365
366 return false;
367}
368
373{
374 std::string choice = (Options::SelfCycle().empty()) ? "" : Options::SelfCycle();
375 if (choice.empty() || choice == KeepAllSelfCycle)
376 keepAllSelfCycle = true;
377 else if (choice == KeepContextSelfCycle)
379 else if (choice == KeepNoneSelfCycle)
381 else
382 {
383 SVFUtil::writeWrnMsg("Unrecognised option. All self cycle edges will be kept.");
384 keepAllSelfCycle = true;
385 }
386}
387
392{
394
396
397 while (!worklist.empty())
398 {
399 const MSSAPHISVFGNode* node = worklist.pop();
400
402 if (checkSelfCycleEdges(node))
403 continue;
404
405 if (node->hasOutgoingEdge() && node->hasIncomingEdge())
406 bypassMSSAPHINode(node);
407
409 if (node->hasIncomingEdge() && node->hasOutgoingEdge() == false)
410 {
414 for (; edgeIt != edgeEit; ++edgeIt)
415 addIntoWorklist((*edgeIt)->getSrcNode());
416
417 removeInEdges(node);
418 }
419 else if (node->hasOutgoingEdge() && node->hasIncomingEdge() == false)
420 {
424 for (; edgeIt != edgeEit; ++edgeIt)
425 addIntoWorklist((*edgeIt)->getDstNode());
426
427 removeOutEdges(node);
428 }
429
431 if (node->hasIncomingEdge() == false && node->hasOutgoingEdge() == false)
432 removeSVFGNode(const_cast<MSSAPHISVFGNode*>(node));
433 }
434}
435
436
443{
444 bool hasSelfCycle = false;
445
449 for (; inEdgeIt != inEdgeEit; ++inEdgeIt)
450 {
452
453 if (preEdge->getSrcID() == preEdge->getDstID())
454 {
456 {
457 hasSelfCycle = true;
458 break;
459 }
460 else if (keepContextSelfCycle &&
461 SVFUtil::isa<CallIndSVFGEdge, RetIndSVFGEdge>(preEdge))
462 {
463 hasSelfCycle = true;
464 continue;
465 }
466 else
467 {
468 assert(SVFUtil::isa<IndirectSVFGEdge>(preEdge) && "can only remove indirect SVFG edge");
470 }
471 }
472 }
473
474 return hasSelfCycle;
475}
476
481{
484 for (; inEdgeIt != inEdgeEit; ++inEdgeIt)
485 {
486 const SVFGEdge* preEdge = *inEdgeIt;
487 const SVFGNode* srcNode = preEdge->getSrcNode();
488
489 bool added = false;
493 for (; outEdgeIt != outEdgeEit; ++outEdgeIt)
494 {
495 const SVFGEdge* succEdge = *outEdgeIt;
496 const SVFGNode* dstNode = (*outEdgeIt)->getDstNode();
497 if (srcNode->getId() != dstNode->getId()
498 && addNewSVFGEdge(srcNode->getId(), dstNode->getId(), preEdge, succEdge))
499 added = true;
500 else
501 {
505 }
506 }
507
508 if (added == false)
509 {
513 }
514 }
515
516 removeAllEdges(node);
517}
518
524{
525 assert(SVFUtil::isa<IndirectSVFGEdge>(preEdge) && SVFUtil::isa<IndirectSVFGEdge>(succEdge)
526 && "either pre or succ edge is not indirect SVFG edge");
527
528 const IndirectSVFGEdge* preIndEdge = SVFUtil::cast<IndirectSVFGEdge>(preEdge);
529 const IndirectSVFGEdge* succIndEdge = SVFUtil::cast<IndirectSVFGEdge>(succEdge);
530
531 NodeBS intersection = preIndEdge->getPointsTo();
532 intersection &= succIndEdge->getPointsTo();
533
534 if (intersection.empty())
535 return false;
536
537 assert(bothInterEdges(preEdge, succEdge) == false && "both edges are inter edges");
538
539 if (const CallIndSVFGEdge* preCallEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(preEdge))
540 {
541 return addCallIndirectSVFGEdge(srcId, dstId, preCallEdge->getCallSiteId(), intersection);
542 }
543 else if (const CallIndSVFGEdge* succCallEdge = SVFUtil::dyn_cast<CallIndSVFGEdge>(succEdge))
544 {
545 return addCallIndirectSVFGEdge(srcId, dstId, succCallEdge->getCallSiteId(), intersection);
546 }
547 else if (const RetIndSVFGEdge* preRetEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(preEdge))
548 {
549 return addRetIndirectSVFGEdge(srcId, dstId, preRetEdge->getCallSiteId(), intersection);
550 }
551 else if (const RetIndSVFGEdge* succRetEdge = SVFUtil::dyn_cast<RetIndSVFGEdge>(succEdge))
552 {
553 return addRetIndirectSVFGEdge(srcId, dstId, succRetEdge->getCallSiteId(), intersection);
554 }
555 else
556 {
558 }
559
560 return false;
561}
static std::string KeepNoneSelfCycle
Definition SVFGOPT.cpp:44
static std::string KeepContextSelfCycle
Definition SVFGOPT.cpp:43
static std::string KeepAllSelfCycle
Definition SVFGOPT.cpp:42
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:484
#define DGENERAL
Definition SVFType.h:490
const PAGNode * getParam() const
Return parameter.
Definition VFGNode.h:907
const CallICFGNode * getCallSite() const
Return callsite.
Definition VFGNode.h:901
bool empty() const
Definition WorkList.h:146
iterator begin()
Iterators.
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
bool hasOutgoingEdge() const
iterator OutEdgeEnd()
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
iterator InEdgeBegin()
iterator InEdgeEnd()
virtual const SVFFunction * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:76
static const Option< bool > KeepAOFI
Definition Options.h:107
static const Option< std::string > SelfCycle
Definition Options.h:108
static const Option< bool > DumpVFG
Definition Options.h:111
static const Option< bool > ContextInsensitive
Definition Options.h:106
NodeID getId() const
Get ID.
Set< SVFGNode * > SVFGNodeSet
Definition SVFGOPT.h:58
bool isDefOfAInFOut(const SVFGNode *node)
Definition SVFGOPT.h:286
SVFGEdge * addCallIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS &cpts)
Add inter-procedural value flow edge.
Definition SVFGOPT.cpp:68
void replaceFParamARetWithPHI(PHISVFGNode *phi, SVFGNode *svfgNode)
Replace FormalParam/ActualRet node with PHI node.
Definition SVFGOPT.cpp:151
void handleIntraValueFlow()
Remove MSSAPHI SVFG nodes.
Definition SVFGOPT.cpp:391
void retargetEdgesOfAOutFIn(SVFGNode *node)
Connect actual-out/formal-in's predecessors to their successors directly.
Definition SVFGOPT.cpp:250
void addInterPHIOperands(PHISVFGNode *phi, const PAGNode *operand)
Definition SVFGOPT.h:238
void setFormalOUTDef(NodeID fo, NodeID def)
Definition SVFGOPT.h:277
void setActualINDef(NodeID ai, NodeID def)
Definition SVFGOPT.h:270
void handleInterValueFlow()
Definition SVFGOPT.cpp:90
void bypassMSSAPHINode(const MSSAPHISVFGNode *node)
Remove MSSAPHI node if possible.
Definition SVFGOPT.cpp:480
void removeInEdges(const SVFGNode *node)
Definition SVFGOPT.h:336
bool keepAllSelfCycle
Definition SVFGOPT.h:357
bool addNewSVFGEdge(NodeID srcId, NodeID dstId, const SVFGEdge *preEdge, const SVFGEdge *succEdge)
Add new SVFG edge from src to dst.
Definition SVFGOPT.cpp:523
bool bothInterEdges(const SVFGEdge *edge1, const SVFGEdge *edge2) const
Return TRUE if both edges are indirect call/ret edges.
Definition SVFGOPT.h:231
bool formalInOfAddressTakenFunc(const FormalINSVFGNode *fi) const
Check if formal-in/formal-out reside in address-taken function.
Definition SVFGOPT.h:305
bool addIntoWorklist(const SVFGNode *node)
Definition SVFGOPT.h:211
void buildSVFG() override
Start building SVFG.
Definition SVFGOPT.cpp:47
bool actualOutOfIndCS(const ActualOUTSVFGNode *ao) const
Definition SVFGOPT.h:297
bool keepActualOutFormalIn
Definition SVFGOPT.h:356
InterPHISVFGNode * addInterPHIForAR(const ActualRetSVFGNode *ar)
Add inter PHI SVFG node for actual return.
Definition SVFGOPT.h:252
bool formalOutOfAddressTakenFunc(const FormalOUTSVFGNode *fo) const
Definition SVFGOPT.h:309
WorkList worklist
storing MSSAPHI nodes which may be removed.
Definition SVFGOPT.h:354
InterPHISVFGNode * addInterPHIForFP(const FormalParmSVFGNode *fp)
Add inter PHI SVFG node for formal parameter.
Definition SVFGOPT.h:244
bool isConnectingTwoCallSites(const SVFGNode *node) const
Return TRUE if this node has both incoming call/ret and outgoing call/ret edges.
Definition SVFGOPT.cpp:292
bool canBeRemoved(const SVFGNode *node)
Definition SVFGOPT.cpp:334
void retargetEdgesOfAInFOut(SVFGNode *node)
Retarget edges related to actual-in/-out and formal-in/-out.
Definition SVFGOPT.cpp:204
void removeAllEdges(const SVFGNode *node)
Remove edges of a SVFG node.
Definition SVFGOPT.h:331
void parseSelfCycleHandleOption()
Definition SVFGOPT.cpp:372
bool keepContextSelfCycle
Definition SVFGOPT.h:358
void initialWorkList()
Initial work list with MSSAPHI nodes which may be removed.
Definition SVFGOPT.h:202
void removeOutEdges(const SVFGNode *node)
Definition SVFGOPT.h:342
bool actualInOfIndCS(const ActualINSVFGNode *ai) const
Check if actual-in/actual-out exist at indirect call site.
Definition SVFGOPT.h:293
SVFGEdge * addRetIndirectSVFGEdge(NodeID srcId, NodeID dstId, CallSiteID csid, const NodeBS &cpts)
Add indirect ret edge from src to dst with one call site ID.
Definition SVFGOPT.cpp:79
bool checkSelfCycleEdges(const MSSAPHISVFGNode *node)
Remove self cycle edges if needed. Return TRUE if some self cycle edges remained.
Definition SVFGOPT.cpp:442
void sfvgOptEnd()
Definition SVFGStat.h:154
void sfvgOptStart()
Definition SVFGStat.h:149
virtual void buildSVFG()
Start building SVFG.
Definition SVFG.cpp:228
void dump(const std::string &file, bool simple=false)
Dump graph into dot file.
Definition SVFG.cpp:576
void removeSVFGNode(SVFGNode *node)
Remove a SVFGNode.
Definition SVFG.h:243
SVFGEdge * addRetIndirectVFEdge(NodeID srcId, NodeID dstId, const NodeBS &cpts, CallSiteID csId)
Definition SVFG.cpp:525
void removeSVFGEdge(SVFGEdge *edge)
Remove a SVFG edge.
Definition SVFG.h:238
NodeID getDef(const PAGNode *pagNode) const
Definition SVFG.h:356
SVFGEdge * addIntraIndirectVFEdge(NodeID srcId, NodeID dstId, const NodeBS &cpts)
Add indirect def-use edges of a memory region between two statements,.
Definition SVFG.cpp:463
SVFGStat * stat
Definition SVFG.h:105
SVFGEdge * addCallIndirectVFEdge(NodeID srcId, NodeID dstId, const NodeBS &cpts, CallSiteID csId)
Definition SVFG.cpp:505
VFGEdgeSetTy SVFGEdgeSetTy
Definition VFGEdge.h:118
VFGEdge::VFGEdgeSetTy::const_iterator const_iterator
Definition VFGNode.h:55
VFGEdge::VFGEdgeSetTy::iterator iterator
Definition VFGNode.h:54
VFGEdge * addRetEdge(NodeID srcId, NodeID dstId, CallSiteID csId)
Definition VFG.cpp:721
VFGEdge * addIntraDirectVFEdge(NodeID srcId, NodeID dstId)
Definition VFG.cpp:675
CallSiteID getCallSiteID(const CallICFGNode *cs, const SVFFunction *func) const
Get callsite given a callsiteID.
Definition VFG.h:178
VFGEdge * addCallEdge(NodeID srcId, NodeID dstId, CallSiteID csId)
Definition VFG.cpp:701
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:100
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:67
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
u32_t NodeID
Definition GeneralType.h:55
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74