xref: /llvm-project/llvm/lib/Target/BPF/BPFAdjustOpt.cpp (revision 6292a808b3524d9ba6f4ce55bc5b9e547b088dd8)
1ddf1864aSYonghong Song //===---------------- BPFAdjustOpt.cpp - Adjust Optimization --------------===//
2ddf1864aSYonghong Song //
3ddf1864aSYonghong Song // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ddf1864aSYonghong Song // See https://llvm.org/LICENSE.txt for license information.
5ddf1864aSYonghong Song // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ddf1864aSYonghong Song //
7ddf1864aSYonghong Song //===----------------------------------------------------------------------===//
8ddf1864aSYonghong Song //
9ddf1864aSYonghong Song // Adjust optimization to make the code more kernel verifier friendly.
10ddf1864aSYonghong Song //
11ddf1864aSYonghong Song //===----------------------------------------------------------------------===//
12ddf1864aSYonghong Song 
13ddf1864aSYonghong Song #include "BPF.h"
14ddf1864aSYonghong Song #include "BPFCORE.h"
15ddf1864aSYonghong Song #include "llvm/IR/Instruction.h"
16ddf1864aSYonghong Song #include "llvm/IR/Instructions.h"
17f63405f6SYonghong Song #include "llvm/IR/IntrinsicsBPF.h"
18ddf1864aSYonghong Song #include "llvm/IR/Module.h"
19e4d751c2SJuneyoung Lee #include "llvm/IR/PatternMatch.h"
20ddf1864aSYonghong Song #include "llvm/IR/Type.h"
21ddf1864aSYonghong Song #include "llvm/IR/User.h"
22ddf1864aSYonghong Song #include "llvm/IR/Value.h"
23ddf1864aSYonghong Song #include "llvm/Pass.h"
24ddf1864aSYonghong Song #include "llvm/Transforms/Utils/BasicBlockUtils.h"
25ddf1864aSYonghong Song 
26ddf1864aSYonghong Song #define DEBUG_TYPE "bpf-adjust-opt"
27ddf1864aSYonghong Song 
28ddf1864aSYonghong Song using namespace llvm;
29e4d751c2SJuneyoung Lee using namespace llvm::PatternMatch;
30ddf1864aSYonghong Song 
31ddf1864aSYonghong Song static cl::opt<bool>
32ddf1864aSYonghong Song     DisableBPFserializeICMP("bpf-disable-serialize-icmp", cl::Hidden,
33ddf1864aSYonghong Song                             cl::desc("BPF: Disable Serializing ICMP insns."),
34ddf1864aSYonghong Song                             cl::init(false));
35ddf1864aSYonghong Song 
36ddf1864aSYonghong Song static cl::opt<bool> DisableBPFavoidSpeculation(
37ddf1864aSYonghong Song     "bpf-disable-avoid-speculation", cl::Hidden,
38ddf1864aSYonghong Song     cl::desc("BPF: Disable Avoiding Speculative Code Motion."),
39ddf1864aSYonghong Song     cl::init(false));
40ddf1864aSYonghong Song 
41ddf1864aSYonghong Song namespace {
4292a67e13SArthur Eubanks class BPFAdjustOptImpl {
43ddf1864aSYonghong Song   struct PassThroughInfo {
44ddf1864aSYonghong Song     Instruction *Input;
45ddf1864aSYonghong Song     Instruction *UsedInst;
46ddf1864aSYonghong Song     uint32_t OpIdx;
47ddf1864aSYonghong Song     PassThroughInfo(Instruction *I, Instruction *U, uint32_t Idx)
48ddf1864aSYonghong Song         : Input(I), UsedInst(U), OpIdx(Idx) {}
49ddf1864aSYonghong Song   };
50ddf1864aSYonghong Song 
51ddf1864aSYonghong Song public:
5292a67e13SArthur Eubanks   BPFAdjustOptImpl(Module *M) : M(M) {}
53ddf1864aSYonghong Song 
5492a67e13SArthur Eubanks   bool run();
55ddf1864aSYonghong Song 
56ddf1864aSYonghong Song private:
5792a67e13SArthur Eubanks   Module *M;
58ddf1864aSYonghong Song   SmallVector<PassThroughInfo, 16> PassThroughs;
59ddf1864aSYonghong Song 
60f63405f6SYonghong Song   bool adjustICmpToBuiltin();
61ddf1864aSYonghong Song   void adjustBasicBlock(BasicBlock &BB);
62ddf1864aSYonghong Song   bool serializeICMPCrossBB(BasicBlock &BB);
63ddf1864aSYonghong Song   void adjustInst(Instruction &I);
64ddf1864aSYonghong Song   bool serializeICMPInBB(Instruction &I);
65ddf1864aSYonghong Song   bool avoidSpeculation(Instruction &I);
66ddf1864aSYonghong Song   bool insertPassThrough();
67ddf1864aSYonghong Song };
68ddf1864aSYonghong Song 
69ddf1864aSYonghong Song } // End anonymous namespace
70ddf1864aSYonghong Song 
7192a67e13SArthur Eubanks bool BPFAdjustOptImpl::run() {
72f63405f6SYonghong Song   bool Changed = adjustICmpToBuiltin();
73f63405f6SYonghong Song 
7492a67e13SArthur Eubanks   for (Function &F : *M)
75ddf1864aSYonghong Song     for (auto &BB : F) {
76ddf1864aSYonghong Song       adjustBasicBlock(BB);
77ddf1864aSYonghong Song       for (auto &I : BB)
78ddf1864aSYonghong Song         adjustInst(I);
79ddf1864aSYonghong Song     }
80f63405f6SYonghong Song   return insertPassThrough() || Changed;
81f63405f6SYonghong Song }
82ddf1864aSYonghong Song 
83f63405f6SYonghong Song // Commit acabad9ff6bf ("[InstCombine] try to canonicalize icmp with
84f63405f6SYonghong Song // trunc op into mask and cmp") added a transformation to
85f63405f6SYonghong Song // convert "(conv)a < power_2_const" to "a & <const>" in certain
86f63405f6SYonghong Song // cases and bpf kernel verifier has to handle the resulted code
87f63405f6SYonghong Song // conservatively and this may reject otherwise legitimate program.
88f63405f6SYonghong Song // Here, we change related icmp code to a builtin which will
89f63405f6SYonghong Song // be restored to original icmp code later to prevent that
90f63405f6SYonghong Song // InstCombine transformatin.
91f63405f6SYonghong Song bool BPFAdjustOptImpl::adjustICmpToBuiltin() {
92f63405f6SYonghong Song   bool Changed = false;
93f63405f6SYonghong Song   ICmpInst *ToBeDeleted = nullptr;
94f63405f6SYonghong Song   for (Function &F : *M)
95f63405f6SYonghong Song     for (auto &BB : F)
96f63405f6SYonghong Song       for (auto &I : BB) {
97f63405f6SYonghong Song         if (ToBeDeleted) {
98f63405f6SYonghong Song           ToBeDeleted->eraseFromParent();
99f63405f6SYonghong Song           ToBeDeleted = nullptr;
100f63405f6SYonghong Song         }
101f63405f6SYonghong Song 
102f63405f6SYonghong Song         auto *Icmp = dyn_cast<ICmpInst>(&I);
103f63405f6SYonghong Song         if (!Icmp)
104f63405f6SYonghong Song           continue;
105f63405f6SYonghong Song 
106f63405f6SYonghong Song         Value *Op0 = Icmp->getOperand(0);
107f63405f6SYonghong Song         if (!isa<TruncInst>(Op0))
108f63405f6SYonghong Song           continue;
109f63405f6SYonghong Song 
110f63405f6SYonghong Song         auto ConstOp1 = dyn_cast<ConstantInt>(Icmp->getOperand(1));
111f63405f6SYonghong Song         if (!ConstOp1)
112f63405f6SYonghong Song           continue;
113f63405f6SYonghong Song 
114f63405f6SYonghong Song         auto ConstOp1Val = ConstOp1->getValue().getZExtValue();
115f63405f6SYonghong Song         auto Op = Icmp->getPredicate();
1168fb3f844SYonghong Song         if (Op == ICmpInst::ICMP_ULT || Op == ICmpInst::ICMP_UGE) {
117f63405f6SYonghong Song           if ((ConstOp1Val - 1) & ConstOp1Val)
118f63405f6SYonghong Song             continue;
1198fb3f844SYonghong Song         } else if (Op == ICmpInst::ICMP_ULE || Op == ICmpInst::ICMP_UGT) {
120f63405f6SYonghong Song           if (ConstOp1Val & (ConstOp1Val + 1))
121f63405f6SYonghong Song             continue;
122f63405f6SYonghong Song         } else {
123f63405f6SYonghong Song           continue;
124f63405f6SYonghong Song         }
125f63405f6SYonghong Song 
126f63405f6SYonghong Song         Constant *Opcode =
127f63405f6SYonghong Song             ConstantInt::get(Type::getInt32Ty(BB.getContext()), Op);
128fa789dffSRahul Joshi         Function *Fn = Intrinsic::getOrInsertDeclaration(
129f63405f6SYonghong Song             M, Intrinsic::bpf_compare, {Op0->getType(), ConstOp1->getType()});
130f63405f6SYonghong Song         auto *NewInst = CallInst::Create(Fn, {Opcode, Op0, ConstOp1});
1318e702735SJeremy Morse         NewInst->insertBefore(I.getIterator());
132f63405f6SYonghong Song         Icmp->replaceAllUsesWith(NewInst);
133f63405f6SYonghong Song         Changed = true;
134f63405f6SYonghong Song         ToBeDeleted = Icmp;
135f63405f6SYonghong Song       }
136f63405f6SYonghong Song 
137f63405f6SYonghong Song   return Changed;
138ddf1864aSYonghong Song }
139ddf1864aSYonghong Song 
14092a67e13SArthur Eubanks bool BPFAdjustOptImpl::insertPassThrough() {
141ddf1864aSYonghong Song   for (auto &Info : PassThroughs) {
142ddf1864aSYonghong Song     auto *CI = BPFCoreSharedInfo::insertPassThrough(
14392a67e13SArthur Eubanks         M, Info.UsedInst->getParent(), Info.Input, Info.UsedInst);
144ddf1864aSYonghong Song     Info.UsedInst->setOperand(Info.OpIdx, CI);
145ddf1864aSYonghong Song   }
146ddf1864aSYonghong Song 
147ddf1864aSYonghong Song   return !PassThroughs.empty();
148ddf1864aSYonghong Song }
149ddf1864aSYonghong Song 
150ddf1864aSYonghong Song // To avoid combining conditionals in the same basic block by
151ddf1864aSYonghong Song // instrcombine optimization.
15292a67e13SArthur Eubanks bool BPFAdjustOptImpl::serializeICMPInBB(Instruction &I) {
153ddf1864aSYonghong Song   // For:
154ddf1864aSYonghong Song   //   comp1 = icmp <opcode> ...;
155ddf1864aSYonghong Song   //   comp2 = icmp <opcode> ...;
156ddf1864aSYonghong Song   //   ... or comp1 comp2 ...
157ddf1864aSYonghong Song   // changed to:
158ddf1864aSYonghong Song   //   comp1 = icmp <opcode> ...;
159ddf1864aSYonghong Song   //   comp2 = icmp <opcode> ...;
160ddf1864aSYonghong Song   //   new_comp1 = __builtin_bpf_passthrough(seq_num, comp1)
161ddf1864aSYonghong Song   //   ... or new_comp1 comp2 ...
162e4d751c2SJuneyoung Lee   Value *Op0, *Op1;
163e4d751c2SJuneyoung Lee   // Use LogicalOr (accept `or i1` as well as `select i1 Op0, true, Op1`)
164e4d751c2SJuneyoung Lee   if (!match(&I, m_LogicalOr(m_Value(Op0), m_Value(Op1))))
165ddf1864aSYonghong Song     return false;
166e4d751c2SJuneyoung Lee   auto *Icmp1 = dyn_cast<ICmpInst>(Op0);
167ddf1864aSYonghong Song   if (!Icmp1)
168ddf1864aSYonghong Song     return false;
169e4d751c2SJuneyoung Lee   auto *Icmp2 = dyn_cast<ICmpInst>(Op1);
170ddf1864aSYonghong Song   if (!Icmp2)
171ddf1864aSYonghong Song     return false;
172ddf1864aSYonghong Song 
173ddf1864aSYonghong Song   Value *Icmp1Op0 = Icmp1->getOperand(0);
174ddf1864aSYonghong Song   Value *Icmp2Op0 = Icmp2->getOperand(0);
175ddf1864aSYonghong Song   if (Icmp1Op0 != Icmp2Op0)
176ddf1864aSYonghong Song     return false;
177ddf1864aSYonghong Song 
178ddf1864aSYonghong Song   // Now we got two icmp instructions which feed into
179ddf1864aSYonghong Song   // an "or" instruction.
180ddf1864aSYonghong Song   PassThroughInfo Info(Icmp1, &I, 0);
181ddf1864aSYonghong Song   PassThroughs.push_back(Info);
182ddf1864aSYonghong Song   return true;
183ddf1864aSYonghong Song }
184ddf1864aSYonghong Song 
185ddf1864aSYonghong Song // To avoid combining conditionals in the same basic block by
186ddf1864aSYonghong Song // instrcombine optimization.
18792a67e13SArthur Eubanks bool BPFAdjustOptImpl::serializeICMPCrossBB(BasicBlock &BB) {
188ddf1864aSYonghong Song   // For:
189ddf1864aSYonghong Song   //   B1:
190ddf1864aSYonghong Song   //     comp1 = icmp <opcode> ...;
191ddf1864aSYonghong Song   //     if (comp1) goto B2 else B3;
192ddf1864aSYonghong Song   //   B2:
193ddf1864aSYonghong Song   //     comp2 = icmp <opcode> ...;
194ddf1864aSYonghong Song   //     if (comp2) goto B4 else B5;
195ddf1864aSYonghong Song   //   B4:
196ddf1864aSYonghong Song   //     ...
197ddf1864aSYonghong Song   // changed to:
198ddf1864aSYonghong Song   //   B1:
199ddf1864aSYonghong Song   //     comp1 = icmp <opcode> ...;
200ddf1864aSYonghong Song   //     comp1 = __builtin_bpf_passthrough(seq_num, comp1);
201ddf1864aSYonghong Song   //     if (comp1) goto B2 else B3;
202ddf1864aSYonghong Song   //   B2:
203ddf1864aSYonghong Song   //     comp2 = icmp <opcode> ...;
204ddf1864aSYonghong Song   //     if (comp2) goto B4 else B5;
205ddf1864aSYonghong Song   //   B4:
206ddf1864aSYonghong Song   //     ...
207ddf1864aSYonghong Song 
208ddf1864aSYonghong Song   // Check basic predecessors, if two of them (say B1, B2) are using
209ddf1864aSYonghong Song   // icmp instructions to generate conditions and one is the predesessor
210ddf1864aSYonghong Song   // of another (e.g., B1 is the predecessor of B2). Add a passthrough
211ddf1864aSYonghong Song   // barrier after icmp inst of block B1.
212ddf1864aSYonghong Song   BasicBlock *B2 = BB.getSinglePredecessor();
213ddf1864aSYonghong Song   if (!B2)
214ddf1864aSYonghong Song     return false;
215ddf1864aSYonghong Song 
216ddf1864aSYonghong Song   BasicBlock *B1 = B2->getSinglePredecessor();
217ddf1864aSYonghong Song   if (!B1)
218ddf1864aSYonghong Song     return false;
219ddf1864aSYonghong Song 
220ddf1864aSYonghong Song   Instruction *TI = B2->getTerminator();
221ddf1864aSYonghong Song   auto *BI = dyn_cast<BranchInst>(TI);
222ddf1864aSYonghong Song   if (!BI || !BI->isConditional())
223ddf1864aSYonghong Song     return false;
224ddf1864aSYonghong Song   auto *Cond = dyn_cast<ICmpInst>(BI->getCondition());
225*6292a808SJeremy Morse   if (!Cond || &*B2->getFirstNonPHIIt() != Cond)
226ddf1864aSYonghong Song     return false;
227ddf1864aSYonghong Song   Value *B2Op0 = Cond->getOperand(0);
228ddf1864aSYonghong Song   auto Cond2Op = Cond->getPredicate();
229ddf1864aSYonghong Song 
230ddf1864aSYonghong Song   TI = B1->getTerminator();
231ddf1864aSYonghong Song   BI = dyn_cast<BranchInst>(TI);
232ddf1864aSYonghong Song   if (!BI || !BI->isConditional())
233ddf1864aSYonghong Song     return false;
234ddf1864aSYonghong Song   Cond = dyn_cast<ICmpInst>(BI->getCondition());
235ddf1864aSYonghong Song   if (!Cond)
236ddf1864aSYonghong Song     return false;
237ddf1864aSYonghong Song   Value *B1Op0 = Cond->getOperand(0);
238ddf1864aSYonghong Song   auto Cond1Op = Cond->getPredicate();
239ddf1864aSYonghong Song 
240ddf1864aSYonghong Song   if (B1Op0 != B2Op0)
241ddf1864aSYonghong Song     return false;
242ddf1864aSYonghong Song 
243ddf1864aSYonghong Song   if (Cond1Op == ICmpInst::ICMP_SGT || Cond1Op == ICmpInst::ICMP_SGE) {
244d2b4a675SYonghong Song     if (Cond2Op != ICmpInst::ICMP_SLT && Cond2Op != ICmpInst::ICMP_SLE)
245ddf1864aSYonghong Song       return false;
246ddf1864aSYonghong Song   } else if (Cond1Op == ICmpInst::ICMP_SLT || Cond1Op == ICmpInst::ICMP_SLE) {
247d2b4a675SYonghong Song     if (Cond2Op != ICmpInst::ICMP_SGT && Cond2Op != ICmpInst::ICMP_SGE)
248ddf1864aSYonghong Song       return false;
2492e94d8e6SYonghong Song   } else if (Cond1Op == ICmpInst::ICMP_ULT || Cond1Op == ICmpInst::ICMP_ULE) {
2502e94d8e6SYonghong Song     if (Cond2Op != ICmpInst::ICMP_UGT && Cond2Op != ICmpInst::ICMP_UGE)
2512e94d8e6SYonghong Song       return false;
2522e94d8e6SYonghong Song   } else if (Cond1Op == ICmpInst::ICMP_UGT || Cond1Op == ICmpInst::ICMP_UGE) {
2532e94d8e6SYonghong Song     if (Cond2Op != ICmpInst::ICMP_ULT && Cond2Op != ICmpInst::ICMP_ULE)
2542e94d8e6SYonghong Song       return false;
255ddf1864aSYonghong Song   } else {
256ddf1864aSYonghong Song     return false;
257ddf1864aSYonghong Song   }
258ddf1864aSYonghong Song 
259ddf1864aSYonghong Song   PassThroughInfo Info(Cond, BI, 0);
260ddf1864aSYonghong Song   PassThroughs.push_back(Info);
261ddf1864aSYonghong Song 
262ddf1864aSYonghong Song   return true;
263ddf1864aSYonghong Song }
264ddf1864aSYonghong Song 
265ddf1864aSYonghong Song // To avoid speculative hoisting certain computations out of
266ddf1864aSYonghong Song // a basic block.
26792a67e13SArthur Eubanks bool BPFAdjustOptImpl::avoidSpeculation(Instruction &I) {
268ddf1864aSYonghong Song   if (auto *LdInst = dyn_cast<LoadInst>(&I)) {
269ddf1864aSYonghong Song     if (auto *GV = dyn_cast<GlobalVariable>(LdInst->getOperand(0))) {
270ddf1864aSYonghong Song       if (GV->hasAttribute(BPFCoreSharedInfo::AmaAttr) ||
271ddf1864aSYonghong Song           GV->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))
272ddf1864aSYonghong Song         return false;
273ddf1864aSYonghong Song     }
274ddf1864aSYonghong Song   }
275ddf1864aSYonghong Song 
276b557c32aSKazu Hirata   if (!isa<LoadInst>(&I) && !isa<CallInst>(&I))
277ddf1864aSYonghong Song     return false;
278ddf1864aSYonghong Song 
279ddf1864aSYonghong Song   // For:
280ddf1864aSYonghong Song   //   B1:
281ddf1864aSYonghong Song   //     var = ...
282ddf1864aSYonghong Song   //     ...
283ddf1864aSYonghong Song   //     /* icmp may not be in the same block as var = ... */
284ddf1864aSYonghong Song   //     comp1 = icmp <opcode> var, <const>;
285ddf1864aSYonghong Song   //     if (comp1) goto B2 else B3;
286ddf1864aSYonghong Song   //   B2:
287ddf1864aSYonghong Song   //     ... var ...
288ddf1864aSYonghong Song   // change to:
289ddf1864aSYonghong Song   //   B1:
290ddf1864aSYonghong Song   //     var = ...
291ddf1864aSYonghong Song   //     ...
292ddf1864aSYonghong Song   //     /* icmp may not be in the same block as var = ... */
293ddf1864aSYonghong Song   //     comp1 = icmp <opcode> var, <const>;
294ddf1864aSYonghong Song   //     if (comp1) goto B2 else B3;
295ddf1864aSYonghong Song   //   B2:
296ddf1864aSYonghong Song   //     var = __builtin_bpf_passthrough(seq_num, var);
297ddf1864aSYonghong Song   //     ... var ...
298ddf1864aSYonghong Song   bool isCandidate = false;
299ddf1864aSYonghong Song   SmallVector<PassThroughInfo, 4> Candidates;
300ddf1864aSYonghong Song   for (User *U : I.users()) {
301ddf1864aSYonghong Song     Instruction *Inst = dyn_cast<Instruction>(U);
302ddf1864aSYonghong Song     if (!Inst)
303ddf1864aSYonghong Song       continue;
304ddf1864aSYonghong Song 
305ddf1864aSYonghong Song     // May cover a little bit more than the
306ddf1864aSYonghong Song     // above pattern.
307ddf1864aSYonghong Song     if (auto *Icmp1 = dyn_cast<ICmpInst>(Inst)) {
308ddf1864aSYonghong Song       Value *Icmp1Op1 = Icmp1->getOperand(1);
309ddf1864aSYonghong Song       if (!isa<Constant>(Icmp1Op1))
310ddf1864aSYonghong Song         return false;
311ddf1864aSYonghong Song       isCandidate = true;
312ddf1864aSYonghong Song       continue;
313ddf1864aSYonghong Song     }
314ddf1864aSYonghong Song 
315ddf1864aSYonghong Song     // Ignore the use in the same basic block as the definition.
316ddf1864aSYonghong Song     if (Inst->getParent() == I.getParent())
317ddf1864aSYonghong Song       continue;
318ddf1864aSYonghong Song 
319ddf1864aSYonghong Song     // use in a different basic block, If there is a call or
320ddf1864aSYonghong Song     // load/store insn before this instruction in this basic
321ddf1864aSYonghong Song     // block. Most likely it cannot be hoisted out. Skip it.
322ddf1864aSYonghong Song     for (auto &I2 : *Inst->getParent()) {
3238ed16361SKazu Hirata       if (isa<CallInst>(&I2))
324ddf1864aSYonghong Song         return false;
3258ed16361SKazu Hirata       if (isa<LoadInst>(&I2) || isa<StoreInst>(&I2))
326ddf1864aSYonghong Song         return false;
327ddf1864aSYonghong Song       if (&I2 == Inst)
328ddf1864aSYonghong Song         break;
329ddf1864aSYonghong Song     }
330ddf1864aSYonghong Song 
331ddf1864aSYonghong Song     // It should be used in a GEP or a simple arithmetic like
332ddf1864aSYonghong Song     // ZEXT/SEXT which is used for GEP.
333ddf1864aSYonghong Song     if (Inst->getOpcode() == Instruction::ZExt ||
334ddf1864aSYonghong Song         Inst->getOpcode() == Instruction::SExt) {
335ddf1864aSYonghong Song       PassThroughInfo Info(&I, Inst, 0);
336ddf1864aSYonghong Song       Candidates.push_back(Info);
337ddf1864aSYonghong Song     } else if (auto *GI = dyn_cast<GetElementPtrInst>(Inst)) {
338ddf1864aSYonghong Song       // traverse GEP inst to find Use operand index
339ddf1864aSYonghong Song       unsigned i, e;
340ddf1864aSYonghong Song       for (i = 1, e = GI->getNumOperands(); i != e; ++i) {
341ddf1864aSYonghong Song         Value *V = GI->getOperand(i);
342ddf1864aSYonghong Song         if (V == &I)
343ddf1864aSYonghong Song           break;
344ddf1864aSYonghong Song       }
345ddf1864aSYonghong Song       if (i == e)
346ddf1864aSYonghong Song         continue;
347ddf1864aSYonghong Song 
348ddf1864aSYonghong Song       PassThroughInfo Info(&I, GI, i);
349ddf1864aSYonghong Song       Candidates.push_back(Info);
350ddf1864aSYonghong Song     }
351ddf1864aSYonghong Song   }
352ddf1864aSYonghong Song 
353ddf1864aSYonghong Song   if (!isCandidate || Candidates.empty())
354ddf1864aSYonghong Song     return false;
355ddf1864aSYonghong Song 
356985f899bSKazu Hirata   llvm::append_range(PassThroughs, Candidates);
357ddf1864aSYonghong Song   return true;
358ddf1864aSYonghong Song }
359ddf1864aSYonghong Song 
36092a67e13SArthur Eubanks void BPFAdjustOptImpl::adjustBasicBlock(BasicBlock &BB) {
361ddf1864aSYonghong Song   if (!DisableBPFserializeICMP && serializeICMPCrossBB(BB))
362ddf1864aSYonghong Song     return;
363ddf1864aSYonghong Song }
364ddf1864aSYonghong Song 
36592a67e13SArthur Eubanks void BPFAdjustOptImpl::adjustInst(Instruction &I) {
366ddf1864aSYonghong Song   if (!DisableBPFserializeICMP && serializeICMPInBB(I))
367ddf1864aSYonghong Song     return;
368ddf1864aSYonghong Song   if (!DisableBPFavoidSpeculation && avoidSpeculation(I))
369ddf1864aSYonghong Song     return;
370ddf1864aSYonghong Song }
37192a67e13SArthur Eubanks 
37292a67e13SArthur Eubanks PreservedAnalyses BPFAdjustOptPass::run(Module &M, ModuleAnalysisManager &AM) {
37392a67e13SArthur Eubanks   return BPFAdjustOptImpl(&M).run() ? PreservedAnalyses::none()
37492a67e13SArthur Eubanks                                     : PreservedAnalyses::all();
37592a67e13SArthur Eubanks }
376