LLVM: lib/Target/BPF/BPFCheckAndAdjustIR.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
30#include "llvm/IR/IntrinsicsBPF.h"
36
37#define DEBUG_TYPE "bpf-check-and-opt-ir"
38
39using namespace llvm;
40
41namespace {
42
43class BPFCheckAndAdjustIR final : public ModulePass {
44 bool runOnModule(Module &F) override;
45
46public:
47 static char ID;
49 void getAnalysisUsage(AnalysisUsage &AU) const override;
50
51private:
52 void checkIR(Module &M);
53 bool adjustIR(Module &M);
54 bool removePassThroughBuiltin(Module &M);
55 bool removeCompareBuiltin(Module &M);
56 bool sinkMinMax(Module &M);
57 bool removeGEPBuiltins(Module &M);
58 bool insertASpaceCasts(Module &M);
59};
60}
61
62char BPFCheckAndAdjustIR::ID = 0;
64 false, false)
65
67 return new BPFCheckAndAdjustIR();
68}
69
70void BPFCheckAndAdjustIR::checkIR(Module &M) {
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 for (Function &F : M)
87 for (auto &BB : F)
88 for (auto &I : BB) {
91 continue;
94 if (!GV)
95 continue;
99 }
100 }
101}
102
103bool BPFCheckAndAdjustIR::removePassThroughBuiltin(Module &M) {
104
105
106
108 CallInst *ToBeDeleted = nullptr;
109 for (Function &F : M)
110 for (auto &BB : F)
111 for (auto &I : BB) {
112 if (ToBeDeleted) {
114 ToBeDeleted = nullptr;
115 }
116
119 continue;
121 if (!GV)
122 continue;
123 if (!GV->getName().starts_with("llvm.bpf.passthrough"))
124 continue;
128 ToBeDeleted = Call;
129 }
131}
132
133bool BPFCheckAndAdjustIR::removeCompareBuiltin(Module &M) {
134
135
136
138 CallInst *ToBeDeleted = nullptr;
139 for (Function &F : M)
140 for (auto &BB : F)
141 for (auto &I : BB) {
142 if (ToBeDeleted) {
144 ToBeDeleted = nullptr;
145 }
146
149 continue;
151 if (!GV)
152 continue;
153 if (!GV->getName().starts_with("llvm.bpf.compare"))
154 continue;
155
160
163
164 auto *ICmp = new ICmpInst(Opcode, Arg1, Arg2);
166
168 ToBeDeleted = Call;
169 }
171}
172
185
188
189
190
191
192
195 V = ZExt->getOperand(0);
196 Info.ZExt = ZExt;
198 V = SExt->getOperand(0);
199 Info.SExt = SExt;
200 }
201
204 return false;
205
207 if (!Called)
208 return false;
209
210 switch (Called->getIntrinsicID()) {
211 case Intrinsic::smin:
212 case Intrinsic::umin:
213 case Intrinsic::smax:
214 case Intrinsic::umax:
215 break;
216 default:
217 return false;
218 }
219
221 return false;
222
224
225 return true;
226 };
227
230 if (Info.SExt) {
231 if (Info.SExt->getType() == V->getType())
232 return V;
233 return Builder.CreateSExt(V, Info.SExt->getType());
234 }
235 if (Info.ZExt) {
236 if (Info.ZExt->getType() == V->getType())
237 return V;
238 return Builder.CreateZExt(V, Info.ZExt->getType());
239 }
240 return V;
241 };
242
245
246
247
248
249
250
251
252
255 if (!ICmp)
256 continue;
258 continue;
262 bool FirstMinMax = IsMinMaxCall(ICmp->getOperand(0), First);
263 bool SecondMinMax = IsMinMaxCall(ICmp->getOperand(1), Second);
264 if (!(FirstMinMax ^ SecondMinMax))
265 continue;
267 }
268
269
270
271 for (auto &Info : SinkList) {
277 IID != Intrinsic::smax)
278 continue;
279
282 Value *A = ZeroOrSignExtend(Builder, MinMax->getArgOperand(0), Info);
283 Value *B = ZeroOrSignExtend(Builder, MinMax->getArgOperand(1), Info);
284 bool IsMin = IID == Intrinsic::smin || IID == Intrinsic::umin;
285 bool IsMax = IID == Intrinsic::smax || IID == Intrinsic::umax;
288 assert(IsMin ^ IsMax);
289 assert(IsLess ^ IsGreater);
290
291 Value *Replacement;
292 Value *LHS = Builder.CreateICmp(P, X, A);
293 Value *RHS = Builder.CreateICmp(P, X, B);
294 if ((IsLess && IsMin) || (IsGreater && IsMax))
295
296
297 Replacement = Builder.CreateLogicalAnd(LHS, RHS);
298 else
299
300
301 Replacement = Builder.CreateLogicalOr(LHS, RHS);
302
304
308 I->eraseFromParent();
309
311 }
312
314}
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343bool BPFCheckAndAdjustIR::sinkMinMax(Module &M) {
345
346 for (Function &F : M) {
347 if (F.isDeclaration())
348 continue;
349
350 LoopInfo &LI = getAnalysis(F).getLoopInfo();
351 for (Loop *L : LI)
352 for (BasicBlock *BB : L->blocks()) {
353
354 Loop *BBLoop = LI.getLoopFor(BB);
356 return LI.getLoopFor(I->getParent()) != BBLoop;
357 };
359 }
360 }
361
363}
364
365void BPFCheckAndAdjustIR::getAnalysisUsage(AnalysisUsage &AU) const {
367}
368
371 GEP->insertBefore(Call->getIterator());
372 Load->insertBefore(Call->getIterator());
373 Call->replaceAllUsesWith(Load);
374 Call->eraseFromParent();
375}
376
379 GEP->insertBefore(Call->getIterator());
380 Store->insertBefore(Call->getIterator());
381 Call->eraseFromParent();
382}
383
387 for (auto &BB : F)
388 for (auto &Insn : BB)
390 if (auto *Called = Call->getCalledFunction())
391 switch (Called->getIntrinsicID()) {
392 case Intrinsic::bpf_getelementptr_and_load:
394 break;
395 case Intrinsic::bpf_getelementptr_and_store:
397 break;
398 }
399
400 if (GEPLoads.empty() && GEPStores.empty())
401 return false;
402
405
406 return true;
407}
408
409
410
411
412
413bool BPFCheckAndAdjustIR::removeGEPBuiltins(Module &M) {
415 for (auto &F : M)
418}
419
420
421
422
423
424
425
426
427
428
431 auto It = Cache.find(ToWrap);
432 if (It != Cache.end())
433 return It->getSecond();
434
436 Value *Ptr = GEP->getPointerOperand();
439 auto *NewGEP = GEP->clone();
440 NewGEP->insertAfter(GEP->getIterator());
442 NewGEP->setOperand(GEP->getPointerOperandIndex(), WrappedPtr);
443 NewGEP->setName(GEP->getName());
444 Cache[ToWrap] = NewGEP;
445 return NewGEP;
446 }
447
450 IB.SetInsertPoint(*InsnPtr->getInsertionPointAfterDef());
451 else
452 IB.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt());
453 auto *ASZeroPtrTy = IB.getPtrTy(0);
454 auto *ACast = IB.CreateAddrSpaceCast(ToWrap, ASZeroPtrTy, ToWrap->getName());
455 Cache[ToWrap] = ACast;
456 return ACast;
457}
458
459
460
462 unsigned OpNum) {
463 Value *OldOp = I->getOperand(OpNum);
465 return;
466
468 I->setOperand(OpNum, NewOp);
469
470
471 for (;;) {
473 if (!OldGEP)
474 break;
475 if (!OldGEP->use_empty())
476 break;
477 OldOp = OldGEP->getPointerOperand();
478 OldGEP->eraseFromParent();
479 }
480}
481
485 if (PTy->getAddressSpace() == 0)
486 return P;
487 }
489}
490
496
499 if (OldDst == NewDst)
500 return nullptr;
501
502
505
508 bool IsVolatile = MS->isVolatile();
509
510 if (ID == Intrinsic::memset)
511 return B.CreateMemSet(NewDst, Val, Len, Align, IsVolatile,
512 MI->getAAMetadata());
513 else
514 return B.CreateMemSetInline(NewDst, Align, Val, Len, IsVolatile,
515 MI->getAAMetadata());
516}
517
523
528 if (OldDst == NewDst && OldSrc == NewSrc)
529 return nullptr;
530
531
533
535 MaybeAlign DstAlign = MT->getDestAlign();
536 MaybeAlign SrcAlign = MT->getSourceAlign();
537 bool IsVolatile = MT->isVolatile();
538
539 return B.CreateMemTransferInst(ID, NewDst, DstAlign, NewSrc, SrcAlign, Len,
540 IsVolatile, MI->getAAMetadata());
541}
542
547
552 if (OldDst == NewDst && OldSrc == NewSrc)
553 return nullptr;
554
555
557
559 MaybeAlign DstAlign = MT->getDestAlign();
560 MaybeAlign SrcAlign = MT->getSourceAlign();
561 bool IsVolatile = MT->isVolatile();
562
563 return B.CreateMemMove(NewDst, DstAlign, NewSrc, SrcAlign, Len, IsVolatile,
564 MI->getAAMetadata());
565}
566
567
568
569
570
571
572
573
574
575
576
577
578bool BPFCheckAndAdjustIR::insertASpaceCasts(Module &M) {
580 for (Function &F : M) {
581 DenseMap<Value *, Value *> CastsCache;
582 for (BasicBlock &BB : F) {
584 unsigned PtrOpNum;
585
587 PtrOpNum = LD->getPointerOperandIndex();
589 continue;
590 }
592 PtrOpNum = ST->getPointerOperandIndex();
594 continue;
595 }
597 PtrOpNum = CmpXchg->getPointerOperandIndex();
599 continue;
600 }
602 PtrOpNum = RMW->getPointerOperandIndex();
604 continue;
605 }
606
608 if (!CI)
609 continue;
610
612 if (!Callee || ->isIntrinsic())
613 continue;
614
615
617 bool IsSet = ID == Intrinsic::memset || ID == Intrinsic::memset_inline;
618 bool IsCpy = ID == Intrinsic::memcpy || ID == Intrinsic::memcpy_inline;
619 bool IsMove = ID == Intrinsic::memmove;
620 if (!IsSet && !IsCpy && !IsMove)
621 continue;
622
624 if (IsSet)
626 else if (IsCpy)
628 else
630
631 if (!New)
632 continue;
633
634 I.replaceAllUsesWith(New);
636 I.eraseFromParent();
637 }
638 }
640 }
641
642
643 for (GlobalVariable &G : M.globals()) {
644 if (G.getAddressSpace() == 0 || G.hasSection())
645 continue;
646 SmallString<16> SecName;
647 raw_svector_ostream OS(SecName);
648 OS << ".addr_space." << G.getAddressSpace();
649 G.setSection(SecName);
650
651 G.setConstant(false);
652 }
654}
655
656bool BPFCheckAndAdjustIR::adjustIR(Module &M) {
657 bool Changed = removePassThroughBuiltin(M);
663}
664
665bool BPFCheckAndAdjustIR::runOnModule(Module &M) {
666 checkIR(M);
667 return adjustIR(M);
668}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
static Instruction * aspaceMemSet(Intrinsic::ID ID, DenseMap< Value *, Value * > &Cache, CallInst *CI)
Definition BPFCheckAndAdjustIR.cpp:491
static Instruction * aspaceMemCpy(Intrinsic::ID ID, DenseMap< Value *, Value * > &Cache, CallInst *CI)
Definition BPFCheckAndAdjustIR.cpp:518
static Instruction * aspaceMemMove(DenseMap< Value *, Value * > &Cache, CallInst *CI)
Definition BPFCheckAndAdjustIR.cpp:543
static bool sinkMinMaxInBB(BasicBlock &BB, const std::function< bool(Instruction *)> &Filter)
Definition BPFCheckAndAdjustIR.cpp:186
static Value * wrapPtrIfASNotZero(DenseMap< Value *, Value * > &Cache, CallInst *CI, Value *P)
Definition BPFCheckAndAdjustIR.cpp:482
static void aspaceWrapOperand(DenseMap< Value *, Value * > &Cache, Instruction *I, unsigned OpNum)
Definition BPFCheckAndAdjustIR.cpp:461
static void unrollGEPStore(CallInst *Call)
Definition BPFCheckAndAdjustIR.cpp:377
static Value * aspaceWrapValue(DenseMap< Value *, Value * > &Cache, Function *F, Value *ToWrap)
Definition BPFCheckAndAdjustIR.cpp:429
static void unrollGEPLoad(CallInst *Call)
Definition BPFCheckAndAdjustIR.cpp:369
static bool removeGEPBuiltinsInFunc(Function &F)
Definition BPFCheckAndAdjustIR.cpp:384
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
static std::pair< GetElementPtrInst *, StoreInst * > reconstructStore(CallInst *Call)
static std::pair< GetElementPtrInst *, LoadInst * > reconstructLoad(CallInst *Call)
LLVM Basic Block Representation.
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Predicate getPredicate() const
Return the predicate for this instruction.
This instruction compares its operands according to the predicate given to the constructor.
static bool isGE(Predicate P)
Return true if the predicate is SGE or UGE.
static bool isLT(Predicate P)
Return true if the predicate is SLT or ULT.
static bool isGT(Predicate P)
Return true if the predicate is SGT or UGT.
bool isRelational() const
Return true if the predicate is relational (not EQ or NE).
static bool isLE(Predicate P)
Return true if the predicate is SLE or ULE.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
This class represents a sign extension of integer types.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
This class represents zero extension of integer types.
self_iterator getIterator()
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
ModulePass * createBPFCheckAndAdjustIR()
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
SExtInst * SExt
Definition BPFCheckAndAdjustIR.cpp:179
CallInst * MinMax
Definition BPFCheckAndAdjustIR.cpp:177
ICmpInst::Predicate Predicate
Definition BPFCheckAndAdjustIR.cpp:176
MinMaxSinkInfo(ICmpInst *ICmp, Value *Other, ICmpInst::Predicate Predicate)
Definition BPFCheckAndAdjustIR.cpp:181
Value * Other
Definition BPFCheckAndAdjustIR.cpp:175
ZExtInst * ZExt
Definition BPFCheckAndAdjustIR.cpp:178
ICmpInst * ICmp
Definition BPFCheckAndAdjustIR.cpp:174
This struct is a compact representation of a valid (non-zero power of two) alignment.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.