LLVM 23.0.0git
BPFCheckAndAdjustIR.cpp
Go to the documentation of this file.
1//===------------ BPFCheckAndAdjustIR.cpp - Check and Adjust IR -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Check IR and adjust IR for verifier friendly codes.
10// The following are done for IR checking:
11// - no relocation globals in PHI node.
12// The following are done for IR adjustment:
13// - remove __builtin_bpf_passthrough builtins. Target independent IR
14// optimizations are done and those builtins can be removed.
15// - remove llvm.bpf.getelementptr.and.load builtins.
16// - remove llvm.bpf.getelementptr.and.store builtins.
17// - for loads and stores with base addresses from non-zero address space
18// cast base address to zero address space (support for BPF address spaces).
19//
20//===----------------------------------------------------------------------===//
21
22#include "BPF.h"
23#include "BPFCORE.h"
25#include "llvm/IR/Analysis.h"
27#include "llvm/IR/IRBuilder.h"
28#include "llvm/IR/Instruction.h"
31#include "llvm/IR/IntrinsicsBPF.h"
32#include "llvm/IR/Module.h"
33#include "llvm/IR/PassManager.h"
34#include "llvm/IR/Type.h"
35#include "llvm/IR/Value.h"
36#include "llvm/Pass.h"
38
39#define DEBUG_TYPE "bpf-check-and-opt-ir"
40
41using namespace llvm;
42
43namespace {
44
45class BPFCheckAndAdjustIRLegacy final : public ModulePass {
46 bool runOnModule(Module &F) override;
47
48public:
49 static char ID;
50 BPFCheckAndAdjustIRLegacy() : ModulePass(ID) {}
51 void getAnalysisUsage(AnalysisUsage &AU) const override;
52};
53} // End anonymous namespace
54
55char BPFCheckAndAdjustIRLegacy::ID = 0;
56INITIALIZE_PASS(BPFCheckAndAdjustIRLegacy, DEBUG_TYPE,
57 "BPF Check And Adjust IR", false, false)
58
60 return new BPFCheckAndAdjustIRLegacy();
61}
62
63static void checkIR(Module &M) {
64 // Ensure relocation global won't appear in PHI node
65 // This may happen if the compiler generated the following code:
66 // B1:
67 // g1 = @llvm.skb_buff:0:1...
68 // ...
69 // goto B_COMMON
70 // B2:
71 // g2 = @llvm.skb_buff:0:2...
72 // ...
73 // goto B_COMMON
74 // B_COMMON:
75 // g = PHI(g1, g2)
76 // x = load g
77 // ...
78 // If anything likes the above "g = PHI(g1, g2)", issue a fatal error.
79 for (Function &F : M)
80 for (auto &BB : F)
81 for (auto &I : BB) {
83 if (!PN || PN->use_empty())
84 continue;
85 for (int i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
87 if (!GV)
88 continue;
89 if (GV->hasAttribute(BPFCoreSharedInfo::AmaAttr) ||
90 GV->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))
91 report_fatal_error("relocation global in PHI node");
92 }
93 }
94}
95
97 // Remove __builtin_bpf_passthrough()'s which are used to prevent
98 // certain IR optimizations. Now major IR optimizations are done,
99 // remove them.
100 bool Changed = false;
101 CallInst *ToBeDeleted = nullptr;
102 for (Function &F : M)
103 for (auto &BB : F)
104 for (auto &I : BB) {
105 if (ToBeDeleted) {
106 ToBeDeleted->eraseFromParent();
107 ToBeDeleted = nullptr;
108 }
109
110 auto *Call = dyn_cast<CallInst>(&I);
111 if (!Call)
112 continue;
113 auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
114 if (!GV)
115 continue;
116 if (!GV->getName().starts_with("llvm.bpf.passthrough"))
117 continue;
118 Changed = true;
119 Value *Arg = Call->getArgOperand(1);
120 Call->replaceAllUsesWith(Arg);
121 ToBeDeleted = Call;
122 }
123 return Changed;
124}
125
127 // Remove __builtin_bpf_compare()'s which are used to prevent
128 // certain IR optimizations. Now major IR optimizations are done,
129 // remove them.
130 bool Changed = false;
131 CallInst *ToBeDeleted = nullptr;
132 for (Function &F : M)
133 for (auto &BB : F)
134 for (auto &I : BB) {
135 if (ToBeDeleted) {
136 ToBeDeleted->eraseFromParent();
137 ToBeDeleted = nullptr;
138 }
139
140 auto *Call = dyn_cast<CallInst>(&I);
141 if (!Call)
142 continue;
143 auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
144 if (!GV)
145 continue;
146 if (!GV->getName().starts_with("llvm.bpf.compare"))
147 continue;
148
149 Changed = true;
150 Value *Arg0 = Call->getArgOperand(0);
151 Value *Arg1 = Call->getArgOperand(1);
152 Value *Arg2 = Call->getArgOperand(2);
153
154 auto OpVal = cast<ConstantInt>(Arg0)->getValue().getZExtValue();
156
157 auto *ICmp = new ICmpInst(Opcode, Arg1, Arg2);
158 ICmp->insertBefore(Call->getIterator());
159
160 Call->replaceAllUsesWith(ICmp);
161 ToBeDeleted = Call;
162 }
163 return Changed;
164}
165
178
180 const std::function<bool(Instruction *)> &Filter) {
181 // Check if V is:
182 // (fn %a %b) or (ext (fn %a %b))
183 // Where:
184 // ext := sext | zext
185 // fn := smin | umin | smax | umax
186 auto IsMinMaxCall = [=](Value *V, MinMaxSinkInfo &Info) {
187 if (auto *ZExt = dyn_cast<ZExtInst>(V)) {
188 V = ZExt->getOperand(0);
189 Info.ZExt = ZExt;
190 } else if (auto *SExt = dyn_cast<SExtInst>(V)) {
191 V = SExt->getOperand(0);
192 Info.SExt = SExt;
193 }
194
195 auto *Call = dyn_cast<CallInst>(V);
196 if (!Call)
197 return false;
198
199 auto *Called = dyn_cast<Function>(Call->getCalledOperand());
200 if (!Called)
201 return false;
202
203 switch (Called->getIntrinsicID()) {
204 case Intrinsic::smin:
205 case Intrinsic::umin:
206 case Intrinsic::smax:
207 case Intrinsic::umax:
208 break;
209 default:
210 return false;
211 }
212
213 if (!Filter(Call))
214 return false;
215
216 Info.MinMax = Call;
217
218 return true;
219 };
220
221 auto ZeroOrSignExtend = [](IRBuilder<> &Builder, Value *V,
222 MinMaxSinkInfo &Info) {
223 if (Info.SExt) {
224 if (Info.SExt->getType() == V->getType())
225 return V;
226 return Builder.CreateSExt(V, Info.SExt->getType());
227 }
228 if (Info.ZExt) {
229 if (Info.ZExt->getType() == V->getType())
230 return V;
231 return Builder.CreateZExt(V, Info.ZExt->getType());
232 }
233 return V;
234 };
235
236 bool Changed = false;
238
239 // Check BB for instructions like:
240 // insn := (icmp %a (fn ...)) | (icmp (fn ...) %a)
241 //
242 // Where:
243 // fn := min | max | (sext (min ...)) | (sext (max ...))
244 //
245 // Put such instructions to SinkList.
246 for (Instruction &I : BB) {
247 ICmpInst *ICmp = dyn_cast<ICmpInst>(&I);
248 if (!ICmp)
249 continue;
250 if (!ICmp->isRelational())
251 continue;
252 MinMaxSinkInfo First(ICmp, ICmp->getOperand(1),
254 MinMaxSinkInfo Second(ICmp, ICmp->getOperand(0), ICmp->getPredicate());
255 bool FirstMinMax = IsMinMaxCall(ICmp->getOperand(0), First);
256 bool SecondMinMax = IsMinMaxCall(ICmp->getOperand(1), Second);
257 if (!(FirstMinMax ^ SecondMinMax))
258 continue;
259 SinkList.push_back(FirstMinMax ? First : Second);
260 }
261
262 // Iterate SinkList and replace each (icmp ...) with corresponding
263 // `x < a && x < b` or similar expression.
264 for (auto &Info : SinkList) {
265 ICmpInst *ICmp = Info.ICmp;
266 CallInst *MinMax = Info.MinMax;
267 Intrinsic::ID IID = MinMax->getCalledFunction()->getIntrinsicID();
268 ICmpInst::Predicate P = Info.Predicate;
269 if (ICmpInst::isSigned(P) && IID != Intrinsic::smin &&
270 IID != Intrinsic::smax)
271 continue;
272
273 IRBuilder<> Builder(ICmp);
274 Value *X = Info.Other;
275 Value *A = ZeroOrSignExtend(Builder, MinMax->getArgOperand(0), Info);
276 Value *B = ZeroOrSignExtend(Builder, MinMax->getArgOperand(1), Info);
277 bool IsMin = IID == Intrinsic::smin || IID == Intrinsic::umin;
278 bool IsMax = IID == Intrinsic::smax || IID == Intrinsic::umax;
279 bool IsLess = ICmpInst::isLE(P) || ICmpInst::isLT(P);
280 bool IsGreater = ICmpInst::isGE(P) || ICmpInst::isGT(P);
281 assert(IsMin ^ IsMax);
282 assert(IsLess ^ IsGreater);
283
284 Value *Replacement;
285 Value *LHS = Builder.CreateICmp(P, X, A);
286 Value *RHS = Builder.CreateICmp(P, X, B);
287 if ((IsLess && IsMin) || (IsGreater && IsMax))
288 // x < min(a, b) -> x < a && x < b
289 // x > max(a, b) -> x > a && x > b
290 Replacement = Builder.CreateLogicalAnd(LHS, RHS);
291 else
292 // x > min(a, b) -> x > a || x > b
293 // x < max(a, b) -> x < a || x < b
294 Replacement = Builder.CreateLogicalOr(LHS, RHS);
295
296 ICmp->replaceAllUsesWith(Replacement);
297
298 Instruction *ToRemove[] = {ICmp, Info.ZExt, Info.SExt, MinMax};
299 for (Instruction *I : ToRemove)
300 if (I && I->use_empty())
301 I->eraseFromParent();
302
303 Changed = true;
304 }
305
306 return Changed;
307}
308
309// Do the following transformation:
310//
311// x < min(a, b) -> x < a && x < b
312// x > min(a, b) -> x > a || x > b
313// x < max(a, b) -> x < a || x < b
314// x > max(a, b) -> x > a && x > b
315//
316// Such patterns are introduced by LICM.cpp:hoistMinMax()
317// transformation and might lead to BPF verification failures for
318// older kernels.
319//
320// To minimize "collateral" changes only do it for icmp + min/max
321// calls when icmp is inside a loop and min/max is outside of that
322// loop.
323//
324// Verification failure happens when:
325// - RHS operand of some `icmp LHS, RHS` is replaced by some RHS1;
326// - verifier can recognize RHS as a constant scalar in some context;
327// - verifier can't recognize RHS1 as a constant scalar in the same
328// context;
329//
330// The "constant scalar" is not a compile time constant, but a register
331// that holds a scalar value known to verifier at some point in time
332// during abstract interpretation.
333//
334// See also:
335// https://lore.kernel.org/bpf/20230406164505.1046801-1-yhs@fb.com/
336static bool sinkMinMax(Module &M,
337 function_ref<LoopInfo &(Function &)> GetLoopInfo) {
338 bool Changed = false;
339
340 for (Function &F : M) {
341 if (F.isDeclaration())
342 continue;
343
344 LoopInfo &LI = GetLoopInfo(F);
345 for (Loop *L : LI)
346 for (BasicBlock *BB : L->blocks()) {
347 // Filter out instructions coming from the same loop
348 Loop *BBLoop = LI.getLoopFor(BB);
349 auto OtherLoopFilter = [&](Instruction *I) {
350 return LI.getLoopFor(I->getParent()) != BBLoop;
351 };
352 Changed |= sinkMinMaxInBB(*BB, OtherLoopFilter);
353 }
354 }
355
356 return Changed;
357}
358
359void BPFCheckAndAdjustIRLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
360 AU.addRequired<LoopInfoWrapperPass>();
361}
362
365 GEP->insertBefore(Call->getIterator());
366 Load->insertBefore(Call->getIterator());
367 Call->replaceAllUsesWith(Load);
368 Call->eraseFromParent();
369}
370
373 GEP->insertBefore(Call->getIterator());
374 Store->insertBefore(Call->getIterator());
375 Call->eraseFromParent();
376}
377
380 SmallVector<CallInst *> GEPStores;
381 for (auto &BB : F)
382 for (auto &Insn : BB)
383 if (auto *Call = dyn_cast<CallInst>(&Insn))
384 if (auto *Called = Call->getCalledFunction())
385 switch (Called->getIntrinsicID()) {
386 case Intrinsic::bpf_getelementptr_and_load:
387 GEPLoads.push_back(Call);
388 break;
389 case Intrinsic::bpf_getelementptr_and_store:
390 GEPStores.push_back(Call);
391 break;
392 }
393
394 if (GEPLoads.empty() && GEPStores.empty())
395 return false;
396
397 for_each(GEPLoads, unrollGEPLoad);
398 for_each(GEPStores, unrollGEPStore);
399
400 return true;
401}
402
403// Rewrites the following builtins:
404// - llvm.bpf.getelementptr.and.load
405// - llvm.bpf.getelementptr.and.store
406// As (load (getelementptr ...)) or (store (getelementptr ...)).
407static bool removeGEPBuiltins(Module &M) {
408 bool Changed = false;
409 for (auto &F : M)
411 return Changed;
412}
413
414// Wrap ToWrap with cast to address space zero:
415// - if ToWrap is a getelementptr,
416// wrap it's base pointer instead and return a copy;
417// - if ToWrap is Instruction, insert address space cast
418// immediately after ToWrap;
419// - if ToWrap is not an Instruction (function parameter
420// or a global value), insert address space cast at the
421// beginning of the Function F;
422// - use Cache to avoid inserting too many casts;
424 Value *ToWrap) {
425 auto It = Cache.find(ToWrap);
426 if (It != Cache.end())
427 return It->getSecond();
428
429 if (auto *GEP = dyn_cast<GetElementPtrInst>(ToWrap)) {
430 Value *Ptr = GEP->getPointerOperand();
431 Value *WrappedPtr = aspaceWrapValue(Cache, F, Ptr);
432 auto *GEPTy = cast<PointerType>(GEP->getType());
433 auto *NewGEP = GEP->clone();
434 NewGEP->insertAfter(GEP->getIterator());
435 NewGEP->mutateType(PointerType::getUnqual(GEPTy->getContext()));
436 NewGEP->setOperand(GEP->getPointerOperandIndex(), WrappedPtr);
437 NewGEP->setName(GEP->getName());
438 Cache[ToWrap] = NewGEP;
439 return NewGEP;
440 }
441
442 IRBuilder IB(F->getContext());
443 if (Instruction *InsnPtr = dyn_cast<Instruction>(ToWrap))
444 IB.SetInsertPoint(*InsnPtr->getInsertionPointAfterDef());
445 else
446 IB.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt());
447 auto *ASZeroPtrTy = IB.getPtrTy(0);
448 auto *ACast = IB.CreateAddrSpaceCast(ToWrap, ASZeroPtrTy, ToWrap->getName());
449 Cache[ToWrap] = ACast;
450 return ACast;
451}
452
453// Wrap a pointer operand OpNum of instruction I
454// with cast to address space zero
456 unsigned OpNum) {
457 Value *OldOp = I->getOperand(OpNum);
458 if (OldOp->getType()->getPointerAddressSpace() == 0)
459 return;
460
461 Value *NewOp = aspaceWrapValue(Cache, I->getFunction(), OldOp);
462 I->setOperand(OpNum, NewOp);
463 // Check if there are any remaining users of old GEP,
464 // delete those w/o users
465 for (;;) {
466 auto *OldGEP = dyn_cast<GetElementPtrInst>(OldOp);
467 if (!OldGEP)
468 break;
469 if (!OldGEP->use_empty())
470 break;
471 OldOp = OldGEP->getPointerOperand();
472 OldGEP->eraseFromParent();
473 }
474}
475
477 CallInst *CI, Value *P) {
478 if (auto *PTy = dyn_cast<PointerType>(P->getType())) {
479 if (PTy->getAddressSpace() == 0)
480 return P;
481 }
482 return aspaceWrapValue(Cache, CI->getFunction(), P);
483}
484
487 CallInst *CI) {
488 auto *MI = cast<MemIntrinsic>(CI);
489 IRBuilder<> B(CI);
490
491 Value *OldDst = CI->getArgOperand(0);
492 Value *NewDst = wrapPtrIfASNotZero(Cache, CI, OldDst);
493 if (OldDst == NewDst)
494 return nullptr;
495
496 // memset(new_dst, val, len, align, isvolatile, md)
497 Value *Val = CI->getArgOperand(1);
498 Value *Len = CI->getArgOperand(2);
499
500 auto *MS = cast<MemSetInst>(CI);
501 MaybeAlign Align = MS->getDestAlign();
502 bool IsVolatile = MS->isVolatile();
503
504 if (ID == Intrinsic::memset)
505 return B.CreateMemSet(NewDst, Val, Len, Align, IsVolatile,
506 MI->getAAMetadata());
507 else
508 return B.CreateMemSetInline(NewDst, Align, Val, Len, IsVolatile,
509 MI->getAAMetadata());
510}
511
514 CallInst *CI) {
515 auto *MI = cast<MemIntrinsic>(CI);
516 IRBuilder<> B(CI);
517
518 Value *OldDst = CI->getArgOperand(0);
519 Value *OldSrc = CI->getArgOperand(1);
520 Value *NewDst = wrapPtrIfASNotZero(Cache, CI, OldDst);
521 Value *NewSrc = wrapPtrIfASNotZero(Cache, CI, OldSrc);
522 if (OldDst == NewDst && OldSrc == NewSrc)
523 return nullptr;
524
525 // memcpy(new_dst, dst_align, new_src, src_align, len, isvolatile, md)
526 Value *Len = CI->getArgOperand(2);
527
528 auto *MT = cast<MemTransferInst>(CI);
529 MaybeAlign DstAlign = MT->getDestAlign();
530 MaybeAlign SrcAlign = MT->getSourceAlign();
531 bool IsVolatile = MT->isVolatile();
532
533 return B.CreateMemTransferInst(ID, NewDst, DstAlign, NewSrc, SrcAlign, Len,
534 IsVolatile, MI->getAAMetadata());
535}
536
538 CallInst *CI) {
539 auto *MI = cast<MemIntrinsic>(CI);
540 IRBuilder<> B(CI);
541
542 Value *OldDst = CI->getArgOperand(0);
543 Value *OldSrc = CI->getArgOperand(1);
544 Value *NewDst = wrapPtrIfASNotZero(Cache, CI, OldDst);
545 Value *NewSrc = wrapPtrIfASNotZero(Cache, CI, OldSrc);
546 if (OldDst == NewDst && OldSrc == NewSrc)
547 return nullptr;
548
549 // memmove(new_dst, dst_align, new_src, src_align, len, isvolatile, md)
550 Value *Len = CI->getArgOperand(2);
551
552 auto *MT = cast<MemTransferInst>(CI);
553 MaybeAlign DstAlign = MT->getDestAlign();
554 MaybeAlign SrcAlign = MT->getSourceAlign();
555 bool IsVolatile = MT->isVolatile();
556
557 return B.CreateMemMove(NewDst, DstAlign, NewSrc, SrcAlign, Len, IsVolatile,
558 MI->getAAMetadata());
559}
560
561// Support for BPF address spaces:
562// - for each function in the module M, update pointer operand of
563// each memory access instruction (load/store/cmpxchg/atomicrmw)
564// or intrinsic call insns (memset/memcpy/memmove)
565// by casting it from non-zero address space to zero address space, e.g:
566//
567// (load (ptr addrspace (N) %p) ...)
568// -> (load (addrspacecast ptr addrspace (N) %p to ptr))
569//
570// - assign section with name .addr_space.N for globals defined in
571// non-zero address space N
572static bool insertASpaceCasts(Module &M) {
573 bool Changed = false;
574 for (Function &F : M) {
576 for (BasicBlock &BB : F) {
578 unsigned PtrOpNum;
579
580 if (auto *LD = dyn_cast<LoadInst>(&I)) {
581 PtrOpNum = LD->getPointerOperandIndex();
582 aspaceWrapOperand(CastsCache, &I, PtrOpNum);
583 continue;
584 }
585 if (auto *ST = dyn_cast<StoreInst>(&I)) {
586 PtrOpNum = ST->getPointerOperandIndex();
587 aspaceWrapOperand(CastsCache, &I, PtrOpNum);
588 continue;
589 }
590 if (auto *CmpXchg = dyn_cast<AtomicCmpXchgInst>(&I)) {
591 PtrOpNum = CmpXchg->getPointerOperandIndex();
592 aspaceWrapOperand(CastsCache, &I, PtrOpNum);
593 continue;
594 }
595 if (auto *RMW = dyn_cast<AtomicRMWInst>(&I)) {
596 PtrOpNum = RMW->getPointerOperandIndex();
597 aspaceWrapOperand(CastsCache, &I, PtrOpNum);
598 continue;
599 }
600
601 auto *CI = dyn_cast<CallInst>(&I);
602 if (!CI)
603 continue;
604
605 Function *Callee = CI->getCalledFunction();
606 if (!Callee || !Callee->isIntrinsic())
607 continue;
608
609 // Check memset/memcpy/memmove
610 Intrinsic::ID ID = Callee->getIntrinsicID();
611 bool IsSet = ID == Intrinsic::memset || ID == Intrinsic::memset_inline;
612 bool IsCpy = ID == Intrinsic::memcpy || ID == Intrinsic::memcpy_inline;
613 bool IsMove = ID == Intrinsic::memmove;
614 if (!IsSet && !IsCpy && !IsMove)
615 continue;
616
617 Instruction *New;
618 if (IsSet)
619 New = aspaceMemSet(ID, CastsCache, CI);
620 else if (IsCpy)
621 New = aspaceMemCpy(ID, CastsCache, CI);
622 else
623 New = aspaceMemMove(CastsCache, CI);
624
625 if (!New)
626 continue;
627
628 I.replaceAllUsesWith(New);
629 New->takeName(&I);
630 I.eraseFromParent();
631 }
632 }
633 Changed |= !CastsCache.empty();
634 }
635 // Merge all globals within same address space into single
636 // .addr_space.<addr space no> section
637 for (GlobalVariable &G : M.globals()) {
638 if (G.getAddressSpace() == 0 || G.hasSection())
639 continue;
640 SmallString<16> SecName;
641 raw_svector_ostream OS(SecName);
642 OS << ".addr_space." << G.getAddressSpace();
643 G.setSection(SecName);
644 // Prevent having separate section for constants
645 G.setConstant(false);
646 }
647 return Changed;
648}
649
650static bool adjustIR(Module &M,
651 function_ref<LoopInfo &(Function &)> GetLoopInfo) {
654 Changed = sinkMinMax(M, GetLoopInfo) || Changed;
657 return Changed;
658}
659
660bool BPFCheckAndAdjustIRLegacy::runOnModule(Module &M) {
661 checkIR(M);
662 return adjustIR(M, [&](Function &F) -> LoopInfo & {
663 return getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
664 });
665}
666
669 checkIR(M);
670 bool Changed = adjustIR(M, [&](Function &F) -> LoopInfo & {
671 return MAM.getResult<FunctionAnalysisManagerModuleProxy>(M)
672 .getManager()
673 .getResult<LoopAnalysis>(F);
674 });
677}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
static Instruction * aspaceMemSet(Intrinsic::ID ID, DenseMap< Value *, Value * > &Cache, CallInst *CI)
static Instruction * aspaceMemCpy(Intrinsic::ID ID, DenseMap< Value *, Value * > &Cache, CallInst *CI)
static bool insertASpaceCasts(Module &M)
static bool adjustIR(Module &M, function_ref< LoopInfo &(Function &)> GetLoopInfo)
static Instruction * aspaceMemMove(DenseMap< Value *, Value * > &Cache, CallInst *CI)
static bool sinkMinMax(Module &M, function_ref< LoopInfo &(Function &)> GetLoopInfo)
static void checkIR(Module &M)
static bool sinkMinMaxInBB(BasicBlock &BB, const std::function< bool(Instruction *)> &Filter)
static bool removePassThroughBuiltin(Module &M)
static Value * wrapPtrIfASNotZero(DenseMap< Value *, Value * > &Cache, CallInst *CI, Value *P)
static void aspaceWrapOperand(DenseMap< Value *, Value * > &Cache, Instruction *I, unsigned OpNum)
static void unrollGEPStore(CallInst *Call)
static Value * aspaceWrapValue(DenseMap< Value *, Value * > &Cache, Function *F, Value *ToWrap)
static bool removeGEPBuiltins(Module &M)
static void unrollGEPLoad(CallInst *Call)
static bool removeGEPBuiltinsInFunc(Function &F)
static bool removeCompareBuiltin(Module &M)
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define DEBUG_TYPE
Hexagon Common GEP
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
Machine Check Debug Module
#define P(N)
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
Value * RHS
Value * LHS
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
Definition BPFCORE.h:63
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
Definition BPFCORE.h:61
static std::pair< GetElementPtrInst *, StoreInst * > reconstructStore(CallInst *Call)
static std::pair< GetElementPtrInst *, LoadInst * > reconstructLoad(CallInst *Call)
LLVM Basic Block Representation.
Definition BasicBlock.h:62
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
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.
Definition InstrTypes.h:740
bool isSigned() const
Definition InstrTypes.h:993
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
Definition InstrTypes.h:890
Predicate getPredicate() const
Return the predicate for this instruction.
Definition InstrTypes.h:828
bool empty() const
Definition DenseMap.h:171
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...
Definition IRBuilder.h:2893
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.
Analysis pass that exposes the LoopInfo for a function.
Definition LoopInfo.h:587
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
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...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
This class represents a sign extension of integer types.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
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
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
bool use_empty() const
Definition Value.h:346
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
This class represents zero extension of integer types.
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to an SmallVector or SmallString.
CallInst * Call
Changed
Pass manager infrastructure for declaring and invalidating analyses.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1732
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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...
Definition STLExtras.h:633
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
ModulePass * createBPFCheckAndAdjustIRLegacyPass()
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
ICmpInst::Predicate Predicate
MinMaxSinkInfo(ICmpInst *ICmp, Value *Other, ICmpInst::Predicate Predicate)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106