Skip to content

Commit 01d7e6b

Browse files
committed
[TSAR, Analysis] Fix memory sources processing.
1 parent 4b93448 commit 01d7e6b

File tree

2 files changed

+184
-139
lines changed

2 files changed

+184
-139
lines changed

lib/Analysis/Memory/RestrictionArgumentsPass.cpp

Lines changed: 169 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <utility>
1010
#include <llvm/Analysis/CallGraph.h>
1111
#include "tsar/Analysis/Memory/RestrictionArgumentsPass.h"
12+
#include "../../../../../../sapfor-build/llvm-project/llvm/lib/IR/ConstantsContext.h"
1213
#include <llvm/Analysis/CallGraph.h>
1314
#include <llvm/Analysis/CallGraphSCCPass.h>
1415
#include <llvm/ADT/SCCIterator.h>
@@ -32,7 +33,7 @@ INITIALIZE_PASS_END(RestrictionArgumentsPass, "restriction-arguments",
3233
DenseSet<Value*> collectGlobalMemorySources(Module* M) {
3334
DenseSet<Value *> GlobalMemorySources;
3435
for (auto &GV : M->getGlobalList()) {
35-
if (GV.getType()->isPointerTy()) {
36+
if (GV.getValueType()->isPointerTy() || GV.getValueType()->isArrayTy()) {
3637
GlobalMemorySources.insert(&GV);
3738
}
3839
}
@@ -93,25 +94,49 @@ DenseSet<int> findPointerArgumentsIndexes(Function* F) {
9394
}
9495

9596
DenseSet<CallInst*> collectCallsOfFunctionsWithPointerArguments(Function* F) {
96-
DenseSet<CallInst*> CallsOfFunctionsWithPointerArguments;
97-
for (auto& I : instructions(F)) {
98-
if (auto* CallI = dyn_cast<CallInst>(&I)) {
99-
auto* CalledF = CallI->getCalledFunction();
100-
// LLVM_DEBUG(
101-
// dbgs() << "\tCallInst";
102-
// CallI->dump();
103-
// dbgs() << "\tCalling Function: ";
104-
// CalledF->dump();
105-
// );
106-
if (!CalledF->isIntrinsic()) {
107-
int PointerArgsAmount = countPointerArguments(CalledF);
108-
if (PointerArgsAmount > 0) {
109-
CallsOfFunctionsWithPointerArguments.insert(CallI);
97+
DenseSet<CallInst*> CallsOfFunctionsWithPointerArguments;
98+
for (auto& I : instructions(F)) {
99+
if (auto* CallI = dyn_cast<CallInst>(&I)) {
100+
auto* CalledF = CallI->getCalledFunction();
101+
if (CalledF) {
102+
LLVM_DEBUG(
103+
dbgs() << "\tCallInst";
104+
CallI->dump();
105+
dbgs() << "\tCalling Function: " << CalledF->getName() << "\n";
106+
);
107+
if (!CalledF->isIntrinsic()) {
108+
int PointerArgsAmount = countPointerArguments(CalledF);
109+
if (PointerArgsAmount > 0) {
110+
CallsOfFunctionsWithPointerArguments.insert(CallI);
111+
}
112+
}
113+
// dealing with call void bitcast (void (...)* @foo to void ()*)()
114+
} else if (auto *CstExpr = dyn_cast<ConstantExpr>(&I)) {
115+
if (CstExpr->isCast()) {
116+
auto *Arg = CstExpr->getOperand(0);
117+
if (Arg) {
118+
if (auto* CallArgI = dyn_cast<CallInst>(Arg)) {
119+
auto* CalledArgF = CallArgI->getCalledFunction();
120+
if (CalledArgF) {
121+
LLVM_DEBUG(
122+
dbgs() << "\tInternal CallInst";
123+
CallArgI->dump();
124+
dbgs() << "\tInternal Calling Function: " << CalledArgF->getName() << "\n";
125+
);
126+
if (!CalledArgF->isIntrinsic()) {
127+
int PointerArgsAmount = countPointerArguments(CalledArgF);
128+
if (PointerArgsAmount > 0) {
129+
CallsOfFunctionsWithPointerArguments.insert(CallArgI);
130+
}
110131
}
132+
}
111133
}
134+
}
112135
}
136+
}
113137
}
114-
return CallsOfFunctionsWithPointerArguments;
138+
}
139+
return CallsOfFunctionsWithPointerArguments;
115140
}
116141

117142
DenseMap<CallInst*, FunctionCallWithMemorySources> initCallsToPtrArgumentsMemorySources(DenseSet<CallInst*>& FunctionsCalls) {
@@ -123,73 +148,77 @@ DenseMap<CallInst*, FunctionCallWithMemorySources> initCallsToPtrArgumentsMemory
123148
}
124149

125150
DenseMap<CallInst*, FunctionCallWithMemorySources> fillCallsToPtrArgumentsMemorySources(
126-
DenseSet<CallInst*>& TargetFunctionsCalls,
127-
DenseSet<Value*>& MemorySources,
128-
DenseMap<Function*, FunctionResultArgumentsMemoryDependencies>& FunctionsReturnValuesDependencies) {
129-
auto CallsToPtrArgumentsMemorySources = initCallsToPtrArgumentsMemorySources(TargetFunctionsCalls);
130-
//First inst in pair is a workpiece, second - its memory source
131-
SmallVector<ValueWithMemorySources, 16> workList;
132-
for (auto* I : MemorySources) {
133-
workList.push_back(ValueWithMemorySources(I, I));
134-
}
135-
while (!workList.empty()) {
136-
auto WorkPair = workList.back();
137-
auto* I = WorkPair.mV;
138-
auto& memorySources = WorkPair.mMemorySources;
139-
workList.pop_back();
140-
for (auto* U : I->users()) {
141-
if (auto* GepU = dyn_cast<GEPOperator>(U)) {
142-
workList.push_back(ValueWithMemorySources(GepU, memorySources));
143-
} else if (auto* CastI = dyn_cast<CastInst>(U)) {
144-
workList.push_back(ValueWithMemorySources(CastI, memorySources));
145-
} else if (auto* SelectI = dyn_cast<SelectInst>(U)) {
146-
workList.push_back(ValueWithMemorySources(SelectI, memorySources));
147-
} else if (auto* LoadI = dyn_cast<LoadInst>(U)) {
148-
workList.push_back(ValueWithMemorySources(LoadI, memorySources));
149-
} else if (auto* CallI = dyn_cast<CallInst>(U)) {
150-
if (TargetFunctionsCalls.count(CallI)) {
151-
LLVM_DEBUG(
152-
dbgs() << "\tFound CallInst in TargetCalls: ";
153-
CallI->dump();
154-
dbgs() << "\tMemory Sources: \n";
155-
for (auto* S : memorySources) {
156-
dbgs() << "\t\t";
157-
S->dump();
158-
}
159-
);
160-
for (int i = 0; i < CallI->getNumArgOperands(); i++) {
161-
auto* Arg = CallI->getArgOperand(i);
162-
if (Arg == I) {
163-
if (CallsToPtrArgumentsMemorySources[CallI].mArgumentMemorySources.count(i)) {
164-
CallsToPtrArgumentsMemorySources[CallI].mArgumentMemorySources[i].insert(memorySources.begin(), memorySources.end());
165-
}
166-
else {
167-
CallsToPtrArgumentsMemorySources[CallI].mArgumentMemorySources.insert(
168-
std::make_pair(i, memorySources)
169-
);
170-
}
171-
}
172-
}
173-
}
174-
auto* TargetFunction = CallI->getCalledFunction();
175-
if (FunctionsReturnValuesDependencies.count(TargetFunction) &&
176-
!FunctionsReturnValuesDependencies[TargetFunction].mInfluencingArgumentsIndexes.empty()) {
177-
auto& InfluencingArgumentsIndexes = FunctionsReturnValuesDependencies[TargetFunction].mInfluencingArgumentsIndexes;
178-
bool shouldProcess = false;
179-
for (int i = 0; i < CallI->getNumArgOperands(); i++) {
180-
auto* Arg = CallI->getArgOperand(i);
181-
if (Arg == I && InfluencingArgumentsIndexes.count(i)) {
182-
shouldProcess = true;
183-
}
184-
}
185-
if (shouldProcess) {
186-
workList.push_back(ValueWithMemorySources(CallI, memorySources));
187-
}
188-
}
151+
DenseSet<CallInst*>& TargetFunctionsCalls,
152+
DenseSet<Value*>& MemorySources,
153+
DenseMap<Function*, FunctionResultArgumentsMemoryDependencies>& FunctionsReturnValuesDependencies) {
154+
auto CallsToPtrArgumentsMemorySources = initCallsToPtrArgumentsMemorySources(TargetFunctionsCalls);
155+
//First inst in pair is a workpiece, second - its memory source
156+
SmallVector<ValueWithMemorySources, 16> workList;
157+
for (auto* I : MemorySources) {
158+
workList.push_back(ValueWithMemorySources(I, I));
159+
}
160+
while (!workList.empty()) {
161+
auto WorkPair = workList.back();
162+
auto* I = WorkPair.mV;
163+
auto& memorySources = WorkPair.mMemorySources;
164+
workList.pop_back();
165+
for (auto* U : I->users()) {
166+
if (auto* GepOp = dyn_cast<GEPOperator>(U)) {
167+
workList.push_back(ValueWithMemorySources(GepOp, memorySources));
168+
} else if (auto* BitCastOp = dyn_cast<BitCastOperator>(U)) {
169+
workList.push_back(ValueWithMemorySources(BitCastOp, memorySources));
170+
} else if (auto* CastI = dyn_cast<CastInst>(U)) {
171+
workList.push_back(ValueWithMemorySources(CastI, memorySources));
172+
} else if (auto* SelectI = dyn_cast<SelectInst>(U)) {
173+
workList.push_back(ValueWithMemorySources(SelectI, memorySources));
174+
} else if (auto* LoadI = dyn_cast<LoadInst>(U)) {
175+
workList.push_back(ValueWithMemorySources(LoadI, memorySources));
176+
} else if (auto* CallI = dyn_cast<CallInst>(U)) {
177+
if (TargetFunctionsCalls.count(CallI)) {
178+
LLVM_DEBUG(
179+
dbgs() << "\tFound CallInst in TargetCalls: ";
180+
CallI->dump();
181+
dbgs() << "\tMemory Sources: \n";
182+
for (auto* S : memorySources) {
183+
dbgs() << "\t\t";
184+
S->dump();
185+
}
186+
);
187+
for (int i = 0; i < CallI->getNumArgOperands(); i++) {
188+
auto* Arg = CallI->getArgOperand(i);
189+
if (Arg == I) {
190+
if (CallsToPtrArgumentsMemorySources[CallI].mArgumentMemorySources.count(i)) {
191+
CallsToPtrArgumentsMemorySources[CallI].mArgumentMemorySources[i].insert(memorySources.begin(), memorySources.end());
192+
}
193+
else {
194+
CallsToPtrArgumentsMemorySources[CallI].mArgumentMemorySources.insert(
195+
std::make_pair(i, memorySources)
196+
);
197+
}
198+
}
199+
}
200+
}
201+
auto* TargetFunction = CallI->getCalledFunction();
202+
if (FunctionsReturnValuesDependencies.count(TargetFunction) &&
203+
!FunctionsReturnValuesDependencies[TargetFunction].mInfluencingArgumentsIndexes.empty()) {
204+
auto& InfluencingArgumentsIndexes = FunctionsReturnValuesDependencies[TargetFunction].mInfluencingArgumentsIndexes;
205+
bool shouldProcess = false;
206+
for (int i = 0; i < CallI->getNumArgOperands(); i++) {
207+
auto* Arg = CallI->getArgOperand(i);
208+
if (Arg == I && InfluencingArgumentsIndexes.count(i)) {
209+
shouldProcess = true;
189210
}
211+
}
212+
if (shouldProcess) {
213+
workList.push_back(ValueWithMemorySources(CallI, memorySources));
214+
}
190215
}
216+
// } else if (auto* ConstExpr = dyn_cast<UnaryConstantExpr>(U)) {
217+
// workList.push_back(ValueWithMemorySources(ConstExpr, memorySources));
218+
}
191219
}
192-
return CallsToPtrArgumentsMemorySources;
220+
}
221+
return CallsToPtrArgumentsMemorySources;
193222
}
194223

195224
// Maps Function to calls info for each pointer argument index
@@ -659,73 +688,74 @@ DenseMap<Function*, FunctionResultArgumentsMemoryDependencies> findFunctionsRetu
659688
}
660689

661690
bool RestrictionArgumentsPass::runOnModule(Module& M) {
662-
LLVM_DEBUG(
663-
dbgs() << "[RESTRICTION ARGS]" << "\n";
664-
M.dump();
665-
);
666-
667-
DenseMap<Function*, DenseSet<int>> RestrictFunctionsInfo;
668-
DenseMap<Function*, DenseSet<int>> NonRestrictFunctionsInfo;
669-
670-
auto& CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
691+
LLVM_DEBUG(
692+
dbgs() << "[RESTRICTION ARGS]" << "\n";
693+
M.dump();
694+
);
671695

672-
auto FunctionsReturnValuesDependencies = findFunctionsReturnValueDependencies(CG);
673-
std::vector<Function*> UpwardCalledFunctions;
674-
for (scc_iterator<CallGraph*> CallGraphIterator = scc_begin(&CG); !CallGraphIterator.isAtEnd(); ++CallGraphIterator) {
675-
const std::vector<CallGraphNode*>& NodeVec = *CallGraphIterator;
676-
if (NodeVec.size() > 1) {
677-
LLVM_DEBUG(
678-
dbgs() << "[RESTRICTION ARGS] Can't process recursion in the Call Graph. First func: \n";
679-
NodeVec[0]->dump();
680-
);
681-
}
682-
else {
683-
for (CallGraphNode* CGNode : *CallGraphIterator) {
684-
if (Function* F = CGNode->getFunction()) {
685-
if (F->isIntrinsic())
686-
continue;
687-
UpwardCalledFunctions.push_back(F);
688-
}
689-
}
696+
DenseMap<Function*, DenseSet<int>> RestrictFunctionsInfo;
697+
DenseMap<Function*, DenseSet<int>> NonRestrictFunctionsInfo;
698+
699+
auto& CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
700+
701+
auto FunctionsReturnValuesDependencies = findFunctionsReturnValueDependencies(CG);
702+
std::vector<Function*> UpwardCalledFunctions;
703+
for (scc_iterator<CallGraph*> CallGraphIterator = scc_begin(&CG); !CallGraphIterator.isAtEnd(); ++CallGraphIterator) {
704+
const std::vector<CallGraphNode*>& NodeVec = *CallGraphIterator;
705+
if (NodeVec.size() > 1) {
706+
LLVM_DEBUG(
707+
dbgs() << "[RESTRICTION ARGS] Can't process recursion in the Call Graph. First func: \n";
708+
NodeVec[0]->dump();
709+
);
710+
}
711+
else {
712+
for (CallGraphNode* CGNode : *CallGraphIterator) {
713+
if (Function* F = CGNode->getFunction()) {
714+
if (F->isIntrinsic())
715+
continue;
716+
UpwardCalledFunctions.push_back(F);
690717
}
718+
}
691719
}
720+
}
692721

693-
DenseSet<Value *> GlobalMemorySources = collectGlobalMemorySources(&M);
694-
695-
for (auto* F : llvm::reverse(UpwardCalledFunctions)) {
696-
runOnFunction(F, RestrictFunctionsInfo, NonRestrictFunctionsInfo, FunctionsReturnValuesDependencies, GlobalMemorySources);
697-
}
698-
699-
LLVM_DEBUG(
700-
dbgs() << "[RESTRICTION ARGS] Restrict Functions: \n";
701-
for (auto& FInfo : RestrictFunctionsInfo) {
702-
auto F = FInfo.first;
703-
auto& Args = FInfo.second;
704-
dbgs() << "\t" << F->getName() << "\n";
705-
std::set<int> orderedArgs(Args.begin(), Args.end());
706-
for (auto ArgIdx : orderedArgs) {
707-
dbgs() << "\t\t" << ArgIdx << "\n";
708-
}
722+
DenseSet<Value *> GlobalMemorySources = collectGlobalMemorySources(&M);
723+
LLVM_DEBUG(
724+
dbgs() << "[RESTRICTION ARGS] Global memory sources: \n";
725+
for (auto& GMS : GlobalMemorySources) {
726+
dbgs() << "\t";
727+
GMS->dump();
709728
}
729+
);
710730

711-
dbgs() << "[RESTRICTION ARGS] Functions with Non Restrict calls:\n";
712-
for (auto& FInfo : NonRestrictFunctionsInfo) {
713-
auto F = FInfo.first;
714-
auto& Args = FInfo.second;
715-
dbgs() << "\t" << F->getName() << "\n";
716-
std::set<int> orderedArgs(Args.begin(), Args.end());
717-
for (auto ArgIdx : orderedArgs) {
718-
dbgs() << "\t\t" << ArgIdx << "\n";
719-
}
720-
}
731+
for (auto* F : llvm::reverse(UpwardCalledFunctions)) {
732+
runOnFunction(F, RestrictFunctionsInfo, NonRestrictFunctionsInfo, FunctionsReturnValuesDependencies, GlobalMemorySources);
733+
}
734+
735+
LLVM_DEBUG(
736+
dbgs() << "[RESTRICTION ARGS] Restrict Functions: \n";
737+
for (auto& FInfo : RestrictFunctionsInfo) {
738+
auto F = FInfo.first;
739+
auto& Args = FInfo.second;
740+
dbgs() << "\t" << F->getName() << "\n";
741+
std::set<int> orderedArgs(Args.begin(), Args.end());
742+
for (auto ArgIdx : orderedArgs) {
743+
dbgs() << "\t\t" << ArgIdx << "\n";
744+
}
745+
}
721746

722-
dbgs() << "[RESTRICTION ARGS] Global vars:\n";
723-
for (auto& GV : GlobalMemorySources) {
724-
dbgs() << "\t" << GV->getName() << "\n";
725-
GV->dump();
747+
dbgs() << "[RESTRICTION ARGS] Functions with Non Restrict calls:\n";
748+
for (auto& FInfo : NonRestrictFunctionsInfo) {
749+
auto F = FInfo.first;
750+
auto& Args = FInfo.second;
751+
dbgs() << "\t" << F->getName() << "\n";
752+
std::set<int> orderedArgs(Args.begin(), Args.end());
753+
for (auto ArgIdx : orderedArgs) {
754+
dbgs() << "\t\t" << ArgIdx << "\n";
726755
}
727-
);
728-
return false;
756+
}
757+
);
758+
return false;
729759
}
730760

731761
void RestrictionArgumentsPass::getAnalysisUsage(llvm::AnalysisUsage& AU) const {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <stdlib.h>
2+
3+
const int c = 5;
4+
static int n;
5+
int b[10];
6+
7+
int foo(int *a, int* b) {
8+
return a[0] + b[0];
9+
}
10+
11+
int main(int argc, char const *argv[]) {
12+
n = 20;
13+
int (*a)[10] = malloc(sizeof(int) * 10 * n * c);
14+
return foo(a[2], b);
15+
}

0 commit comments

Comments
 (0)