34#define DEBUG_TYPE "bpf-check-and-opt-ir"
40class BPFCheckAndAdjustIR final :
public ModulePass {
51 bool removePassThroughBuiltin(
Module &M);
52 bool removeCompareBuiltin(
Module &M);
53 bool sinkMinMax(
Module &M);
57char BPFCheckAndAdjustIR::ID = 0;
62 return new BPFCheckAndAdjustIR();
65void BPFCheckAndAdjustIR::checkIR(
Module &M) {
98bool BPFCheckAndAdjustIR::removePassThroughBuiltin(
Module &M) {
102 bool Changed =
false;
109 ToBeDeleted =
nullptr;
112 auto *
Call = dyn_cast<CallInst>(&
I);
115 auto *GV = dyn_cast<GlobalValue>(
Call->getCalledOperand());
118 if (!GV->getName().startswith(
"llvm.bpf.passthrough"))
122 Call->replaceAllUsesWith(Arg);
128bool BPFCheckAndAdjustIR::removeCompareBuiltin(
Module &M) {
132 bool Changed =
false;
139 ToBeDeleted =
nullptr;
142 auto *
Call = dyn_cast<CallInst>(&
I);
145 auto *GV = dyn_cast<GlobalValue>(
Call->getCalledOperand());
148 if (!GV->getName().startswith(
"llvm.bpf.compare"))
156 auto OpVal = cast<ConstantInt>(Arg0)->getValue().getZExtValue();
159 auto *ICmp =
new ICmpInst(Opcode, Arg1, Arg2);
160 ICmp->insertBefore(Call);
162 Call->replaceAllUsesWith(ICmp);
189 if (
auto *ZExt = dyn_cast<ZExtInst>(V)) {
190 V = ZExt->getOperand(0);
192 }
else if (
auto *SExt = dyn_cast<SExtInst>(V)) {
193 V = SExt->getOperand(0);
197 auto *Call = dyn_cast<CallInst>(V);
201 auto *Called = dyn_cast<Function>(Call->getCalledOperand());
205 switch (Called->getIntrinsicID()) {
206 case Intrinsic::smin:
207 case Intrinsic::umin:
208 case Intrinsic::smax:
209 case Intrinsic::umax:
226 if (
Info.SExt->getType() == V->getType())
228 return Builder.CreateSExt(V,
Info.SExt->getType());
231 if (
Info.ZExt->getType() == V->getType())
233 return Builder.CreateZExt(V,
Info.ZExt->getType());
238 bool Changed =
false;
258 bool SecondMinMax = IsMinMaxCall(ICmp->
getOperand(1), Second);
259 if (!(FirstMinMax ^ SecondMinMax))
266 for (
auto &
Info : SinkList) {
271 if (ICmpInst::isSigned(
P) && IID != Intrinsic::smin &&
272 IID != Intrinsic::smax)
279 bool IsMin = IID == Intrinsic::smin || IID == Intrinsic::umin;
280 bool IsMax = IID == Intrinsic::smax || IID == Intrinsic::umax;
284 assert(IsLess ^ IsGreater);
289 if ((IsLess && IsMin) || (IsGreater && IsMax))
302 if (
I &&
I->use_empty())
303 I->eraseFromParent();
338bool BPFCheckAndAdjustIR::sinkMinMax(
Module &M) {
339 bool Changed =
false;
342 if (
F.isDeclaration())
345 LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>(
F).getLoopInfo();
349 Loop *BBLoop = LI.getLoopFor(BB);
351 return LI.getLoopFor(
I->getParent()) != BBLoop;
360void BPFCheckAndAdjustIR::getAnalysisUsage(
AnalysisUsage &AU)
const {
364bool BPFCheckAndAdjustIR::adjustIR(
Module &M) {
365 bool Changed = removePassThroughBuiltin(M);
366 Changed = removeCompareBuiltin(M) || Changed;
367 Changed = sinkMinMax(M) || Changed;
371bool BPFCheckAndAdjustIR::runOnModule(
Module &M) {
ReachingDefAnalysis InstSet & ToRemove
static bool sinkMinMaxInBB(BasicBlock &BB, const std::function< bool(Instruction *)> &Filter)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
LLVM Basic Block Representation.
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Predicate getPredicate() const
Return the predicate for this instruction.
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...
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
This class represents a sign extension of integer types.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Value * getOperand(unsigned i) const
LLVM Value Representation.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
This class represents zero extension of integer types.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
ModulePass * createBPFCheckAndAdjustIR()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
ICmpInst::Predicate Predicate
MinMaxSinkInfo(ICmpInst *ICmp, Value *Other, ICmpInst::Predicate Predicate)