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 {
48 :
Input(
I), UsedInst(U), OpIdx(Idx) {}
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();
77 if (
F.isDeclaration() ||
F.hasLocalLinkage())
79 F.addFnAttr(Attribute::NoIPA);
89 return insertPassThrough() ||
Changed;
100bool BPFAdjustOptImpl::adjustICmpToBuiltin() {
102 ICmpInst *ToBeDeleted =
nullptr;
108 ToBeDeleted =
nullptr;
115 Value *Op0 = Icmp->getOperand(0);
123 auto ConstOp1Val = ConstOp1->getValue().getZExtValue();
124 auto Op = Icmp->getPredicate();
125 if (
Op == ICmpInst::ICMP_ULT ||
Op == ICmpInst::ICMP_UGE) {
126 if ((ConstOp1Val - 1) & ConstOp1Val)
128 }
else if (
Op == ICmpInst::ICMP_ULE ||
Op == ICmpInst::ICMP_UGT) {
129 if (ConstOp1Val & (ConstOp1Val + 1))
136 ConstantInt::get(Type::getInt32Ty(BB.getContext()),
Op);
138 M, Intrinsic::bpf_compare, {Op0->
getType(), ConstOp1->getType()});
141 Icmp->replaceAllUsesWith(NewInst);
149bool BPFAdjustOptImpl::insertPassThrough() {
150 for (
auto &Info : PassThroughs) {
152 M,
Info.UsedInst->getParent(),
Info.Input,
Info.UsedInst);
153 Info.UsedInst->setOperand(
Info.OpIdx, CI);
156 return !PassThroughs.empty();
161bool BPFAdjustOptImpl::serializeICMPInBB(Instruction &
I) {
182 Value *Icmp1Op0 = Icmp1->getOperand(0);
183 Value *Icmp2Op0 = Icmp2->getOperand(0);
184 if (Icmp1Op0 != Icmp2Op0)
189 PassThroughInfo
Info(Icmp1, &
I, 0);
190 PassThroughs.push_back(Info);
196bool BPFAdjustOptImpl::serializeICMPCrossBB(BasicBlock &BB) {
234 if (!
Cond || &*
B2->getFirstNonPHIIt() !=
Cond)
237 auto Cond2Op =
Cond->getPredicate();
239 TI =
B1->getTerminator();
247 auto Cond1Op =
Cond->getPredicate();
252 if (Cond1Op == ICmpInst::ICMP_SGT || Cond1Op == ICmpInst::ICMP_SGE) {
253 if (Cond2Op != ICmpInst::ICMP_SLT && Cond2Op != ICmpInst::ICMP_SLE)
255 }
else if (Cond1Op == ICmpInst::ICMP_SLT || Cond1Op == ICmpInst::ICMP_SLE) {
256 if (Cond2Op != ICmpInst::ICMP_SGT && Cond2Op != ICmpInst::ICMP_SGE)
258 }
else if (Cond1Op == ICmpInst::ICMP_ULT || Cond1Op == ICmpInst::ICMP_ULE) {
259 if (Cond2Op != ICmpInst::ICMP_UGT && Cond2Op != ICmpInst::ICMP_UGE)
261 }
else if (Cond1Op == ICmpInst::ICMP_UGT || Cond1Op == ICmpInst::ICMP_UGE) {
262 if (Cond2Op != ICmpInst::ICMP_ULT && Cond2Op != ICmpInst::ICMP_ULE)
269 PassThroughs.push_back(Info);
276bool BPFAdjustOptImpl::avoidSpeculation(Instruction &
I) {
309 for (User *U :
I.users()) {
317 Value *Icmp1Op1 = Icmp1->getOperand(1);
342 if (Inst->
getOpcode() == Instruction::ZExt ||
343 Inst->
getOpcode() == Instruction::SExt) {
344 PassThroughInfo
Info(&
I, Inst, 0);
349 for (i = 1, e = GI->getNumOperands(); i != e; ++i) {
350 Value *
V = GI->getOperand(i);
357 PassThroughInfo
Info(&
I, GI, i);
369void BPFAdjustOptImpl::adjustBasicBlock(BasicBlock &BB) {
374void 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))
Module.h This file contains the declarations for the Module class.
static bool isCandidate(const MachineInstr *MI, Register &DefedReg, Register FrameReg)
SmallVector< MachineOperand, 4 > 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 const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
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 * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
auto m_LogicalOr()
Matches L || R where L and R are arbitrary values.
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.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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.