brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · d70b87d Raw
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