Skip to content

Commit b817652

Browse files
author
Shaobo
committed
Added a pass that warns about loops
It also prints a loop bound if it can be determined via LLVM's ScalarEvolution class. Specifically, it's equal to the `ConstantMaxBackedgeTakenCount`. Partially addressed #760
1 parent 7f927dc commit b817652

File tree

6 files changed

+88
-0
lines changed

6 files changed

+88
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ add_library(smackTranslator STATIC
124124
include/smack/SplitAggregateValue.h
125125
include/smack/Prelude.h
126126
include/smack/SmackWarnings.h
127+
include/smack/LoopInfo.h
127128
lib/smack/AddTiming.cpp
128129
lib/smack/BoogieAst.cpp
129130
lib/smack/BplFilePrinter.cpp
@@ -151,6 +152,7 @@ add_library(smackTranslator STATIC
151152
lib/smack/SplitAggregateValue.cpp
152153
lib/smack/Prelude.cpp
153154
lib/smack/SmackWarnings.cpp
155+
lib/smack/LoopInfo.cpp
154156
)
155157

156158
add_executable(llvm2bpl

include/smack/LoopInfo.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// This file is distributed under the MIT License. See LICENSE for details.
3+
//
4+
#ifndef LOOPINFO_H
5+
#define LOOPINFO_H
6+
7+
#include "llvm/Pass.h"
8+
9+
namespace smack {
10+
11+
class LoopInfo : public llvm::FunctionPass {
12+
public:
13+
static char ID; // Pass identification, replacement for typeid
14+
LoopInfo() : llvm::FunctionPass(ID) {}
15+
virtual llvm::StringRef getPassName() const override;
16+
virtual bool runOnFunction(llvm::Function &F) override;
17+
virtual void getAnalysisUsage(llvm::AnalysisUsage &) const override;
18+
};
19+
} // namespace smack
20+
21+
#endif // LOOPINFO_H

include/smack/SmackWarnings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class SmackWarnings {
3434
static void warnApproximate(std::string name, Block *currBlock,
3535
const llvm::Instruction *i);
3636

37+
static void warnLoop(std::string description);
38+
3739
static void warnOverApproximate(std::string name, UnsetFlagsT unsetFlags,
3840
Block *currBlock, const llvm::Instruction *i,
3941
FlagRelation rel);

lib/smack/LoopInfo.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// This file is distributed under the MIT License. See LICENSE for details.
3+
//
4+
5+
#define DEBUG_TYPE "smack-loop-info"
6+
#include "smack/LoopInfo.h"
7+
#include "smack/Debug.h"
8+
#include "smack/SmackWarnings.h"
9+
#include "llvm/Analysis/LoopInfo.h"
10+
#include "llvm/Analysis/ScalarEvolution.h"
11+
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
12+
#include "llvm/Support/raw_ostream.h"
13+
14+
namespace smack {
15+
16+
using namespace llvm;
17+
18+
void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
19+
AU.setPreservesAll();
20+
AU.addRequired<LoopInfoWrapperPass>();
21+
AU.addRequired<ScalarEvolutionWrapperPass>();
22+
}
23+
24+
bool LoopInfo::runOnFunction(Function &F) {
25+
auto &loopInfo = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
26+
auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
27+
for (auto LI = loopInfo.begin(), LIEnd = loopInfo.end(); LI != LIEnd; ++LI) {
28+
auto L = *LI;
29+
auto lr = L->getLocRange();
30+
auto sl = lr.getStart();
31+
auto el = lr.getEnd();
32+
std::string description;
33+
raw_string_ostream o(description);
34+
o << "found loop from line " << sl.getLine() << " to line " << el.getLine()
35+
<< " in function " << F.getName() << " with ";
36+
// TODO: figure out why induction variable won't work
37+
// auto bs = L->getInductionVariable(SE);
38+
if (auto C =
39+
dyn_cast<SCEVConstant>(SE.getConstantMaxBackedgeTakenCount(L))) {
40+
auto CI = C->getValue()->getValue().getZExtValue();
41+
o << "known loop bound " << CI;
42+
} else
43+
o << "unknown loop bound";
44+
SmackWarnings::warnLoop(o.str());
45+
}
46+
return false;
47+
}
48+
49+
char LoopInfo::ID = 0;
50+
51+
StringRef LoopInfo::getPassName() const {
52+
return "Get Loop Information for the purpose of sound analysis";
53+
}
54+
} // namespace smack

lib/smack/SmackWarnings.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ std::string SmackWarnings::getFlagStr(UnsetFlagsT flags) {
5454
return ret + "}";
5555
}
5656

57+
void SmackWarnings::warnLoop(std::string description) {
58+
processApproximate(description + "; please check loop unrolling bound "
59+
"otherwise there may be missed bugs",
60+
{}, nullptr, nullptr, FlagRelation::And);
61+
}
62+
5763
void SmackWarnings::warnApproximate(std::string name, Block *currBlock,
5864
const Instruction *i) {
5965
processApproximate(

tools/llvm2bpl/llvm2bpl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "smack/ExtractContracts.h"
3535
#include "smack/InitializePasses.h"
3636
#include "smack/IntegerOverflowChecker.h"
37+
#include "smack/LoopInfo.h"
3738
#include "smack/MemorySafetyChecker.h"
3839
#include "smack/Naming.h"
3940
#include "smack/NormalizeLoops.h"
@@ -213,6 +214,8 @@ int main(int argc, char **argv) {
213214
// pass_manager.add(new smack::SimplifyLibCalls());
214215
pass_manager.add(new llvm::Devirtualize());
215216
pass_manager.add(new smack::SplitAggregateValue());
217+
pass_manager.add(llvm::createLoopSimplifyPass());
218+
pass_manager.add(new smack::LoopInfo());
216219

217220
if (smack::SmackOptions::MemorySafety) {
218221
pass_manager.add(new smack::MemorySafetyChecker());

0 commit comments

Comments
 (0)