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