17#include "llvm/IR/IntrinsicsBPF.h"
26#define DEBUG_TYPE "bpf-adjust-opt"
33 cl::desc(
"BPF: Disable Serializing ICMP insns."),
38 cl::desc(
"BPF: Disable Avoiding Speculative Code Motion."),
42class BPFAdjustOptImpl {
43 struct PassThroughInfo {
52 BPFAdjustOptImpl(
Module *M) : M(M) {}
60 bool adjustICmpToBuiltin();
61 void adjustBasicBlock(BasicBlock &BB);
62 bool serializeICMPCrossBB(BasicBlock &BB);
63 void adjustInst(Instruction &
I);
64 bool serializeICMPInBB(Instruction &
I);
65 bool avoidSpeculation(Instruction &
I);
66 bool insertPassThrough();
71bool BPFAdjustOptImpl::run() {
72 bool Changed = adjustICmpToBuiltin();
74 for (Function &
F : *M)
80 return insertPassThrough() ||
Changed;
91bool BPFAdjustOptImpl::adjustICmpToBuiltin() {
93 ICmpInst *ToBeDeleted =
nullptr;
94 for (Function &
F : *M)
99 ToBeDeleted =
nullptr;
106 Value *Op0 = Icmp->getOperand(0);
114 auto ConstOp1Val = ConstOp1->getValue().getZExtValue();
115 auto Op = Icmp->getPredicate();
116 if (
Op == ICmpInst::ICMP_ULT ||
Op == ICmpInst::ICMP_UGE) {
117 if ((ConstOp1Val - 1) & ConstOp1Val)
119 }
else if (
Op == ICmpInst::ICMP_ULE ||
Op == ICmpInst::ICMP_UGT) {
120 if (ConstOp1Val & (ConstOp1Val + 1))
127 ConstantInt::get(Type::getInt32Ty(BB.getContext()),
Op);
129 M, Intrinsic::bpf_compare, {Op0->
getType(), ConstOp1->getType()});
132 Icmp->replaceAllUsesWith(NewInst);
140bool BPFAdjustOptImpl::insertPassThrough() {
141 for (
auto &
Info : PassThroughs) {
143 M,
Info.UsedInst->getParent(),
Info.Input,
Info.UsedInst);
144 Info.UsedInst->setOperand(
Info.OpIdx, CI);
147 return !PassThroughs.empty();
152bool BPFAdjustOptImpl::serializeICMPInBB(Instruction &
I) {
173 Value *Icmp1Op0 = Icmp1->getOperand(0);
174 Value *Icmp2Op0 = Icmp2->getOperand(0);
175 if (Icmp1Op0 != Icmp2Op0)
180 PassThroughInfo
Info(Icmp1, &
I, 0);
181 PassThroughs.push_back(
Info);
187bool BPFAdjustOptImpl::serializeICMPCrossBB(BasicBlock &BB) {
222 if (!BI || !BI->isConditional())
228 auto Cond2Op =
Cond->getPredicate();
232 if (!BI || !BI->isConditional())
238 auto Cond1Op =
Cond->getPredicate();
243 if (Cond1Op == ICmpInst::ICMP_SGT || Cond1Op == ICmpInst::ICMP_SGE) {
244 if (Cond2Op != ICmpInst::ICMP_SLT && Cond2Op != ICmpInst::ICMP_SLE)
246 }
else if (Cond1Op == ICmpInst::ICMP_SLT || Cond1Op == ICmpInst::ICMP_SLE) {
247 if (Cond2Op != ICmpInst::ICMP_SGT && Cond2Op != ICmpInst::ICMP_SGE)
249 }
else if (Cond1Op == ICmpInst::ICMP_ULT || Cond1Op == ICmpInst::ICMP_ULE) {
250 if (Cond2Op != ICmpInst::ICMP_UGT && Cond2Op != ICmpInst::ICMP_UGE)
252 }
else if (Cond1Op == ICmpInst::ICMP_UGT || Cond1Op == ICmpInst::ICMP_UGE) {
253 if (Cond2Op != ICmpInst::ICMP_ULT && Cond2Op != ICmpInst::ICMP_ULE)
260 PassThroughs.push_back(
Info);
267bool BPFAdjustOptImpl::avoidSpeculation(Instruction &
I) {
300 for (User *U :
I.users()) {
308 Value *Icmp1Op1 = Icmp1->getOperand(1);
333 if (Inst->
getOpcode() == Instruction::ZExt ||
334 Inst->
getOpcode() == Instruction::SExt) {
335 PassThroughInfo
Info(&
I, Inst, 0);
340 for (i = 1, e = GI->getNumOperands(); i != e; ++i) {
341 Value *
V = GI->getOperand(i);
348 PassThroughInfo
Info(&
I, GI, i);
360void BPFAdjustOptImpl::adjustBasicBlock(BasicBlock &BB) {
365void BPFAdjustOptImpl::adjustInst(Instruction &
I) {
static cl::opt< bool > DisableBPFserializeICMP("bpf-disable-serialize-icmp", cl::Hidden, cl::desc("BPF: Disable Serializing ICMP insns."), cl::init(false))
static cl::opt< bool > DisableBPFavoidSpeculation("bpf-disable-avoid-speculation", cl::Hidden, cl::desc("BPF: Disable Avoiding Speculative Code Motion."), cl::init(false))
Analysis containing CSE Info
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
static bool isCandidate(const MachineInstr *MI, Register &DefedReg, Register FrameReg)
MachineInstr unsigned OpIdx
const SmallVectorImpl< MachineOperand > & Cond
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
static Instruction * insertPassThrough(Module *M, BasicBlock *BB, Instruction *Input, Instruction *Before)
Insert a bpf passthrough builtin function.
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A Module instance is used to store all the information related to an LLVM module.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void push_back(const T &Elt)
Type * getType() const
All values are typed, get the type of this value.
const ParentTy * getParent() const
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
bool match(Val *V, const Pattern &P)
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
DWARFExpression::Operation Op
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.