Skip to content

Commit e8ac7f4

Browse files
committed
[TSAR, Memory, Interproc] Add finding the range of the array in memory.
1 parent 0512966 commit e8ac7f4

File tree

4 files changed

+136
-11
lines changed

4 files changed

+136
-11
lines changed

include/tsar/Analysis/Memory/DefinedMemory.h

+30-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include "tsar/ADT/DataFlow.h"
3737
#include "tsar/ADT/DenseMapTraits.h"
3838
#include "tsar/Analysis/DFRegionInfo.h"
39+
#include "llvm/Analysis/ScalarEvolution.h"
40+
#include "tsar/Analysis/Memory/Delinearization.h"
3941
#include "tsar/Analysis/Memory/DFMemoryLocation.h"
4042
#include "tsar/Analysis/Memory/MemoryLocationRange.h"
4143
#include "tsar/Analysis/Memory/Passes.h"
@@ -365,6 +367,14 @@ class ReachDFFwk : private bcl::Uncopyable {
365367
bcl::tagged<std::unique_ptr<DefUseSet>, DefUseSet>>> InterprocDefUseInfo;
366368

367369
/// Creates data-flow framework.
370+
ReachDFFwk(AliasTree &AT, llvm::TargetLibraryInfo &TLI,
371+
const llvm::DominatorTree *DT, DefinedMemoryInfo &DefInfo,
372+
const DelinearizeInfo &DI, llvm::ScalarEvolution &SE,
373+
const llvm::DataLayout &DL) :
374+
mAliasTree(&AT), mTLI(&TLI), mDT(DT), mDefInfo(&DefInfo), mDI(&DI),
375+
mSE(&SE), mDL(&DL) {}
376+
377+
/// Creates data-flow framework.
368378
ReachDFFwk(AliasTree &AT, llvm::TargetLibraryInfo &TLI,
369379
const llvm::DominatorTree *DT, DefinedMemoryInfo &DefInfo) :
370380
mAliasTree(&AT), mTLI(&TLI), mDT(DT), mDefInfo(&DefInfo) {}
@@ -376,6 +386,14 @@ class ReachDFFwk : private bcl::Uncopyable {
376386
mAliasTree(&AT), mTLI(&TLI), mDT(DT), mDefInfo(&DefInfo),
377387
mInterprocDUInfo(&InterprocDUInfo) {}
378388

389+
/// Creates data-flow framework.
390+
ReachDFFwk(AliasTree &AT, llvm::TargetLibraryInfo &TLI,
391+
const llvm::DominatorTree *DT, DefinedMemoryInfo &DefInfo,
392+
const DelinearizeInfo &DI, llvm::ScalarEvolution &SE,
393+
const llvm::DataLayout &DL, InterprocDefUseInfo &InterprocDUInfo) :
394+
mAliasTree(&AT), mTLI(&TLI), mDT(DT), mDefInfo(&DefInfo),
395+
mDI(&DI), mSE(&SE), mDL(&DL), mInterprocDUInfo(&InterprocDUInfo) {}
396+
379397
/// Return results of interprocedural analysis or nullptr.
380398
InterprocDefUseInfo * getInterprocDefUseInfo() noexcept {
381399
return mInterprocDUInfo;
@@ -401,16 +419,27 @@ class ReachDFFwk : private bcl::Uncopyable {
401419
/// Returns dominator tree if it is available or nullptr.
402420
const llvm::DominatorTree * getDomTree() const noexcept { return mDT; }
403421

422+
/// Returns delinearize info.
423+
const DelinearizeInfo * getDelinearizeInfo() const noexcept { return mDI; }
424+
425+
/// Returns scalar evolution.
426+
llvm::ScalarEvolution * getScalarEvolution() const noexcept { return mSE; }
427+
428+
/// Returns data layout.
429+
const llvm::DataLayout & getDataLayout() const noexcept { return *mDL; }
430+
404431
/// Collapses a data-flow graph which represents a region to a one node
405432
/// in a data-flow graph of an outer region.
406433
void collapse(DFRegion *R);
407-
408434
private:
409435
AliasTree *mAliasTree;
410436
llvm::TargetLibraryInfo *mTLI;
411437
const llvm::DominatorTree *mDT;
412438
DefinedMemoryInfo *mDefInfo;
413439
InterprocDefUseInfo *mInterprocDUInfo = nullptr;
440+
const DelinearizeInfo *mDI = nullptr;
441+
llvm::ScalarEvolution *mSE = nullptr;
442+
const llvm::DataLayout *mDL;
414443
};
415444

416445
/// This represents results of interprocedural reach definition analysis.

lib/Analysis/Memory/DefinedMemory.cpp

+81-8
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,20 @@
2424

2525
#include "tsar/Analysis/Memory/DefinedMemory.h"
2626
#include "tsar/Analysis/DFRegionInfo.h"
27+
#include "tsar/Analysis/Memory/Delinearization.h"
2728
#include "tsar/Analysis/Memory/EstimateMemory.h"
2829
#include "tsar/Analysis/Memory/MemoryAccessUtils.h"
2930
#include "tsar/Analysis/Memory/Utils.h"
3031
#include "tsar/Support/Utils.h"
3132
#include "tsar/Support/IRUtils.h"
33+
#include "tsar/Support/SCEVUtils.h"
3234
#include "tsar/Unparse/Utils.h"
3335
#include <llvm/ADT/STLExtras.h>
3436
#include <llvm/Analysis/AliasAnalysis.h>
3537
#include <llvm/Analysis/AliasSetTracker.h>
3638
#include <llvm/Analysis/LoopInfo.h>
39+
#include "llvm/Analysis/ScalarEvolution.h"
40+
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
3741
#include <llvm/Analysis/ValueTracking.h>
3842
#include <llvm/Config/llvm-config.h>
3943
#include <llvm/IR/Dominators.h>
@@ -53,6 +57,8 @@ char DefinedMemoryPass::ID = 0;
5357
INITIALIZE_PASS_BEGIN(DefinedMemoryPass, "def-mem",
5458
"Defined Memory Region Analysis", false, true)
5559
LLVM_DEBUG(INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass));
60+
INITIALIZE_PASS_DEPENDENCY(DelinearizationPass)
61+
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
5662
INITIALIZE_PASS_DEPENDENCY(DFRegionInfoPass)
5763
INITIALIZE_PASS_DEPENDENCY(EstimateMemoryPass)
5864
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
@@ -67,18 +73,23 @@ bool llvm::DefinedMemoryPass::runOnFunction(Function & F) {
6773
const DominatorTree *DT = nullptr;
6874
LLVM_DEBUG(DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree());
6975
auto *DFF = cast<DFFunction>(RegionInfo.getTopLevelRegion());
76+
auto &DI = getAnalysis<DelinearizationPass>().getDelinearizeInfo();
77+
auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
7078
auto &GDM = getAnalysis<GlobalDefinedMemoryWrapper>();
79+
auto &DL = F.getParent()->getDataLayout();
7180
if (GDM) {
72-
ReachDFFwk ReachDefFwk(AliasTree, TLI, DT, mDefInfo, *GDM);
81+
ReachDFFwk ReachDefFwk(AliasTree, TLI, DT, mDefInfo, DI, SE, DL, *GDM);
7382
solveDataFlowUpward(&ReachDefFwk, DFF);
7483
} else {
75-
ReachDFFwk ReachDefFwk(AliasTree, TLI, DT, mDefInfo);
84+
ReachDFFwk ReachDefFwk(AliasTree, TLI, DT, mDefInfo, DI, SE, DL);
7685
solveDataFlowUpward(&ReachDefFwk, DFF);
7786
}
7887
return false;
7988
}
8089

8190
void DefinedMemoryPass::getAnalysisUsage(AnalysisUsage & AU) const {
91+
AU.addRequired<DelinearizationPass>();
92+
AU.addRequired<ScalarEvolutionWrapperPass>();
8293
LLVM_DEBUG(AU.addRequired<DominatorTreeWrapperPass>());
8394
AU.addRequired<DFRegionInfoPass>();
8495
AU.addRequired<EstimateMemoryPass>();
@@ -579,6 +590,49 @@ void ReachDFFwk::collapse(DFRegion *R) {
579590
// of execution paths of iterations of the loop.
580591
DFNode *ExitNode = R->getExitNode();
581592
const DefinitionInfo &ExitingDefs = RT::getValue(ExitNode, this);
593+
auto calcArrayLocation = [this, R](const tsar::MemoryLocationRange &Loc) {
594+
MemoryLocationRange arrayLoc;
595+
arrayLoc.Ptr = nullptr;
596+
auto LocInfo = getDelinearizeInfo()->findRange(Loc.Ptr);
597+
if (LocInfo.first && LocInfo.first->isDelinearized() &&
598+
LocInfo.second->isValid()) {
599+
for (auto *S : LocInfo.second->Subscripts) {
600+
auto *SE = getScalarEvolution();
601+
auto AddRecInfo = computeSCEVAddRec(S, *SE);
602+
if (AddRecInfo.second) {
603+
auto SCEV = AddRecInfo.first;
604+
if (static_cast<SCEVTypes>(SCEV->getSCEVType()) != scAddRecExpr) {
605+
break;
606+
}
607+
auto addRecExpr = cast<SCEVAddRecExpr>(SCEV);
608+
if (auto *DFL = dyn_cast<DFLoop>(R)) {
609+
auto *L = DFL->getLoop();
610+
auto maxTripCount = SE->getSmallConstantMaxTripCount(L);
611+
if (maxTripCount == 0)
612+
break;
613+
auto rangeMin = SE->getSignedRangeMin(SCEV);
614+
auto rangeMax = SE->getSignedRangeMax(SCEV);
615+
auto *stepSCEV = addRecExpr->getOperand(1);
616+
if (static_cast<SCEVTypes>(stepSCEV->getSCEVType()) !=
617+
scConstant)
618+
break;
619+
auto stepNumber = *cast<SCEVConstant>(stepSCEV)->
620+
getValue()->getValue().getRawData();
621+
if (stepNumber > 1)
622+
break;
623+
PointerType *pointerType = cast<PointerType>(
624+
LocInfo.first->getBase()->getType());
625+
auto arrayElementSize = getDataLayout().getTypeStoreSize(
626+
pointerType->getElementType());
627+
arrayLoc = Loc;
628+
arrayLoc.LowerBound = *rangeMin.getRawData() * arrayElementSize;
629+
arrayLoc.UpperBound = (*rangeMax.getRawData()+1) * arrayElementSize;
630+
}
631+
}
632+
}
633+
}
634+
return arrayLoc;
635+
};
582636
for (DFNode *N : R->getNodes()) {
583637
auto DefItr = getDefInfo().find(N);
584638
assert(DefItr != getDefInfo().end() &&
@@ -624,8 +678,13 @@ void ReachDFFwk::collapse(DFRegion *R) {
624678
break;
625679
}
626680
}
627-
if (!RS->getIn().MustReach.contain(Loc) && !(StartInLoop && EndInLoop))
628-
DefUse->addUse(Loc);
681+
if (!RS->getIn().MustReach.contain(Loc) && !(StartInLoop && EndInLoop)) {
682+
auto arrayLoc = calcArrayLocation(Loc);
683+
if (arrayLoc.Ptr != nullptr)
684+
DefUse->addUse(arrayLoc);
685+
else
686+
DefUse->addUse(Loc);
687+
}
629688
}
630689
// It is possible that some locations are only written in the loop.
631690
// In this case this locations are not located at set of node uses but
@@ -648,13 +707,27 @@ void ReachDFFwk::collapse(DFRegion *R) {
648707
// X = ...;
649708
// }
650709
for (auto &Loc : DU->getDefs()) {
651-
if (ExitingDefs.MustReach.contain(Loc))
652-
DefUse->addDef(Loc);
710+
if (ExitingDefs.MustReach.contain(Loc)) {
711+
auto arrayLoc = calcArrayLocation(Loc);
712+
if (arrayLoc.Ptr != nullptr)
713+
DefUse->addDef(arrayLoc);
714+
else
715+
DefUse->addDef(Loc);
716+
} else {
717+
auto arrayLoc = calcArrayLocation(Loc);
718+
if (arrayLoc.Ptr != nullptr)
719+
DefUse->addMayDef(arrayLoc);
720+
else
721+
DefUse->addMayDef(Loc);
722+
}
723+
}
724+
for (auto &Loc : DU->getMayDefs()) {
725+
auto arrayLoc = calcArrayLocation(Loc);
726+
if (arrayLoc.Ptr != nullptr)
727+
DefUse->addMayDef(arrayLoc);
653728
else
654729
DefUse->addMayDef(Loc);
655730
}
656-
for (auto &Loc : DU->getMayDefs())
657-
DefUse->addMayDef(Loc);
658731
DefUse->addExplicitAccesses(DU->getExplicitAccesses());
659732
DefUse->addExplicitUnknowns(DU->getExplicitUnknowns());
660733
for (auto Loc : DU->getAddressAccesses())

lib/Analysis/Memory/GlobalDefinedMemory.cpp

+19-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@
2222
//===----------------------------------------------------------------------===//
2323

2424
#include "tsar/Analysis/Attributes.h"
25+
#include "tsar/Analysis/Memory/Delinearization.h"
26+
#include "llvm/Analysis/ScalarEvolution.h"
2527
#include "tsar/Analysis/Memory/DefinedMemory.h"
2628
#include "tsar/Analysis/Memory/EstimateMemory.h"
2729
#include "tsar/Analysis/Memory/Passes.h"
30+
#include "tsar/Support/GlobalOptions.h"
2831
#include "tsar/Support/PassProvider.h"
2932
#include <bcl/utility.h>
3033
#include <llvm/ADT/SCCIterator.h>
@@ -90,7 +93,9 @@ class GlobalDefinedMemoryStorage :
9093
using GlobalDefinedMemoryProvider = FunctionPassProvider<
9194
DFRegionInfoPass,
9295
EstimateMemoryPass,
93-
DominatorTreeWrapperPass>;
96+
DominatorTreeWrapperPass,
97+
DelinearizationPass,
98+
ScalarEvolutionWrapperPass>;
9499
}
95100

96101
INITIALIZE_PROVIDER_BEGIN(GlobalDefinedMemoryProvider,
@@ -99,6 +104,7 @@ INITIALIZE_PROVIDER_BEGIN(GlobalDefinedMemoryProvider,
99104
INITIALIZE_PASS_DEPENDENCY(DFRegionInfoPass)
100105
INITIALIZE_PASS_DEPENDENCY(EstimateMemoryPass)
101106
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
107+
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
102108
INITIALIZE_PROVIDER_END(GlobalDefinedMemoryProvider, "global-def-mem-provider",
103109
"Global Defined Memory Analysis (Provider)")
104110

@@ -120,6 +126,7 @@ INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
120126
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
121127
INITIALIZE_PASS_DEPENDENCY(GlobalDefinedMemoryProvider)
122128
INITIALIZE_PASS_DEPENDENCY(GlobalDefinedMemoryWrapper)
129+
INITIALIZE_PASS_DEPENDENCY(GlobalOptionsImmutableWrapper)
123130
INITIALIZE_PASS_END(GlobalDefinedMemory, "global-def-mem",
124131
"Global Defined Memory Analysis", true, true)
125132

@@ -128,6 +135,8 @@ void GlobalDefinedMemory::getAnalysisUsage(AnalysisUsage &AU) const {
128135
AU.addRequired<GlobalDefinedMemoryWrapper>();
129136
AU.addRequired<CallGraphWrapperPass>();
130137
AU.addRequired<TargetLibraryInfoWrapperPass>();
138+
AU.addRequired<GlobalOptionsImmutableWrapper>();
139+
AU.addRequired<ScalarEvolutionWrapperPass>();
131140
AU.setPreservesAll();
132141
}
133142

@@ -144,8 +153,14 @@ bool GlobalDefinedMemory::runOnModule(Module &SCC) {
144153
if (!Wrapper)
145154
return false;
146155
Wrapper->clear();
156+
auto &GO = getAnalysis<GlobalOptionsImmutableWrapper>().getOptions();
157+
GlobalDefinedMemoryProvider::initialize<GlobalOptionsImmutableWrapper>(
158+
[&GO](GlobalOptionsImmutableWrapper &Wrapper) {
159+
Wrapper.setOptions(&GO);
160+
});
147161
auto &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
148162
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
163+
auto &DL = SCC.getDataLayout();
149164
for (scc_iterator<CallGraph *> SCC = scc_begin(&CG); !SCC.isAtEnd(); ++SCC) {
150165
/// TODO (kaniandr@gmail.com): implement analysis in case of recursion.
151166
if (SCC->size() > 1)
@@ -164,11 +179,13 @@ bool GlobalDefinedMemory::runOnModule(Module &SCC) {
164179
auto &Provider = getAnalysis<GlobalDefinedMemoryProvider>(*F);
165180
auto &RegInfo = Provider.get<DFRegionInfoPass>().getRegionInfo();
166181
auto &AT = Provider.get<EstimateMemoryPass>().getAliasTree();
182+
auto &DI = Provider.get<DelinearizationPass>().getDelinearizeInfo();
183+
auto &SE = Provider.get<ScalarEvolutionWrapperPass>().getSE();
167184
const DominatorTree *DT = nullptr;
168185
LLVM_DEBUG(DT = &Provider.get<DominatorTreeWrapperPass>().getDomTree());
169186
auto *DFF = cast<DFFunction>(RegInfo.getTopLevelRegion());
170187
DefinedMemoryInfo DefInfo;
171-
ReachDFFwk ReachDefFwk(AT, TLI, DT, DefInfo, *Wrapper);
188+
ReachDFFwk ReachDefFwk(AT, TLI, DT, DefInfo, DI, SE, DL, *Wrapper);
172189
solveDataFlowUpward(&ReachDefFwk, DFF);
173190
auto DefUseSetItr = ReachDefFwk.getDefInfo().find(DFF);
174191
assert(DefUseSetItr != ReachDefFwk.getDefInfo().end() &&

lib/Analysis/Memory/GlobalLiveMemory.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ using CallList = std::vector<
104104
using LiveMemoryForCalls = DenseMap<const Function *, CallList>;
105105

106106
using GlobalLiveMemoryProvider = FunctionPassProvider<
107+
GlobalOptionsImmutableWrapper,
107108
DFRegionInfoPass,
108109
DefinedMemoryPass,
109110
DominatorTreeWrapperPass>;
@@ -187,6 +188,7 @@ INITIALIZE_PROVIDER_BEGIN(GlobalLiveMemoryProvider, "global-live-mem-provider",
187188
INITIALIZE_PASS_DEPENDENCY(DFRegionInfoPass)
188189
INITIALIZE_PASS_DEPENDENCY(DefinedMemoryPass)
189190
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
191+
INITIALIZE_PASS_DEPENDENCY(GlobalOptionsImmutableWrapper)
190192
INITIALIZE_PROVIDER_END(GlobalLiveMemoryProvider, "global-live-mem-provider",
191193
"Global Live Memory Analysis (Provider)")
192194

@@ -263,6 +265,10 @@ bool GlobalLiveMemory::runOnModule(Module &M) {
263265
return false;
264266
Worklist.push_back(CGN);
265267
}
268+
GlobalLiveMemoryProvider::initialize<GlobalOptionsImmutableWrapper>(
269+
[&GO](GlobalOptionsImmutableWrapper &Wrapper) {
270+
Wrapper.setOptions(&GO);
271+
});
266272
auto &GDM = getAnalysis<GlobalDefinedMemoryWrapper>();
267273
if (GDM) {
268274
GlobalLiveMemoryProvider::initialize<GlobalDefinedMemoryWrapper>(

0 commit comments

Comments
 (0)