LLVM: lib/Target/BPF/BPFAdjustOpt.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
17#include "llvm/IR/IntrinsicsBPF.h"
25
26#define DEBUG_TYPE "bpf-adjust-opt"
27
28using namespace llvm;
30
33 cl::desc("BPF: Disable Serializing ICMP insns."),
35
37 "bpf-disable-avoid-speculation", cl::Hidden,
38 cl::desc("BPF: Disable Avoiding Speculative Code Motion."),
40
41namespace {
42class BPFAdjustOptImpl {
43 struct PassThroughInfo {
49 };
50
51public:
52 BPFAdjustOptImpl(Module *M) : M(M) {}
53
54 bool run();
55
56private:
59
60 bool adjustICmpToBuiltin();
61 void adjustBasicBlock(BasicBlock &BB);
62 bool serializeICMPCrossBB(BasicBlock &BB);
63 void adjustInst(Instruction &I);
64 bool serializeICMPInBB(Instruction &I);
65 bool avoidSpeculation(Instruction &I);
66 bool insertPassThrough();
67};
68
69}
70
71bool BPFAdjustOptImpl::run() {
72 bool Changed = adjustICmpToBuiltin();
73
74 for (Function &F : *M)
75 for (auto &BB : F) {
76 adjustBasicBlock(BB);
77 for (auto &I : BB)
78 adjustInst(I);
79 }
80 return insertPassThrough() || Changed;
81}
82
83
84
85
86
87
88
89
90
91bool BPFAdjustOptImpl::adjustICmpToBuiltin() {
93 ICmpInst *ToBeDeleted = nullptr;
94 for (Function &F : *M)
95 for (auto &BB : F)
96 for (auto &I : BB) {
97 if (ToBeDeleted) {
99 ToBeDeleted = nullptr;
100 }
101
103 if (!Icmp)
104 continue;
105
106 Value *Op0 = Icmp->getOperand(0);
108 continue;
109
111 if (!ConstOp1)
112 continue;
113
114 auto ConstOp1Val = ConstOp1->getValue().getZExtValue();
115 auto Op = Icmp->getPredicate();
116 if (Op == ICmpInst::ICMP_ULT || Op == ICmpInst::ICMP_UGE) {
117 if ((ConstOp1Val - 1) & ConstOp1Val)
118 continue;
119 } else if (Op == ICmpInst::ICMP_ULE || Op == ICmpInst::ICMP_UGT) {
120 if (ConstOp1Val & (ConstOp1Val + 1))
121 continue;
122 } else {
123 continue;
124 }
125
127 ConstantInt::get(Type::getInt32Ty(BB.getContext()), Op);
129 M, Intrinsic::bpf_compare, {Op0->getType(), ConstOp1->getType()});
130 auto *NewInst = CallInst::Create(Fn, {Opcode, Op0, ConstOp1});
132 Icmp->replaceAllUsesWith(NewInst);
134 ToBeDeleted = Icmp;
135 }
136
138}
139
140bool BPFAdjustOptImpl::insertPassThrough() {
141 for (auto &Info : PassThroughs) {
143 M, Info.UsedInst->getParent(), Info.Input, Info.UsedInst);
144 Info.UsedInst->setOperand(Info.OpIdx, CI);
145 }
146
147 return !PassThroughs.empty();
148}
149
150
151
152bool BPFAdjustOptImpl::serializeICMPInBB(Instruction &I) {
153
154
155
156
157
158
159
160
161
162 Value *Op0, *Op1;
163
165 return false;
167 if (!Icmp1)
168 return false;
170 if (!Icmp2)
171 return false;
172
173 Value *Icmp1Op0 = Icmp1->getOperand(0);
174 Value *Icmp2Op0 = Icmp2->getOperand(0);
175 if (Icmp1Op0 != Icmp2Op0)
176 return false;
177
178
179
180 PassThroughInfo Info(Icmp1, &I, 0);
181 PassThroughs.push_back(Info);
182 return true;
183}
184
185
186
187bool BPFAdjustOptImpl::serializeICMPCrossBB(BasicBlock &BB) {
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
213 if (!B2)
214 return false;
215
217 if (!B1)
218 return false;
219
222 if (!BI || !BI->isConditional())
223 return false;
226 return false;
227 Value *B2Op0 = Cond->getOperand(0);
228 auto Cond2Op = Cond->getPredicate();
229
232 if (!BI || !BI->isConditional())
233 return false;
236 return false;
237 Value *B1Op0 = Cond->getOperand(0);
238 auto Cond1Op = Cond->getPredicate();
239
240 if (B1Op0 != B2Op0)
241 return false;
242
243 if (Cond1Op == ICmpInst::ICMP_SGT || Cond1Op == ICmpInst::ICMP_SGE) {
244 if (Cond2Op != ICmpInst::ICMP_SLT && Cond2Op != ICmpInst::ICMP_SLE)
245 return false;
246 } else if (Cond1Op == ICmpInst::ICMP_SLT || Cond1Op == ICmpInst::ICMP_SLE) {
247 if (Cond2Op != ICmpInst::ICMP_SGT && Cond2Op != ICmpInst::ICMP_SGE)
248 return false;
249 } else if (Cond1Op == ICmpInst::ICMP_ULT || Cond1Op == ICmpInst::ICMP_ULE) {
250 if (Cond2Op != ICmpInst::ICMP_UGT && Cond2Op != ICmpInst::ICMP_UGE)
251 return false;
252 } else if (Cond1Op == ICmpInst::ICMP_UGT || Cond1Op == ICmpInst::ICMP_UGE) {
253 if (Cond2Op != ICmpInst::ICMP_ULT && Cond2Op != ICmpInst::ICMP_ULE)
254 return false;
255 } else {
256 return false;
257 }
258
259 PassThroughInfo Info(Cond, BI, 0);
260 PassThroughs.push_back(Info);
261
262 return true;
263}
264
265
266
267bool BPFAdjustOptImpl::avoidSpeculation(Instruction &I) {
272 return false;
273 }
274 }
275
277 return false;
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
300 for (User *U : I.users()) {
302 if (!Inst)
303 continue;
304
305
306
308 Value *Icmp1Op1 = Icmp1->getOperand(1);
310 return false;
312 continue;
313 }
314
315
316 if (Inst->getParent() == I.getParent())
317 continue;
318
319
320
321
322 for (auto &I2 : *Inst->getParent()) {
324 return false;
326 return false;
327 if (&I2 == Inst)
328 break;
329 }
330
331
332
333 if (Inst->getOpcode() == Instruction::ZExt ||
334 Inst->getOpcode() == Instruction::SExt) {
335 PassThroughInfo Info(&I, Inst, 0);
338
339 unsigned i, e;
340 for (i = 1, e = GI->getNumOperands(); i != e; ++i) {
341 Value *V = GI->getOperand(i);
342 if (V == &I)
343 break;
344 }
345 if (i == e)
346 continue;
347
348 PassThroughInfo Info(&I, GI, i);
350 }
351 }
352
354 return false;
355
357 return true;
358}
359
360void BPFAdjustOptImpl::adjustBasicBlock(BasicBlock &BB) {
362 return;
363}
364
365void BPFAdjustOptImpl::adjustInst(Instruction &I) {
367 return;
369 return;
370}
371
static cl::opt< bool > DisableBPFserializeICMP("bpf-disable-serialize-icmp", cl::Hidden, cl::desc("BPF: Disable Serializing ICMP insns."), cl::init(false))
static cl::opt< bool > DisableBPFavoidSpeculation("bpf-disable-avoid-speculation", cl::Hidden, cl::desc("BPF: Disable Avoiding Speculative Code Motion."), cl::init(false))
Analysis containing CSE Info
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
static bool isCandidate(const MachineInstr *MI, Register &DefedReg, Register FrameReg)
MachineInstr unsigned OpIdx
const SmallVectorImpl< MachineOperand > & Cond
The Input class is used to parse a yaml document into in-memory structs and vectors.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition BPFAdjustOpt.cpp:372
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
Type * getType() const
All values are typed, get the type of this value.
const ParentTy * getParent() const
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
bool match(Val *V, const Pattern &P)
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.