forked from sampsyo/llvm-pass-skeleton
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLICM.cpp
86 lines (76 loc) · 2.75 KB
/
LICM.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Pass.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
using namespace llvm;
namespace {
/**
* Return true if an instruction has loop invariant operands given the loop it resides in and
* a set of values already marked LI
*/
bool hasLoopInvariantOperands(const Loop &L, const DenseSet<Value *> &LI, const Instruction &Inst) {
for (const auto &Use : Inst.operands()) {
if (LI.contains(&*Use))
// Operand already marked LI
continue;
if (auto *UseInst = dyn_cast<Instruction>(&*Use)) {
if (L.contains(UseInst)) {
// The def of this operand is inside the loop
return false;
}
}
}
return true;
}
struct LICMPass : public PassInfoMixin<LICMPass> {
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U) {
auto *Preheader = L.getLoopPreheader();
assert(Preheader && "Loop does not have preheader");
SmallVector<Instruction *> ToHoist;
DenseSet<Value *> LI;
bool Converged = false;
while (!Converged) {
Converged = true;
for (auto *BB : L.blocks()) {
for (auto &Inst : *BB) {
if (LI.contains(&Inst) || // Already have marked LI
!isSafeToSpeculativelyExecute(&Inst) || // Cannot hoist effectful instruction
Inst.mayReadOrWriteMemory() || // Conservatively, don't hoist any memory ops
!hasLoopInvariantOperands(L, LI, Inst)) continue; // Operands not LI;
// Otherwise, we mark this instruction as LI
LI.insert(&Inst);
ToHoist.push_back(&Inst);
Converged = false;
}
}
}
// Hoist all LI instructions to preheader
for (auto *Inst : ToHoist) {
Inst->moveBefore(Preheader->getTerminator());
}
return ToHoist.empty() ? PreservedAnalyses::all() : PreservedAnalyses::none();
};
static StringRef name() {
return "LICMPass";
}
};
} // namespace
extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return {.APIVersion = LLVM_PLUGIN_API_VERSION,
.PluginName = "LICMPass",
.PluginVersion = "v0.1",
.RegisterPassBuilderCallbacks = [](PassBuilder &PB) {
PB.registerPipelineParsingCallback(
[](StringRef name, FunctionPassManager &FPM,
ArrayRef<PassBuilder::PipelineElement>) {
if (name != "LICMPass") return false;
FPM.addPass(createFunctionToLoopPassAdaptor(LICMPass()));
return true;
});
}};
}