-
Notifications
You must be signed in to change notification settings - Fork 13.6k
change contents of ScalarEvolution from private to protected #83052
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 13 commits
eea887c
e47436b
f55e361
8e85c06
3f378b5
14a0c6c
abb0ab4
c1d83de
66ab0c3
9b57191
5776793
bdabce8
a9c9251
7597a83
16d19f6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
|
||
#include "llvm/Analysis/AliasAnalysis.h" | ||
skewballfox marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include "llvm/Analysis/LoopAnalysisManager.h" | ||
#include "llvm/Analysis/TargetLibraryInfo.h" | ||
|
||
#include "llvm/IR/Function.h" | ||
|
||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/Transforms/Utils/ValueMapper.h" | ||
#include <deque> | ||
|
||
// TODO note this doesn't go through [loop, unreachable], and we could get more | ||
// performance by doing this can consider doing some domtree magic potentially | ||
static inline llvm::SmallPtrSet<llvm::BasicBlock *, 4> | ||
getGuaranteedUnreachable(llvm::Function *F) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @wsmoses Could you please provide some context on what's up with this whole "guaranteed unreachable" logic? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping @wsmoses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yeah so basically the gist is as follows. Suppose we have some code from the loop that results in unreacahble blocks. For example: for (int i=0; i<N; i++) {
if (i > array.size()) {
printf("Bounds error\n");
exit(1);
}
something(i);
} Again in our (enzyme) case here, we can assume we only need the loop limits if we successfully run the function (e.g. exit via a return). Thus we'd prefer to learn that this look has a bound of N, rather than unknown (since otherwise the loop could exit at an arbitrary time, via an exit call / unreachable). This actually makes a huge performance difference in practice since a lot of codes have this bounds checking (and other related things), and not deducing the fixed bound forces us to use a dynamic reallocation rather than a static allocation size of N. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The guaranteed unreachable stuff is basically finding blocks/paths which are guaranteed to result in unreachable. E.g. if you had something like
we can ignore this entire sub-cfg even if the individual blocks terminators are not unreachable (since any path through the block will necessarily result in an unreachable). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the context of SE, I think the best way to integrate this may be a list of blocks/branches/etc for SE to ignore in the context of computing the available exits. In this context we're choosing ones that are guaranteed to hit unreachable, but I think the nicer one to integrate would be something along the lines of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
llvm::SmallPtrSet<llvm::BasicBlock *, 4> knownUnreachables; | ||
if (F->empty()) | ||
return knownUnreachables; | ||
std::deque<llvm::BasicBlock *> todo; | ||
for (auto &BB : *F) { | ||
todo.push_back(&BB); | ||
} | ||
|
||
while (!todo.empty()) { | ||
llvm::BasicBlock *next = todo.front(); | ||
todo.pop_front(); | ||
|
||
if (knownUnreachables.find(next) != knownUnreachables.end()) | ||
continue; | ||
|
||
if (llvm::isa<llvm::ReturnInst>(next->getTerminator())) | ||
continue; | ||
|
||
if (llvm::isa<llvm::UnreachableInst>(next->getTerminator())) { | ||
knownUnreachables.insert(next); | ||
for (llvm::BasicBlock *Pred : predecessors(next)) { | ||
todo.push_back(Pred); | ||
} | ||
continue; | ||
} | ||
|
||
// Assume resumes don't happen | ||
// TODO consider EH | ||
if (llvm::isa<llvm::ResumeInst>(next->getTerminator())) { | ||
knownUnreachables.insert(next); | ||
for (llvm::BasicBlock *Pred : predecessors(next)) { | ||
todo.push_back(Pred); | ||
} | ||
continue; | ||
} | ||
|
||
bool unreachable = true; | ||
for (llvm::BasicBlock *Succ : llvm::successors(next)) { | ||
if (knownUnreachables.find(Succ) == knownUnreachables.end()) { | ||
unreachable = false; | ||
break; | ||
} | ||
} | ||
|
||
if (!unreachable) | ||
continue; | ||
knownUnreachables.insert(next); | ||
for (llvm::BasicBlock *Pred : llvm::predecessors(next)) { | ||
todo.push_back(Pred); | ||
} | ||
continue; | ||
} | ||
|
||
return knownUnreachables; | ||
} |
Uh oh!
There was an error while loading. Please reload this page.