84 #define DEBUG_TYPE "divergence"
101 bool runOnFunction(
Function &
F)
override;
107 bool isDivergent(
const Value *V)
const {
return DivergentValues.count(V); }
109 bool isUniform(
const Value *V)
const {
return !isDivergent(V); }
133 : F(F), TTI(TTI), DT(DT), PDT(PDT), DV(DV) {}
134 void populateWithSourcesOfDivergence();
139 void exploreDataDependency(
Value *V);
148 void findUsersOutsideInfluenceRegion(
155 std::vector<Value *> Worklist;
159 void DivergencePropagator::populateWithSourcesOfDivergence() {
163 if (TTI.isSourceOfDivergence(&
I)) {
164 Worklist.push_back(&
I);
168 for (
auto &Arg :
F.args()) {
169 if (TTI.isSourceOfDivergence(&Arg)) {
170 Worklist.push_back(&Arg);
176 void DivergencePropagator::exploreSyncDependency(
TerminatorInst *TI) {
187 BasicBlock *IPostDom = PDT.getNode(ThisBB)->getIDom()->getBlock();
188 if (IPostDom ==
nullptr)
191 for (
auto I = IPostDom->
begin(); isa<PHINode>(
I); ++
I) {
194 if (!cast<PHINode>(
I)->hasConstantValue() && DV.insert(
I).second)
195 Worklist.push_back(
I);
218 computeInfluenceRegion(ThisBB, IPostDom, InfluenceRegion);
224 while (InfluenceRegion.
count(InfluencedBB)) {
225 for (
auto &
I : *InfluencedBB)
226 findUsersOutsideInfluenceRegion(
I, InfluenceRegion);
228 if (IDomNode ==
nullptr)
230 InfluencedBB = IDomNode->
getBlock();
234 void DivergencePropagator::findUsersOutsideInfluenceRegion(
239 if (DV.insert(UserInst).second)
240 Worklist.push_back(UserInst);
245 void DivergencePropagator::computeInfluenceRegion(
248 assert(PDT.properlyDominates(End, Start) &&
249 "End does not properly dominate Start");
250 std::vector<BasicBlock *> InfluenceStack;
251 InfluenceStack.push_back(Start);
252 InfluenceRegion.
insert(Start);
253 while (!InfluenceStack.empty()) {
255 InfluenceStack.pop_back();
257 if (End != Succ && InfluenceRegion.
insert(Succ).second)
258 InfluenceStack.push_back(Succ);
263 void DivergencePropagator::exploreDataDependency(
Value *V) {
267 if (DV.insert(UserInst).second)
268 Worklist.push_back(UserInst);
272 void DivergencePropagator::propagate() {
274 while (!Worklist.empty()) {
275 Value *V = Worklist.back();
281 exploreSyncDependency(TI);
283 exploreDataDependency(V);
290 return new DivergenceAnalysis();
293 bool DivergenceAnalysis::runOnFunction(
Function &
F) {
294 auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
295 if (TTIWP ==
nullptr)
304 DivergentValues.clear();
305 DivergencePropagator DP(F, TTI,
306 getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
307 getAnalysis<PostDominatorTree>(), DivergentValues);
308 DP.populateWithSourcesOfDivergence();
314 if (DivergentValues.empty())
316 const Value *FirstDivergentValue = *DivergentValues.begin();
318 if (
const Argument *Arg = dyn_cast<Argument>(FirstDivergentValue)) {
321 dyn_cast<Instruction>(FirstDivergentValue)) {
328 for (
auto &Arg : F->
args()) {
329 if (DivergentValues.count(&Arg))
330 OS <<
"DIVERGENT: " << Arg <<
"\n";
334 if (DivergentValues.count(&I))
335 OS <<
"DIVERGENT:" << I <<
"\n";
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVM Argument representation.
const Instruction & back() const
A Module instance is used to store all the information related to an LLVM module. ...
FunctionPass * createDivergenceAnalysisPass()
end namespace anonymous
const Function * getParent() const
Return the enclosing method, or null if none.
iterator begin()
Instruction iterator methods.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Base class for the actual dominator tree node.
void initializeDivergenceAnalysisPass(PassRegistry &)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
unsigned getNumSuccessors() const
Return the number of successors that this terminator has.
Subclasses of this class are all able to terminate a basic block.
LLVM Basic Block Representation.
size_type count(const ValueT &V) const
Return 1 if the specified key is in the set, 0 otherwise.
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
std::pair< iterator, bool > insert(const ValueT &V)
DomTreeNodeBase< NodeT > * getIDom() const
void setPreservesAll()
Set by analyses that do not transform their input at all.
iterator_range< user_iterator > users()
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
iterator_range< inst_iterator > inst_range(Function *F)
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
succ_range successors(BasicBlock *BB)
This class implements an extremely fast bulk output stream that can only output to a stream...
INITIALIZE_PASS_BEGIN(DivergenceAnalysis,"divergence","Divergence Analysis", false, true) INITIALIZE_PASS_END(DivergenceAnalysis
Legacy analysis pass which computes a DominatorTree.
DivergencePropagator(Function &F, TargetTransformInfo &TTI, DominatorTree &DT, PostDominatorTree &PDT, DenseSet< const Value * > &DV)
const BasicBlock * getParent() const
iterator_range< arg_iterator > args()