Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.h
35294 views
//===- SPIRVConvergenceRegionAnalysis.h ------------------------*- C++ -*--===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// The analysis determines the convergence region for each basic block of9// the module, and provides a tree-like structure describing the region10// hierarchy.11//12//===----------------------------------------------------------------------===//1314#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVCONVERGENCEREGIONANALYSIS_H15#define LLVM_LIB_TARGET_SPIRV_SPIRVCONVERGENCEREGIONANALYSIS_H1617#include "llvm/ADT/SmallPtrSet.h"18#include "llvm/Analysis/CFG.h"19#include "llvm/Analysis/LoopInfo.h"20#include "llvm/IR/Dominators.h"21#include "llvm/IR/IntrinsicInst.h"22#include <iostream>23#include <optional>24#include <unordered_set>2526namespace llvm {27class SPIRVSubtarget;28class MachineFunction;29class MachineModuleInfo;3031namespace SPIRV {3233// Returns the first convergence intrinsic found in |BB|, |nullopt| otherwise.34std::optional<IntrinsicInst *> getConvergenceToken(BasicBlock *BB);35std::optional<const IntrinsicInst *> getConvergenceToken(const BasicBlock *BB);3637// Describes a hierarchy of convergence regions.38// A convergence region defines a CFG for which the execution flow can diverge39// starting from the entry block, but should reconverge back before the end of40// the exit blocks.41class ConvergenceRegion {42DominatorTree &DT;43LoopInfo &LI;4445public:46// The parent region of this region, if any.47ConvergenceRegion *Parent = nullptr;48// The sub-regions contained in this region, if any.49SmallVector<ConvergenceRegion *> Children = {};50// The convergence instruction linked to this region, if any.51std::optional<IntrinsicInst *> ConvergenceToken = std::nullopt;52// The only block with a predecessor outside of this region.53BasicBlock *Entry = nullptr;54// All the blocks with an edge leaving this convergence region.55SmallPtrSet<BasicBlock *, 2> Exits = {};56// All the blocks that belongs to this region, including its subregions'.57SmallPtrSet<BasicBlock *, 8> Blocks = {};5859// Creates a single convergence region encapsulating the whole function |F|.60ConvergenceRegion(DominatorTree &DT, LoopInfo &LI, Function &F);6162// Creates a single convergence region defined by entry and exits nodes, a63// list of blocks, and possibly a convergence token.64ConvergenceRegion(DominatorTree &DT, LoopInfo &LI,65std::optional<IntrinsicInst *> ConvergenceToken,66BasicBlock *Entry, SmallPtrSet<BasicBlock *, 8> &&Blocks,67SmallPtrSet<BasicBlock *, 2> &&Exits);6869ConvergenceRegion(ConvergenceRegion &&CR)70: DT(CR.DT), LI(CR.LI), Parent(std::move(CR.Parent)),71Children(std::move(CR.Children)),72ConvergenceToken(std::move(CR.ConvergenceToken)),73Entry(std::move(CR.Entry)), Exits(std::move(CR.Exits)),74Blocks(std::move(CR.Blocks)) {}7576ConvergenceRegion(const ConvergenceRegion &other) = delete;7778// Returns true if the given basic block belongs to this region, or to one of79// its subregion.80bool contains(const BasicBlock *BB) const { return Blocks.count(BB) != 0; }8182void releaseMemory();8384// Write to the debug output this region's hierarchy.85// |IndentSize| defines the number of tabs to print before any new line.86void dump(const unsigned IndentSize = 0) const;87};8889// Holds a ConvergenceRegion hierarchy.90class ConvergenceRegionInfo {91// The convergence region this structure holds.92ConvergenceRegion *TopLevelRegion;9394public:95ConvergenceRegionInfo() : TopLevelRegion(nullptr) {}9697// Creates a new ConvergenceRegionInfo. Ownership of the TopLevelRegion is98// passed to this object.99ConvergenceRegionInfo(ConvergenceRegion *TopLevelRegion)100: TopLevelRegion(TopLevelRegion) {}101102~ConvergenceRegionInfo() { releaseMemory(); }103104ConvergenceRegionInfo(ConvergenceRegionInfo &&LHS)105: TopLevelRegion(LHS.TopLevelRegion) {106if (TopLevelRegion != LHS.TopLevelRegion) {107releaseMemory();108TopLevelRegion = LHS.TopLevelRegion;109}110LHS.TopLevelRegion = nullptr;111}112113ConvergenceRegionInfo &operator=(ConvergenceRegionInfo &&LHS) {114if (TopLevelRegion != LHS.TopLevelRegion) {115releaseMemory();116TopLevelRegion = LHS.TopLevelRegion;117}118LHS.TopLevelRegion = nullptr;119return *this;120}121122void releaseMemory() {123if (TopLevelRegion == nullptr)124return;125126TopLevelRegion->releaseMemory();127delete TopLevelRegion;128TopLevelRegion = nullptr;129}130131const ConvergenceRegion *getTopLevelRegion() const { return TopLevelRegion; }132};133134} // namespace SPIRV135136// Wrapper around the function above to use it with the legacy pass manager.137class SPIRVConvergenceRegionAnalysisWrapperPass : public FunctionPass {138SPIRV::ConvergenceRegionInfo CRI;139140public:141static char ID;142143SPIRVConvergenceRegionAnalysisWrapperPass();144145void getAnalysisUsage(AnalysisUsage &AU) const override {146AU.setPreservesAll();147AU.addRequired<LoopInfoWrapperPass>();148AU.addRequired<DominatorTreeWrapperPass>();149};150151bool runOnFunction(Function &F) override;152153SPIRV::ConvergenceRegionInfo &getRegionInfo() { return CRI; }154const SPIRV::ConvergenceRegionInfo &getRegionInfo() const { return CRI; }155};156157// Wrapper around the function above to use it with the new pass manager.158class SPIRVConvergenceRegionAnalysis159: public AnalysisInfoMixin<SPIRVConvergenceRegionAnalysis> {160friend AnalysisInfoMixin<SPIRVConvergenceRegionAnalysis>;161static AnalysisKey Key;162163public:164using Result = SPIRV::ConvergenceRegionInfo;165166Result run(Function &F, FunctionAnalysisManager &AM);167};168169namespace SPIRV {170ConvergenceRegionInfo getConvergenceRegions(Function &F, DominatorTree &DT,171LoopInfo &LI);172} // namespace SPIRV173174} // namespace llvm175#endif // LLVM_LIB_TARGET_SPIRV_SPIRVCONVERGENCEREGIONANALYSIS_H176177178