LLVM 24.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"
24#include "llvm/ADT/MapVector.h"
26#include "llvm/IR/Analysis.h"
28#include "llvm/IR/IRBuilder.h"
29#include "llvm/IR/Instruction.h"
32#include "llvm/IR/IntrinsicsBPF.h"
33#include "llvm/IR/Module.h"
34#include "llvm/IR/PassManager.h"
36#include "llvm/IR/Type.h"
37#include "llvm/IR/Value.h"
38#include "llvm/Pass.h"
40
41#define DEBUG_TYPE "bpf-check-and-opt-ir"
42
43using namespace llvm;
44
45namespace {
46
47class BPFCheckAndAdjustIRLegacy final : public ModulePass {
48 bool runOnModule(Module &F) override;
49
50public:
51 static char ID;
52 BPFCheckAndAdjustIRLegacy() : ModulePass(ID) {}
53 void getAnalysisUsage(AnalysisUsage &AU) const override;
54};
55} // End anonymous namespace
56
57char BPFCheckAndAdjustIRLegacy::ID = 0;
58INITIALIZE_PASS(BPFCheckAndAdjustIRLegacy, DEBUG_TYPE,
59 "BPF Check And Adjust IR", false, false)
60
62 return new BPFCheckAndAdjustIRLegacy();
63}
64
65static void checkIR(Module &M) {
66 // Ensure relocation global won't appear in PHI node
67 // This may happen if the compiler generated the following code:
68 // B1:
69 // g1 = @llvm.skb_buff:0:1...
70 // ...
71 // goto B_COMMON
72 // B2:
73 // g2 = @llvm.skb_buff:0:2...
74 // ...
75 // goto B_COMMON
76 // B_COMMON:
77 // g = PHI(g1, g2)
78 // x = load g
79 // ...
80 // If anything likes the above "g = PHI(g1, g2)", issue a fatal error.
81 for (Function &F : M)
82 for (auto &BB : F)
83 for (auto &I : BB) {
85 if (!PN || PN->use_empty())
86 continue;
87 for (int i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
89 if (!GV)
90 continue;
91 if (GV->hasAttribute(BPFCoreSharedInfo::AmaAttr) ||
92 GV->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))
93 report_fatal_error("relocation global in PHI node");
94 }
95 }
96}
97
99 // Remove __builtin_bpf_passthrough()'s which are used to prevent
100 // certain IR optimizations. Now major IR optimizations are done,
101 // remove them.
102 bool Changed = false;
103 CallInst *ToBeDeleted = nullptr;
104 for (Function &F : M)
105 for (auto &BB : F)
106 for (auto &I : BB) {
107 if (ToBeDeleted) {
108 ToBeDeleted->eraseFromParent();
109 ToBeDeleted = nullptr;
110 }
111
112 auto *Call = dyn_cast<CallInst>(&I);
113 if (!Call)
114 continue;
115 auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
116 if (!GV)
117 continue;
118 if (!GV->getName().starts_with("llvm.bpf.passthrough"))
119 continue;
120 Changed = true;
121 Value *Arg = Call->getArgOperand(1);
122 Call->replaceAllUsesWith(Arg);
123 ToBeDeleted = Call;
124 }
125 return Changed;
126}
127
129 // Remove __builtin_bpf_compare()'s which are used to prevent
130 // certain IR optimizations. Now major IR optimizations are done,
131 // remove them.
132 bool Changed = false;
133 CallInst *ToBeDeleted = nullptr;
134 for (Function &F : M)
135 for (auto &BB : F)
136 for (auto &I : BB) {
137 if (ToBeDeleted) {
138 ToBeDeleted->eraseFromParent();
139 ToBeDeleted = nullptr;
140 }
141
142 auto *Call = dyn_cast<CallInst>(&I);
143 if (!Call)
144 continue;
145 auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
146 if (!GV)
147 continue;
148 if (!GV->getName().starts_with("llvm.bpf.compare"))
149 continue;
150
151 Changed = true;
152 Value *Arg0 = Call->getArgOperand(0);
153 Value *Arg1 = Call->getArgOperand(1);
154 Value *Arg2 = Call->getArgOperand(2);
155
156 auto OpVal = cast<ConstantInt>(Arg0)->getValue().getZExtValue();
158
159 auto *ICmp = new ICmpInst(Opcode, Arg1, Arg2);
160 ICmp->insertBefore(Call->getIterator());
161
162 Call->replaceAllUsesWith(ICmp);
163 ToBeDeleted = Call;
164 }
165 return Changed;
166}
167
180
182 const std::function<bool(Instruction *)> &Filter) {
183 // Check if V is:
184 // (fn %a %b) or (ext (fn %a %b))
185 // Where:
186 // ext := sext | zext
187 // fn := smin | umin | smax | umax
188 auto IsMinMaxCall = [=](Value *V, MinMaxSinkInfo &Info) {
189 if (auto *ZExt = dyn_cast<ZExtInst>(V)) {
190 V = ZExt->getOperand(0);
191 Info.ZExt = ZExt;
192 } else if (auto *SExt = dyn_cast<SExtInst>(V)) {
193 V = SExt->getOperand(0);
194 Info.SExt = SExt;
195 }
196
197 auto *Call = dyn_cast<CallInst>(V);
198 if (!Call)
199 return false;
200
201 auto *Called = dyn_cast<Function>(Call->getCalledOperand());
202 if (!Called)
203 return false;
204
205 switch (Called->getIntrinsicID()) {
206 case Intrinsic::smin:
207 case Intrinsic::umin:
208 case Intrinsic::smax:
209 case Intrinsic::umax:
210 break;
211 default:
212 return false;
213 }
214
215 if (!Filter(Call))
216 return false;
217
218 Info.MinMax = Call;
219
220 return true;
221 };
222
223 auto ZeroOrSignExtend = [](IRBuilder<> &Builder, Value *V,
224 MinMaxSinkInfo &Info) {
225 if (Info.SExt) {
226 if (Info.SExt->getType() == V->getType())
227 return V;
228 return Builder.CreateSExt(V, Info.SExt->getType());
229 }
230 if (Info.ZExt) {
231 if (Info.ZExt->getType() == V->getType())
232 return V;
233 return Builder.CreateZExt(V, Info.ZExt->getType());
234 }
235 return V;
236 };
237
238 bool Changed = false;
240
241 // Check BB for instructions like:
242 // insn := (icmp %a (fn ...)) | (icmp (fn ...) %a)
243 //
244 // Where:
245 // fn := min | max | (sext (min ...)) | (sext (max ...))
246 //
247 // Put such instructions to SinkList.
248 for (Instruction &I : BB) {
249 ICmpInst *ICmp = dyn_cast<ICmpInst>(&I);
250 if (!ICmp)
251 continue;
252 if (!ICmp->isRelational())
253 continue;
254 MinMaxSinkInfo First(ICmp, ICmp->getOperand(1),
256 MinMaxSinkInfo Second(ICmp, ICmp->getOperand(0), ICmp->getPredicate());
257 bool FirstMinMax = IsMinMaxCall(ICmp->getOperand(0), First);
258 bool SecondMinMax = IsMinMaxCall(ICmp->getOperand(1), Second);
259 if (!(FirstMinMax ^ SecondMinMax))
260 continue;
261 SinkList.push_back(FirstMinMax ? First : Second);
262 }
263
264 // Iterate SinkList and replace each (icmp ...) with corresponding
265 // `x < a && x < b` or similar expression.
266 for (auto &Info : SinkList) {
267 ICmpInst *ICmp = Info.ICmp;
268 CallInst *MinMax = Info.MinMax;
269 Intrinsic::ID IID = MinMax->getCalledFunction()->getIntrinsicID();
270 ICmpInst::Predicate P = Info.Predicate;
271 if (ICmpInst::isSigned(P) && IID != Intrinsic::smin &&
272 IID != Intrinsic::smax)
273 continue;
274
275 IRBuilder<> Builder(ICmp);
276 Value *X = Info.Other;
277 Value *A = ZeroOrSignExtend(Builder, MinMax->getArgOperand(0), Info);
278 Value *B = ZeroOrSignExtend(Builder, MinMax->getArgOperand(1), Info);
279 bool IsMin = IID == Intrinsic::smin || IID == Intrinsic::umin;
280 bool IsMax = IID == Intrinsic::smax || IID == Intrinsic::umax;
281 bool IsLess = ICmpInst::isLE(P) || ICmpInst::isLT(P);
282 bool IsGreater = ICmpInst::isGE(P) || ICmpInst::isGT(P);
283 assert(IsMin ^ IsMax);
284 assert(IsLess ^ IsGreater);
285
286 Value *Replacement;
287 Value *LHS = Builder.CreateICmp(P, X, A);
288 Value *RHS = Builder.CreateICmp(P, X, B);
289 if ((IsLess && IsMin) || (IsGreater && IsMax))
290 // x < min(a, b) -> x < a && x < b
291 // x > max(a, b) -> x > a && x > b
292 Replacement = Builder.CreateLogicalAnd(LHS, RHS);
293 else
294 // x > min(a, b) -> x > a || x > b
295 // x < max(a, b) -> x < a || x < b
296 Replacement = Builder.CreateLogicalOr(LHS, RHS);
297
298 if (SelectInst *ReplacementInst = dyn_cast<SelectInst>(Replacement))
300
301 ICmp->replaceAllUsesWith(Replacement);
302
303 Instruction *ToRemove[] = {ICmp, Info.ZExt, Info.SExt, MinMax};
304 for (Instruction *I : ToRemove)
305 if (I && I->use_empty())
306 I->eraseFromParent();
307
308 Changed = true;
309 }
310
311 return Changed;
312}
313
314// Do the following transformation:
315//
316// x < min(a, b) -> x < a && x < b
317// x > min(a, b) -> x > a || x > b
318// x < max(a, b) -> x < a || x < b
319// x > max(a, b) -> x > a && x > b
320//
321// Such patterns are introduced by LICM.cpp:hoistMinMax()
322// transformation and might lead to BPF verification failures for
323// older kernels.
324//
325// To minimize "collateral" changes only do it for icmp + min/max
326// calls when icmp is inside a loop and min/max is outside of that
327// loop.
328//
329// Verification failure happens when:
330// - RHS operand of some `icmp LHS, RHS` is replaced by some RHS1;
331// - verifier can recognize RHS as a constant scalar in some context;
332// - verifier can't recognize RHS1 as a constant scalar in the same
333// context;
334//
335// The "constant scalar" is not a compile time constant, but a register
336// that holds a scalar value known to verifier at some point in time
337// during abstract interpretation.
338//
339// See also:
340// https://lore.kernel.org/bpf/20230406164505.1046801-1-yhs@fb.com/
341static bool sinkMinMax(Module &M,
342 function_ref<LoopInfo &(Function &)> GetLoopInfo) {
343 bool Changed = false;
344
345 for (Function &F : M) {
346 if (F.isDeclaration())
347 continue;
348
349 LoopInfo &LI = GetLoopInfo(F);
350 for (Loop *L : LI)
351 for (BasicBlock *BB : L->blocks()) {
352 // Filter out instructions coming from the same loop
353 Loop *BBLoop = LI.getLoopFor(BB);
354 auto OtherLoopFilter = [&](Instruction *I) {
355 return LI.getLoopFor(I->getParent()) != BBLoop;
356 };
357 Changed |= sinkMinMaxInBB(*BB, OtherLoopFilter);
358 }
359 }
360
361 return Changed;
362}
363
364void BPFCheckAndAdjustIRLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
365 AU.addRequired<LoopInfoWrapperPass>();
366}
367
370 GEP->insertBefore(Call->getIterator());
371 Load->insertBefore(Call->getIterator());
372 Call->replaceAllUsesWith(Load);
373 Call->eraseFromParent();
374}
375
378 GEP->insertBefore(Call->getIterator());
379 Store->insertBefore(Call->getIterator());
380 Call->eraseFromParent();
381}
382
385 SmallVector<CallInst *> GEPStores;
386 for (auto &BB : F)
387 for (auto &Insn : BB)
388 if (auto *Call = dyn_cast<CallInst>(&Insn))
389 if (auto *Called = Call->getCalledFunction())
390 switch (Called->getIntrinsicID()) {
391 case Intrinsic::bpf_getelementptr_and_load:
392 GEPLoads.push_back(Call);
393 break;
394 case Intrinsic::bpf_getelementptr_and_store:
395 GEPStores.push_back(Call);
396 break;
397 }
398
399 if (GEPLoads.empty() && GEPStores.empty())
400 return false;
401
402 for_each(GEPLoads, unrollGEPLoad);
403 for_each(GEPStores, unrollGEPStore);
404
405 return true;
406}
407
408// Rewrites the following builtins:
409// - llvm.bpf.getelementptr.and.load
410// - llvm.bpf.getelementptr.and.store
411// As (load (getelementptr ...)) or (store (getelementptr ...)).
412static bool removeGEPBuiltins(Module &M) {
413 bool Changed = false;
414 for (auto &F : M)
416 return Changed;
417}
418
419// Wrap ToWrap with cast to address space zero:
420// - if ToWrap is a getelementptr,
421// wrap it's base pointer instead and return a copy;
422// - if ToWrap is Instruction, insert address space cast
423// immediately after ToWrap;
424// - if ToWrap is not an Instruction (function parameter
425// or a global value), insert address space cast at the
426// beginning of the Function F;
427// - use Cache to avoid inserting too many casts;
429 Value *ToWrap) {
430 auto It = Cache.find(ToWrap);
431 if (It != Cache.end())
432 return It->getSecond();
433
434 if (auto *GEP = dyn_cast<GetElementPtrInst>(ToWrap)) {
435 Value *Ptr = GEP->getPointerOperand();
436 Value *WrappedPtr = aspaceWrapValue(Cache, F, Ptr);
437 auto *GEPTy = cast<PointerType>(GEP->getType());
438 auto *NewGEP = GEP->clone();
439 NewGEP->insertAfter(GEP->getIterator());
440 NewGEP->mutateType(PointerType::getUnqual(GEPTy->getContext()));
441 NewGEP->setOperand(GEP->getPointerOperandIndex(), WrappedPtr);
442 NewGEP->setName(GEP->getName());
443 Cache[ToWrap] = NewGEP;
444 return NewGEP;
445 }
446
447 IRBuilder IB(*F->getParent());
448 if (Instruction *InsnPtr = dyn_cast<Instruction>(ToWrap))
449 IB.SetInsertPoint(*InsnPtr->getInsertionPointAfterDef());
450 else
451 IB.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt());
452 auto *ASZeroPtrTy = IB.getPtrTy(0);
453 auto *ACast = IB.CreateAddrSpaceCast(ToWrap, ASZeroPtrTy, ToWrap->getName());
454 Cache[ToWrap] = ACast;
455 return ACast;
456}
457
458// Wrap a pointer operand OpNum of instruction I
459// with cast to address space zero
461 unsigned OpNum) {
462 Value *OldOp = I->getOperand(OpNum);
463 if (OldOp->getType()->getPointerAddressSpace() == 0)
464 return;
465
466 Value *NewOp = aspaceWrapValue(Cache, I->getFunction(), OldOp);
467 I->setOperand(OpNum, NewOp);
468 // Check if there are any remaining users of old GEP,
469 // delete those w/o users
470 for (;;) {
471 auto *OldGEP = dyn_cast<GetElementPtrInst>(OldOp);
472 if (!OldGEP)
473 break;
474 if (!OldGEP->use_empty())
475 break;
476 OldOp = OldGEP->getPointerOperand();
477 OldGEP->eraseFromParent();
478 }
479}
480
482 CallInst *CI, Value *P) {
483 if (auto *PTy = dyn_cast<PointerType>(P->getType())) {
484 if (PTy->getAddressSpace() == 0)
485 return P;
486 }
487 return aspaceWrapValue(Cache, CI->getFunction(), P);
488}
489
492 CallInst *CI) {
493 auto *MI = cast<MemIntrinsic>(CI);
494 IRBuilder<> B(CI);
495
496 Value *OldDst = CI->getArgOperand(0);
497 Value *NewDst = wrapPtrIfASNotZero(Cache, CI, OldDst);
498 if (OldDst == NewDst)
499 return nullptr;
500
501 // memset(new_dst, val, len, align, isvolatile, md)
502 Value *Val = CI->getArgOperand(1);
503 Value *Len = CI->getArgOperand(2);
504
505 auto *MS = cast<MemSetInst>(CI);
506 MaybeAlign Align = MS->getDestAlign();
507 bool IsVolatile = MS->isVolatile();
508
509 if (ID == Intrinsic::memset)
510 return B.CreateMemSet(NewDst, Val, Len, Align, IsVolatile,
511 MI->getAAMetadata());
512 else
513 return B.CreateMemSetInline(NewDst, Align, Val, Len, IsVolatile,
514 MI->getAAMetadata());
515}
516
519 CallInst *CI) {
520 auto *MI = cast<MemIntrinsic>(CI);
521 IRBuilder<> B(CI);
522
523 Value *OldDst = CI->getArgOperand(0);
524 Value *OldSrc = CI->getArgOperand(1);
525 Value *NewDst = wrapPtrIfASNotZero(Cache, CI, OldDst);
526 Value *NewSrc = wrapPtrIfASNotZero(Cache, CI, OldSrc);
527 if (OldDst == NewDst && OldSrc == NewSrc)
528 return nullptr;
529
530 // memcpy(new_dst, dst_align, new_src, src_align, len, isvolatile, md)
531 Value *Len = CI->getArgOperand(2);
532
533 auto *MT = cast<MemTransferInst>(CI);
534 MaybeAlign DstAlign = MT->getDestAlign();
535 MaybeAlign SrcAlign = MT->getSourceAlign();
536 bool IsVolatile = MT->isVolatile();
537
538 return B.CreateMemTransferInst(ID, NewDst, DstAlign, NewSrc, SrcAlign, Len,
539 IsVolatile, MI->getAAMetadata());
540}
541
543 CallInst *CI) {
544 auto *MI = cast<MemIntrinsic>(CI);
545 IRBuilder<> B(CI);
546
547 Value *OldDst = CI->getArgOperand(0);
548 Value *OldSrc = CI->getArgOperand(1);
549 Value *NewDst = wrapPtrIfASNotZero(Cache, CI, OldDst);
550 Value *NewSrc = wrapPtrIfASNotZero(Cache, CI, OldSrc);
551 if (OldDst == NewDst && OldSrc == NewSrc)
552 return nullptr;
553
554 // memmove(new_dst, dst_align, new_src, src_align, len, isvolatile, md)
555 Value *Len = CI->getArgOperand(2);
556
557 auto *MT = cast<MemTransferInst>(CI);
558 MaybeAlign DstAlign = MT->getDestAlign();
559 MaybeAlign SrcAlign = MT->getSourceAlign();
560 bool IsVolatile = MT->isVolatile();
561
562 return B.CreateMemMove(NewDst, DstAlign, NewSrc, SrcAlign, Len, IsVolatile,
563 MI->getAAMetadata());
564}
565
566// Support for BPF address spaces:
567// - for each function in the module M, update pointer operand of
568// each memory access instruction (load/store/cmpxchg/atomicrmw)
569// or intrinsic call insns (memset/memcpy/memmove)
570// by casting it from non-zero address space to zero address space, e.g:
571//
572// (load (ptr addrspace (N) %p) ...)
573// -> (load (addrspacecast ptr addrspace (N) %p to ptr))
574//
575// - assign section with name .addr_space.N for globals defined in
576// non-zero address space N
577static bool insertASpaceCasts(Module &M) {
578 bool Changed = false;
579 for (Function &F : M) {
581 for (BasicBlock &BB : F) {
583 unsigned PtrOpNum;
584
585 if (auto *LD = dyn_cast<LoadInst>(&I)) {
586 PtrOpNum = LD->getPointerOperandIndex();
587 aspaceWrapOperand(CastsCache, &I, PtrOpNum);
588 continue;
589 }
590 if (auto *ST = dyn_cast<StoreInst>(&I)) {
591 PtrOpNum = ST->getPointerOperandIndex();
592 aspaceWrapOperand(CastsCache, &I, PtrOpNum);
593 continue;
594 }
595 if (auto *CmpXchg = dyn_cast<AtomicCmpXchgInst>(&I)) {
596 PtrOpNum = CmpXchg->getPointerOperandIndex();
597 aspaceWrapOperand(CastsCache, &I, PtrOpNum);
598 continue;
599 }
600 if (auto *RMW = dyn_cast<AtomicRMWInst>(&I)) {
601 PtrOpNum = RMW->getPointerOperandIndex();
602 aspaceWrapOperand(CastsCache, &I, PtrOpNum);
603 continue;
604 }
605
606 auto *CI = dyn_cast<CallInst>(&I);
607 if (!CI)
608 continue;
609
610 Function *Callee = CI->getCalledFunction();
611 if (!Callee || !Callee->isIntrinsic())
612 continue;
613
614 // Check memset/memcpy/memmove
615 Intrinsic::ID ID = Callee->getIntrinsicID();
616 bool IsSet = ID == Intrinsic::memset || ID == Intrinsic::memset_inline;
617 bool IsCpy = ID == Intrinsic::memcpy || ID == Intrinsic::memcpy_inline;
618 bool IsMove = ID == Intrinsic::memmove;
619 if (!IsSet && !IsCpy && !IsMove)
620 continue;
621
622 Instruction *New;
623 if (IsSet)
624 New = aspaceMemSet(ID, CastsCache, CI);
625 else if (IsCpy)
626 New = aspaceMemCpy(ID, CastsCache, CI);
627 else
628 New = aspaceMemMove(CastsCache, CI);
629
630 if (!New)
631 continue;
632
633 I.replaceAllUsesWith(New);
634 New->takeName(&I);
635 I.eraseFromParent();
636 }
637 }
638 Changed |= !CastsCache.empty();
639 }
640 // Merge all globals within same address space into single
641 // .addr_space.<addr space no> section
642 for (GlobalVariable &G : M.globals()) {
643 if (G.getAddressSpace() == 0 || G.hasSection())
644 continue;
645 SmallString<16> SecName;
646 raw_svector_ostream OS(SecName);
647 OS << ".addr_space." << G.getAddressSpace();
648 G.setSection(SecName);
649 // Prevent having separate section for constants
650 G.setConstant(false);
651 }
652 return Changed;
653}
654
655// There is no range check in front of a jump table when the default of the
656// switch is unreachable. The compiler knows that the value is one of the cases,
657// e.g. the discriminant of an enum that was loaded from memory. The verifier
658// doesn't and rejects the load from the table.
659//
660// Anything can be the default of such a switch. Take the destination that most
661// cases go to and drop these cases. A switch that becomes compares needs as
662// many of them as before.
664 bool Changed = false;
665
666 for (Function &F : M) {
667 for (BasicBlock &BB : F) {
669
670 if (!SI || !SI->getNumCases() ||
671 !isa<UnreachableInst>(*SI->getDefaultDest()->getFirstNonPHIIt()))
672 continue;
673
675 for (auto &Case : SI->cases())
676 ++Cnt[Case.getCaseSuccessor()];
677 BasicBlock *Dest = max_element(Cnt, [](const auto &A, const auto &B) {
678 return A.second < B.second;
679 })->first;
680
681 for (PHINode &Phi : Dest->phis())
682 Phi.addIncoming(Phi.getIncomingValueForBlock(&BB), &BB);
683 SI->getDefaultDest()->removePredecessor(&BB);
684 SI->setDefaultDest(Dest);
685
687 for (auto It = SIW->case_begin(); It != SIW->case_end();) {
688 if (It->getCaseSuccessor() != Dest) {
689 ++It;
690 continue;
691 }
692 Dest->removePredecessor(&BB);
693 It = SIW.removeCase(It);
694 }
695 Changed = true;
696 }
697 }
698 return Changed;
699}
700
701static bool adjustIR(Module &M,
702 function_ref<LoopInfo &(Function &)> GetLoopInfo) {
705 Changed = sinkMinMax(M, GetLoopInfo) || Changed;
709 return Changed;
710}
711
712bool BPFCheckAndAdjustIRLegacy::runOnModule(Module &M) {
713 checkIR(M);
714 return adjustIR(M, [&](Function &F) -> LoopInfo & {
715 return getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
716 });
717}
718
721 checkIR(M);
722 bool Changed = adjustIR(M, [&](Function &F) -> LoopInfo & {
723 return MAM.getResult<FunctionAnalysisManagerModuleProxy>(M)
724 .getManager()
725 .getResult<LoopAnalysis>(F);
726 });
729}
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 giveSwitchesDefault(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:665
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
This file implements a map that provides insertion order iteration.
#define P(N)
ModuleAnalysisManager MAM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file contains the declarations for profiling metadata utility functions.
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:64
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
Definition BPFCORE.h:62
static std::pair< GetElementPtrInst *, StoreInst * > reconstructStore(CallInst *Call)
static std::pair< GetElementPtrInst *, LoadInst * > reconstructLoad(CallInst *Call)
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
Definition BasicBlock.h:509
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
LLVM_ABI void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
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:716
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:2909
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:594
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
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
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.
This class represents the LLVM 'select' instruction.
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.
A wrapper class to simplify modification of SwitchInst cases along with their prof branch_weights met...
LLVM_ABI SwitchInst::CaseIt removeCase(SwitchInst::CaseIt I)
Delegate the call to the underlying SwitchInst::removeCase() and remove correspondent branch weight.
CaseIt case_end()
Returns a read/write iterator that points one past the last in the SwitchInst.
CaseIt case_begin()
Returns a read/write iterator that points to the first case in the SwitchInst.
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:257
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:549
bool use_empty() const
Definition Value.h:348
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
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
Pass manager infrastructure for declaring and invalidating analyses.
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:1748
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
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:649
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
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2104
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:111