[clang] [llvm] [BPF] add cast_{user,kern} instructions (PR #79902)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 13 12:28:02 PST 2024
================
@@ -416,11 +419,124 @@ bool BPFCheckAndAdjustIR::removeGEPBuiltins(Module &M) {
return Changed;
}
+// Wrap ToWrap with cast to address space zero:
+// - if ToWrap is a getelementptr,
+// wrap it's base pointer instead and return a copy;
+// - if ToWrap is Instruction, insert address space cast
+// immediately after ToWrap;
+// - if ToWrap is not an Instruction (function parameter
+// or a global value), insert address space cast at the
+// beginning of the Function F;
+// - use Cache to avoid inserting too many casts;
+static Value *aspaceWrapValue(DenseMap<Value *, Value *> &Cache, Function *F,
+ Value *ToWrap) {
+ auto It = Cache.find(ToWrap);
+ if (It != Cache.end())
+ return It->getSecond();
+
+ if (auto *GEP = dyn_cast<GetElementPtrInst>(ToWrap)) {
+ Value *Ptr = GEP->getPointerOperand();
+ Value *WrappedPtr = aspaceWrapValue(Cache, F, Ptr);
+ auto *GEPTy = cast<PointerType>(GEP->getType());
+ auto *NewGEP = GEP->clone();
+ NewGEP->insertAfter(GEP);
+ NewGEP->mutateType(GEPTy->getPointerTo(0));
+ NewGEP->setOperand(GEP->getPointerOperandIndex(), WrappedPtr);
+ NewGEP->setName(GEP->getName());
+ Cache[ToWrap] = NewGEP;
+ return NewGEP;
+ }
+
+ IRBuilder IB(F->getContext());
+ if (Instruction *InsnPtr = dyn_cast<Instruction>(ToWrap))
+ IB.SetInsertPoint(*InsnPtr->getInsertionPointAfterDef());
+ else
+ IB.SetInsertPoint(F->getEntryBlock().getFirstInsertionPt());
+ auto *PtrTy = cast<PointerType>(ToWrap->getType());
+ auto *ASZeroPtrTy = PtrTy->getPointerTo(0);
+ auto *ACast = IB.CreateAddrSpaceCast(ToWrap, ASZeroPtrTy, ToWrap->getName());
+ Cache[ToWrap] = ACast;
+ return ACast;
+}
+
+// Wrap a pointer operand OpNum of instruction I
+// with cast to address space zero
+static void aspaceWrapOperand(DenseMap<Value *, Value *> &Cache, Instruction *I,
+ unsigned OpNum) {
+ Value *OldOp = I->getOperand(OpNum);
+ if (OldOp->getType()->getPointerAddressSpace() == 0)
+ return;
+
+ Value *NewOp = aspaceWrapValue(Cache, I->getFunction(), OldOp);
+ I->setOperand(OpNum, NewOp);
+ // Check if there are any remaining users of old GEP,
+ // delete those w/o users
+ for (;;) {
+ auto *OldGEP = dyn_cast<GetElementPtrInst>(OldOp);
+ if (!OldGEP)
+ break;
+ if (!OldGEP->use_empty())
+ break;
+ OldOp = OldGEP->getPointerOperand();
+ OldGEP->eraseFromParent();
+ }
+}
+
+// Support for BPF arenas:
+// - for each function in the module M, update pointer operand of
+// each memory access instruction (load/store/cmpxchg/atomicrmw)
+// by casting it from non-zero address space to zero address space, e.g:
+//
+// (load (ptr addrspace (N) %p) ...)
+// -> (load (addrspacecast ptr addrspace (N) %p to ptr))
+//
+// - assign section with name .arena.N for globals defined in
+// non-zero address space N
+bool BPFCheckAndAdjustIR::insertASpaceCasts(Module &M) {
+ bool Changed = false;
+ for (Function &F : M) {
+ DenseMap<Value *, Value *> CastsCache;
----------------
4ast wrote:
Overall looks great. This Cache of ACast is per function. Is it correct to reuse that operand out of every BB ? It won't break 'volatile' pointer derefs ?
https://github.com/llvm/llvm-project/pull/79902
More information about the cfe-commits
mailing list