brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · 81efca9 Raw
144 lines · cpp
1//===- CoroCleanup.cpp - Coroutine Cleanup Pass ---------------------------===//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 "llvm/Transforms/Coroutines/CoroCleanup.h"10#include "CoroInternal.h"11#include "llvm/IR/Function.h"12#include "llvm/IR/IRBuilder.h"13#include "llvm/IR/InstIterator.h"14#include "llvm/IR/Module.h"15#include "llvm/IR/PassManager.h"16#include "llvm/Transforms/Scalar/SimplifyCFG.h"17 18using namespace llvm;19 20#define DEBUG_TYPE "coro-cleanup"21 22namespace {23// Created on demand if CoroCleanup pass has work to do.24struct Lowerer : coro::LowererBase {25  IRBuilder<> Builder;26  Lowerer(Module &M) : LowererBase(M), Builder(Context) {}27  bool lower(Function &F);28};29}30 31static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) {32  Builder.SetInsertPoint(SubFn);33  Value *FramePtr = SubFn->getFrame();34  int Index = SubFn->getIndex();35 36  auto *FrameTy = StructType::get(SubFn->getContext(),37                                  {Builder.getPtrTy(), Builder.getPtrTy()});38 39  Builder.SetInsertPoint(SubFn);40  auto *Gep = Builder.CreateConstInBoundsGEP2_32(FrameTy, FramePtr, 0, Index);41  auto *Load = Builder.CreateLoad(FrameTy->getElementType(Index), Gep);42 43  SubFn->replaceAllUsesWith(Load);44}45 46bool Lowerer::lower(Function &F) {47  bool IsPrivateAndUnprocessed = F.isPresplitCoroutine() && F.hasLocalLinkage();48  bool Changed = false;49 50  for (Instruction &I : llvm::make_early_inc_range(instructions(F))) {51    if (auto *II = dyn_cast<IntrinsicInst>(&I)) {52      switch (II->getIntrinsicID()) {53      default:54        continue;55      case Intrinsic::coro_begin:56      case Intrinsic::coro_begin_custom_abi:57        II->replaceAllUsesWith(II->getArgOperand(1));58        break;59      case Intrinsic::coro_free:60        II->replaceAllUsesWith(II->getArgOperand(1));61        break;62      case Intrinsic::coro_alloc:63        II->replaceAllUsesWith(ConstantInt::getTrue(Context));64        break;65      case Intrinsic::coro_async_resume:66        II->replaceAllUsesWith(67            ConstantPointerNull::get(cast<PointerType>(I.getType())));68        break;69      case Intrinsic::coro_id:70      case Intrinsic::coro_id_retcon:71      case Intrinsic::coro_id_retcon_once:72      case Intrinsic::coro_id_async:73        II->replaceAllUsesWith(ConstantTokenNone::get(Context));74        break;75      case Intrinsic::coro_subfn_addr:76        lowerSubFn(Builder, cast<CoroSubFnInst>(II));77        break;78      case Intrinsic::coro_suspend_retcon:79      case Intrinsic::coro_is_in_ramp:80        if (IsPrivateAndUnprocessed) {81          II->replaceAllUsesWith(PoisonValue::get(II->getType()));82        } else83          continue;84        break;85      case Intrinsic::coro_async_size_replace:86        auto *Target = cast<ConstantStruct>(87            cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts())88                ->getInitializer());89        auto *Source = cast<ConstantStruct>(90            cast<GlobalVariable>(II->getArgOperand(1)->stripPointerCasts())91                ->getInitializer());92        auto *TargetSize = Target->getOperand(1);93        auto *SourceSize = Source->getOperand(1);94        if (TargetSize->isElementWiseEqual(SourceSize)) {95          break;96        }97        auto *TargetRelativeFunOffset = Target->getOperand(0);98        auto *NewFuncPtrStruct = ConstantStruct::get(99            Target->getType(), TargetRelativeFunOffset, SourceSize);100        Target->replaceAllUsesWith(NewFuncPtrStruct);101        break;102      }103      II->eraseFromParent();104      Changed = true;105    }106  }107 108  return Changed;109}110 111static bool declaresCoroCleanupIntrinsics(const Module &M) {112  return coro::declaresIntrinsics(113      M, {Intrinsic::coro_alloc, Intrinsic::coro_begin,114          Intrinsic::coro_subfn_addr, Intrinsic::coro_free, Intrinsic::coro_id,115          Intrinsic::coro_id_retcon, Intrinsic::coro_id_async,116          Intrinsic::coro_id_retcon_once, Intrinsic::coro_async_size_replace,117          Intrinsic::coro_async_resume, Intrinsic::coro_begin_custom_abi});118}119 120PreservedAnalyses CoroCleanupPass::run(Module &M,121                                       ModuleAnalysisManager &MAM) {122  if (!declaresCoroCleanupIntrinsics(M))123    return PreservedAnalyses::all();124 125  FunctionAnalysisManager &FAM =126      MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();127 128  FunctionPassManager FPM;129  FPM.addPass(SimplifyCFGPass());130 131  PreservedAnalyses FuncPA;132  FuncPA.preserveSet<CFGAnalyses>();133 134  Lowerer L(M);135  for (auto &F : M) {136    if (L.lower(F)) {137      FAM.invalidate(F, FuncPA);138      FPM.run(F, FAM);139    }140  }141 142  return PreservedAnalyses::none();143}144