brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.8 KiB · b1a8d1a Raw
87 lines · cpp
1//===-- SPIRVStripConvergentIntrinsics.cpp ----------------------*- C++ -*-===//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// This pass trims convergence intrinsics as those were only useful when10// modifying the CFG during IR passes.11//12//===----------------------------------------------------------------------===//13 14#include "SPIRV.h"15#include "SPIRVSubtarget.h"16#include "SPIRVUtils.h"17#include "llvm/IR/IntrinsicInst.h"18#include "llvm/IR/Intrinsics.h"19#include "llvm/Transforms/Utils/Cloning.h"20#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"21 22using namespace llvm;23 24namespace {25class SPIRVStripConvergentIntrinsics : public FunctionPass {26public:27  static char ID;28 29  SPIRVStripConvergentIntrinsics() : FunctionPass(ID) {}30 31  bool runOnFunction(Function &F) override {32    DenseSet<Instruction *> ToRemove;33 34    // Is the instruction is a convergent intrinsic, add it to kill-list and35    // returns true. Returns false otherwise.36    auto CleanupIntrinsic = [&](IntrinsicInst *II) {37      if (II->getIntrinsicID() != Intrinsic::experimental_convergence_entry &&38          II->getIntrinsicID() != Intrinsic::experimental_convergence_loop &&39          II->getIntrinsicID() != Intrinsic::experimental_convergence_anchor)40        return false;41 42      II->replaceAllUsesWith(UndefValue::get(II->getType()));43      ToRemove.insert(II);44      return true;45    };46 47    // Replace the given CallInst by a similar CallInst with no convergencectrl48    // attribute.49    auto CleanupCall = [&](CallInst *CI) {50      auto OB = CI->getOperandBundle(LLVMContext::OB_convergencectrl);51      if (!OB.has_value())52        return;53 54      auto *NewCall = CallBase::removeOperandBundle(55          CI, LLVMContext::OB_convergencectrl, CI->getIterator());56      NewCall->copyMetadata(*CI);57      CI->replaceAllUsesWith(NewCall);58      ToRemove.insert(CI);59    };60 61    for (BasicBlock &BB : F) {62      for (Instruction &I : BB) {63        if (auto *II = dyn_cast<IntrinsicInst>(&I))64          if (CleanupIntrinsic(II))65            continue;66        if (auto *CI = dyn_cast<CallInst>(&I))67          CleanupCall(CI);68      }69    }70 71    // All usages must be removed before their definition is removed.72    for (Instruction *I : ToRemove)73      I->eraseFromParent();74 75    return ToRemove.size() != 0;76  }77};78} // namespace79 80char SPIRVStripConvergentIntrinsics::ID = 0;81INITIALIZE_PASS(SPIRVStripConvergentIntrinsics, "strip-convergent-intrinsics",82                "SPIRV strip convergent intrinsics", false, false)83 84FunctionPass *llvm::createSPIRVStripConvergenceIntrinsicsPass() {85  return new SPIRVStripConvergentIntrinsics();86}87