93 lines · cpp
1//===-- BPFASpaceCastSimplifyPass.cpp - BPF addrspacecast simplications --===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "BPF.h"10#include <optional>11 12#define DEBUG_TYPE "bpf-aspace-simplify"13 14using namespace llvm;15 16namespace {17 18struct CastGEPCast {19 AddrSpaceCastInst *OuterCast;20 21 // Match chain of instructions:22 // %inner = addrspacecast N->M23 // %gep = getelementptr %inner, ...24 // %outer = addrspacecast M->N %gep25 // Where I is %outer.26 static std::optional<CastGEPCast> match(Value *I) {27 auto *OuterCast = dyn_cast<AddrSpaceCastInst>(I);28 if (!OuterCast)29 return std::nullopt;30 auto *GEP = dyn_cast<GetElementPtrInst>(OuterCast->getPointerOperand());31 if (!GEP)32 return std::nullopt;33 auto *InnerCast = dyn_cast<AddrSpaceCastInst>(GEP->getPointerOperand());34 if (!InnerCast)35 return std::nullopt;36 if (InnerCast->getSrcAddressSpace() != OuterCast->getDestAddressSpace())37 return std::nullopt;38 if (InnerCast->getDestAddressSpace() != OuterCast->getSrcAddressSpace())39 return std::nullopt;40 return CastGEPCast{OuterCast};41 }42 43 static PointerType *changeAddressSpace(PointerType *Ty, unsigned AS) {44 return Ty->get(Ty->getContext(), AS);45 }46 47 // Assuming match(this->OuterCast) is true, convert:48 // (addrspacecast M->N (getelementptr (addrspacecast N->M ptr) ...))49 // To:50 // (getelementptr ptr ...)51 GetElementPtrInst *rewrite() {52 auto *GEP = cast<GetElementPtrInst>(OuterCast->getPointerOperand());53 auto *InnerCast = cast<AddrSpaceCastInst>(GEP->getPointerOperand());54 unsigned AS = OuterCast->getDestAddressSpace();55 auto *NewGEP = cast<GetElementPtrInst>(GEP->clone());56 NewGEP->setName(GEP->getName());57 NewGEP->insertAfter(OuterCast->getIterator());58 NewGEP->setOperand(0, InnerCast->getPointerOperand());59 auto *GEPTy = cast<PointerType>(GEP->getType());60 NewGEP->mutateType(changeAddressSpace(GEPTy, AS));61 OuterCast->replaceAllUsesWith(NewGEP);62 OuterCast->eraseFromParent();63 if (GEP->use_empty())64 GEP->eraseFromParent();65 if (InnerCast->use_empty())66 InnerCast->eraseFromParent();67 return NewGEP;68 }69};70 71} // anonymous namespace72 73PreservedAnalyses BPFASpaceCastSimplifyPass::run(Function &F,74 FunctionAnalysisManager &AM) {75 SmallVector<CastGEPCast, 16> WorkList;76 bool Changed = false;77 for (BasicBlock &BB : F) {78 for (Instruction &I : BB)79 if (auto It = CastGEPCast::match(&I))80 WorkList.push_back(It.value());81 Changed |= !WorkList.empty();82 83 while (!WorkList.empty()) {84 CastGEPCast InsnChain = WorkList.pop_back_val();85 GetElementPtrInst *NewGEP = InsnChain.rewrite();86 for (User *U : NewGEP->users())87 if (auto It = CastGEPCast::match(U))88 WorkList.push_back(It.value());89 }90 }91 return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();92}93