30#include "llvm/IR/IntrinsicsBPF.h" 
   37#define DEBUG_TYPE "bpf-check-and-opt-ir" 
   43class BPFCheckAndAdjustIR final : 
public ModulePass {
 
   44  bool runOnModule(
Module &
F) 
override;
 
   54  bool removePassThroughBuiltin(
Module &M);
 
   55  bool removeCompareBuiltin(
Module &M);
 
   56  bool sinkMinMax(
Module &M);
 
   57  bool removeGEPBuiltins(
Module &M);
 
   58  bool insertASpaceCasts(
Module &M);
 
   62char BPFCheckAndAdjustIR::ID = 0;
 
   67  return new BPFCheckAndAdjustIR();
 
 
   70void BPFCheckAndAdjustIR::checkIR(
Module &M) {
 
  103bool BPFCheckAndAdjustIR::removePassThroughBuiltin(
Module &M) {
 
  108  CallInst *ToBeDeleted = 
nullptr;
 
  109  for (Function &
F : M)
 
  114          ToBeDeleted = 
nullptr;
 
  123        if (!GV->getName().starts_with(
"llvm.bpf.passthrough"))
 
  133bool BPFCheckAndAdjustIR::removeCompareBuiltin(
Module &M) {
 
  138  CallInst *ToBeDeleted = 
nullptr;
 
  139  for (Function &
F : M)
 
  144          ToBeDeleted = 
nullptr;
 
  153        if (!GV->getName().starts_with(
"llvm.bpf.compare"))
 
  164        auto *ICmp = 
new ICmpInst(Opcode, Arg1, Arg2);
 
  195      V = ZExt->getOperand(0);
 
  198      V = SExt->getOperand(0);
 
  210    switch (Called->getIntrinsicID()) {
 
  211    case Intrinsic::smin:
 
  212    case Intrinsic::umin:
 
  213    case Intrinsic::smax:
 
  214    case Intrinsic::umax:
 
  231      if (
Info.SExt->getType() == V->getType())
 
  233      return Builder.CreateSExt(V, 
Info.SExt->getType());
 
  236      if (
Info.ZExt->getType() == V->getType())
 
  238      return Builder.CreateZExt(V, 
Info.ZExt->getType());
 
  263    bool SecondMinMax = IsMinMaxCall(ICmp->
getOperand(1), Second);
 
  264    if (!(FirstMinMax ^ SecondMinMax))
 
  271  for (
auto &
Info : SinkList) {
 
  277        IID != Intrinsic::smax)
 
  284    bool IsMin = IID == Intrinsic::smin || IID == Intrinsic::umin;
 
  285    bool IsMax = IID == Intrinsic::smax || IID == Intrinsic::umax;
 
  289    assert(IsLess ^ IsGreater);
 
  294    if ((IsLess && IsMin) || (IsGreater && IsMax))
 
  297      Replacement = Builder.CreateLogicalAnd(
LHS, 
RHS);
 
  301      Replacement = Builder.CreateLogicalOr(
LHS, 
RHS);
 
  307      if (
I && 
I->use_empty())
 
  308        I->eraseFromParent();
 
 
  343bool BPFCheckAndAdjustIR::sinkMinMax(
Module &M) {
 
  346  for (Function &
F : M) {
 
  347    if (
F.isDeclaration())
 
  350    LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>(
F).getLoopInfo();
 
  352      for (BasicBlock *BB : 
L->blocks()) {
 
  354        Loop *BBLoop = LI.getLoopFor(BB);
 
  356          return LI.getLoopFor(
I->getParent()) != BBLoop;
 
  365void BPFCheckAndAdjustIR::getAnalysisUsage(AnalysisUsage &AU)
 const {
 
  371  GEP->insertBefore(
Call->getIterator());
 
  372  Load->insertBefore(
Call->getIterator());
 
  373  Call->replaceAllUsesWith(Load);
 
  374  Call->eraseFromParent();
 
 
  379  GEP->insertBefore(
Call->getIterator());
 
  380  Store->insertBefore(
Call->getIterator());
 
  381  Call->eraseFromParent();
 
 
  388    for (
auto &Insn : BB)
 
  390        if (
auto *Called = 
Call->getCalledFunction())
 
  391          switch (Called->getIntrinsicID()) {
 
  392          case Intrinsic::bpf_getelementptr_and_load:
 
  395          case Intrinsic::bpf_getelementptr_and_store:
 
 
  413bool BPFCheckAndAdjustIR::removeGEPBuiltins(
Module &M) {
 
  431  auto It = Cache.find(ToWrap);
 
  432  if (It != Cache.end())
 
  433    return It->getSecond();
 
  439    auto *NewGEP = 
GEP->clone();
 
  440    NewGEP->insertAfter(
GEP->getIterator());
 
  442    NewGEP->setOperand(
GEP->getPointerOperandIndex(), WrappedPtr);
 
  443    NewGEP->setName(
GEP->getName());
 
  444    Cache[ToWrap] = NewGEP;
 
  450    IB.SetInsertPoint(*InsnPtr->getInsertionPointAfterDef());
 
  452    IB.SetInsertPoint(
F->getEntryBlock().getFirstInsertionPt());
 
  453  auto *ASZeroPtrTy = IB.getPtrTy(0);
 
  454  auto *ACast = IB.CreateAddrSpaceCast(ToWrap, ASZeroPtrTy, ToWrap->
getName());
 
  455  Cache[ToWrap] = ACast;
 
 
  463  Value *OldOp = 
I->getOperand(OpNum);
 
  468  I->setOperand(OpNum, NewOp);
 
  475    if (!OldGEP->use_empty())
 
  477    OldOp = OldGEP->getPointerOperand();
 
  478    OldGEP->eraseFromParent();
 
 
  485    if (PTy->getAddressSpace() == 0)
 
 
  499  if (OldDst == NewDst)
 
  508  bool IsVolatile = MS->isVolatile();
 
  510  if (
ID == Intrinsic::memset)
 
  511    return B.CreateMemSet(NewDst, Val, Len, 
Align, IsVolatile,
 
  512                          MI->getAAMetadata());
 
  514    return B.CreateMemSetInline(NewDst, 
Align, Val, Len, IsVolatile,
 
  515                                MI->getAAMetadata());
 
 
  528  if (OldDst == NewDst && OldSrc == NewSrc)
 
  537  bool IsVolatile = MT->isVolatile();
 
  539  return B.CreateMemTransferInst(
ID, NewDst, DstAlign, NewSrc, SrcAlign, Len,
 
  540                                 IsVolatile, 
MI->getAAMetadata());
 
 
  552  if (OldDst == NewDst && OldSrc == NewSrc)
 
  561  bool IsVolatile = MT->isVolatile();
 
  563  return B.CreateMemMove(NewDst, DstAlign, NewSrc, SrcAlign, Len, IsVolatile,
 
  564                         MI->getAAMetadata());
 
 
  578bool BPFCheckAndAdjustIR::insertASpaceCasts(
Module &M) {
 
  580  for (Function &
F : M) {
 
  581    DenseMap<Value *, Value *> CastsCache;
 
  582    for (BasicBlock &BB : 
F) {
 
  587          PtrOpNum = 
LD->getPointerOperandIndex();
 
  592          PtrOpNum = 
ST->getPointerOperandIndex();
 
  597          PtrOpNum = CmpXchg->getPointerOperandIndex();
 
  602          PtrOpNum = RMW->getPointerOperandIndex();
 
  612        if (!Callee || !
Callee->isIntrinsic())
 
  617        bool IsSet = 
ID == Intrinsic::memset || 
ID == Intrinsic::memset_inline;
 
  618        bool IsCpy = 
ID == Intrinsic::memcpy || 
ID == Intrinsic::memcpy_inline;
 
  619        bool IsMove = 
ID == Intrinsic::memmove;
 
  620        if (!IsSet && !IsCpy && !IsMove)
 
  634        I.replaceAllUsesWith(New);
 
  643  for (GlobalVariable &
G : 
M.globals()) {
 
  644    if (
G.getAddressSpace() == 0 || 
G.hasSection())
 
  646    SmallString<16> SecName;
 
  647    raw_svector_ostream OS(SecName);
 
  648    OS << 
".addr_space." << 
G.getAddressSpace();
 
  649    G.setSection(SecName);
 
  651    G.setConstant(
false);
 
  656bool BPFCheckAndAdjustIR::adjustIR(
Module &M) {
 
  657  bool Changed = removePassThroughBuiltin(M);
 
  665bool BPFCheckAndAdjustIR::runOnModule(
Module &M) {
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
 
ReachingDefInfo InstSet & ToRemove
 
static Instruction * aspaceMemSet(Intrinsic::ID ID, DenseMap< Value *, Value * > &Cache, CallInst *CI)
 
static Instruction * aspaceMemCpy(Intrinsic::ID ID, DenseMap< Value *, Value * > &Cache, CallInst *CI)
 
static Instruction * aspaceMemMove(DenseMap< Value *, Value * > &Cache, CallInst *CI)
 
static bool sinkMinMaxInBB(BasicBlock &BB, const std::function< bool(Instruction *)> &Filter)
 
static Value * wrapPtrIfASNotZero(DenseMap< Value *, Value * > &Cache, CallInst *CI, Value *P)
 
static void aspaceWrapOperand(DenseMap< Value *, Value * > &Cache, Instruction *I, unsigned OpNum)
 
static void unrollGEPStore(CallInst *Call)
 
static Value * aspaceWrapValue(DenseMap< Value *, Value * > &Cache, Function *F, Value *ToWrap)
 
static void unrollGEPLoad(CallInst *Call)
 
static bool removeGEPBuiltinsInFunc(Function &F)
 
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
 
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
 
Analysis containing CSE Info
 
Module.h This file contains the declarations for the Module class.
 
Machine Check Debug Module
 
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
 
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
 
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.
 
static std::pair< GetElementPtrInst *, StoreInst * > reconstructStore(CallInst *Call)
 
static std::pair< GetElementPtrInst *, LoadInst * > reconstructLoad(CallInst *Call)
 
LLVM Basic Block Representation.
 
Value * getCalledOperand() const
 
Value * getArgOperand(unsigned i) const
 
This class represents a function call, abstracting a target machine's calling convention.
 
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
 
Predicate getSwappedPredicate() const
For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.
 
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...
 
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
 
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
 
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
 
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.
 
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
 
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.
 
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
 
Value * getOperand(unsigned i) const
 
LLVM Value Representation.
 
Type * getType() const
All values are typed, get the type of this value.
 
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
 
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
 
This class represents zero extension of integer types.
 
self_iterator getIterator()
 
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
 
friend class Instruction
Iterator for Instructions in a `BasicBlock.
 
This is an optimization pass for GlobalISel generic memory operations.
 
FunctionAddr VTableAddr Value
 
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
 
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
 
ModulePass * createBPFCheckAndAdjustIR()
 
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
 
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
 
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
 
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
 
ICmpInst::Predicate Predicate
 
MinMaxSinkInfo(ICmpInst *ICmp, Value *Other, ICmpInst::Predicate Predicate)
 
This struct is a compact representation of a valid (non-zero power of two) alignment.
 
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.