//===- Codegen/IRBuilder.h - The IR builder used by Polly -*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
// The Polly IRBuilder file contains Polly specific extensions for the IRBuilder
 
// that are used e.g. to emit the llvm.loop.parallel metadata.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef POLLY_CODEGEN_IRBUILDER_H
 
#define POLLY_CODEGEN_IRBUILDER_H
 
 
 
#include "llvm/ADT/MapVector.h"
 
#include "llvm/IR/IRBuilder.h"
 
 
 
namespace llvm {
 
class Loop;
 
class SCEV;
 
class ScalarEvolution;
 
} // namespace llvm
 
 
 
namespace polly {
 
class Scop;
 
struct BandAttr;
 
 
 
/// Helper class to annotate newly generated SCoPs with metadata.
 
///
 
/// The annotations are twofold:
 
///   1) Loops are stored in a stack-like structure in the order they are
 
///      constructed and the LoopID metadata node is added to the backedge.
 
///      Contained memory instructions and loop headers are annotated according
 
///      to all parallel surrounding loops.
 
///   2) The new SCoP is assumed alias free (either due to the result of
 
///      AliasAnalysis queries or runtime alias checks). We annotate therefore
 
///      all memory instruction with alias scopes to indicate that fact to
 
///      later optimizations.
 
///      These alias scopes live in a new alias domain only used in this SCoP.
 
///      Each base pointer has its own alias scope and is annotated to not
 
///      alias with any access to different base pointers.
 
class ScopAnnotator {
 
public:
 
  ScopAnnotator();
 
  ~ScopAnnotator();
 
 
 
  /// Build all alias scopes for the given SCoP.
 
  void buildAliasScopes(Scop &S);
 
 
 
  /// Add a new loop @p L which is parallel if @p IsParallel is true.
 
  void pushLoop(llvm::Loop *L, bool IsParallel);
 
 
 
  /// Remove the last added loop.
 
  void popLoop(bool isParallel);
 
 
 
  /// Annotate the new instruction @p I for all parallel loops.
 
  void annotate(llvm::Instruction *I);
 
 
 
  /// Annotate the loop latch @p B wrt. @p L.
 
  void annotateLoopLatch(llvm::BranchInst *B, llvm::Loop *L, bool IsParallel,
 
                         bool IsLoopVectorizerDisabled) const;
 
 
 
  /// Add alternative alias based pointers
 
  ///
 
  /// When annotating instructions with alias scope metadata, the right metadata
 
  /// is identified through the base pointer of the memory access. In some cases
 
  /// (e.g. OpenMP code generation), the base pointer of the memory accesses is
 
  /// not the original base pointer, but was changed when passing the original
 
  /// base pointer over a function boundary. This function allows to provide a
 
  /// map that maps from these new base pointers to the original base pointers
 
  /// to allow the ScopAnnotator to still find the right alias scop annotations.
 
  ///
 
  /// @param NewMap A map from new base pointers to original base pointers.
 
  void addAlternativeAliasBases(
 
      llvm::DenseMap<llvm::AssertingVH<llvm::Value>,
 
                     llvm::AssertingVH<llvm::Value>> &NewMap) {
 
    AlternativeAliasBases.insert(NewMap.begin(), NewMap.end());
 
  }
 
 
 
  /// Delete the set of alternative alias bases
 
  void resetAlternativeAliasBases() { AlternativeAliasBases.clear(); }
 
 
 
  /// Stack for surrounding BandAttr annotations.
 
  llvm::SmallVector<BandAttr *, 8> LoopAttrEnv;
 
  BandAttr *&getStagingAttrEnv() { return LoopAttrEnv.back(); }
 
  BandAttr *getActiveAttrEnv() const {
 
    return LoopAttrEnv[LoopAttrEnv.size() - 2];
 
  }
 
 
 
private:
 
  /// The ScalarEvolution analysis we use to find base pointers.
 
  llvm::ScalarEvolution *SE;
 
 
 
  /// All loops currently under construction.
 
  llvm::SmallVector<llvm::Loop *, 8> ActiveLoops;
 
 
 
  /// Access groups for the parallel loops currently under construction.
 
  llvm::SmallVector<llvm::MDNode *, 8> ParallelLoops;
 
 
 
  /// The alias scope domain for the current SCoP.
 
  llvm::MDNode *AliasScopeDomain;
 
 
 
  /// A map from base pointers to its alias scope.
 
  llvm::MapVector<llvm::AssertingVH<llvm::Value>, llvm::MDNode *> AliasScopeMap;
 
 
 
  /// A map from base pointers to an alias scope list of other pointers.
 
  llvm::DenseMap<llvm::AssertingVH<llvm::Value>, llvm::MDNode *>
 
      OtherAliasScopeListMap;
 
 
 
  llvm::DenseMap<llvm::AssertingVH<llvm::Value>, llvm::AssertingVH<llvm::Value>>
 
      AlternativeAliasBases;
 
};
 
 
 
/// Add Polly specifics when running IRBuilder.
 
///
 
/// This is used to add additional items such as e.g. the llvm.loop.parallel
 
/// metadata.
 
class IRInserter final : public llvm::IRBuilderDefaultInserter {
 
public:
 
  IRInserter() = default;
 
  IRInserter(ScopAnnotator &A) : Annotator(&A) {}
 
 
 
  void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
 
                    llvm::BasicBlock *BB,
 
                    llvm::BasicBlock::iterator InsertPt) const override {
 
    llvm::IRBuilderDefaultInserter::InsertHelper(I, Name, BB, InsertPt);
 
    if (Annotator)
 
      Annotator->annotate(I);
 
  }
 
 
 
private:
 
  ScopAnnotator *Annotator = nullptr;
 
};
 
 
 
// TODO: We should not name instructions in NDEBUG builds.
 
//
 
// We currently always name instructions, as the polly test suite currently
 
// matches for certain names.
 
typedef llvm::IRBuilder<llvm::ConstantFolder, IRInserter> PollyIRBuilder;
 
 
 
} // namespace polly
 
#endif