//===- IslAst.h - Interface to the isl code generator -----------*- 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 isl code generator interface takes a Scop and generates a isl_ast. This
 
// ist_ast can either be returned directly or it can be pretty printed to
 
// stdout.
 
//
 
// A typical isl_ast output looks like this:
 
//
 
// for (c2 = max(0, ceild(n + m, 2); c2 <= min(511, floord(5 * n, 3)); c2++) {
 
//   bb2(c2);
 
// }
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef POLLY_ISLAST_H
 
#define POLLY_ISLAST_H
 
 
 
#include "polly/ScopPass.h"
 
#include "llvm/ADT/SmallPtrSet.h"
 
#include "llvm/IR/PassManager.h"
 
#include "isl/ctx.h"
 
 
 
namespace polly {
 
using llvm::SmallPtrSet;
 
 
 
class Dependences;
 
 
 
class IslAst final {
 
public:
 
  IslAst(const IslAst &) = delete;
 
  IslAst &operator=(const IslAst &) = delete;
 
  IslAst(IslAst &&);
 
  IslAst &operator=(IslAst &&) = delete;
 
 
 
  static IslAst create(Scop &Scop, const Dependences &D);
 
 
 
  isl::ast_node getAst();
 
 
 
  const std::shared_ptr<isl_ctx> getSharedIslCtx() const { return Ctx; }
 
 
 
  /// Get the run-time conditions for the Scop.
 
  isl::ast_expr getRunCondition();
 
 
 
  /// Build run-time condition for scop.
 
  ///
 
  /// @param S     The scop to build the condition for.
 
  /// @param Build The isl_build object to use to build the condition.
 
  ///
 
  /// @returns An ast expression that describes the necessary run-time check.
 
  static isl::ast_expr buildRunCondition(Scop &S, const isl::ast_build &Build);
 
 
 
private:
 
  Scop &S;
 
  std::shared_ptr<isl_ctx> Ctx;
 
  isl::ast_expr RunCondition;
 
  isl::ast_node Root;
 
 
 
  IslAst(Scop &Scop);
 
 
 
  void init(const Dependences &D);
 
};
 
 
 
class IslAstInfo {
 
public:
 
  using MemoryAccessSet = SmallPtrSet<MemoryAccess *, 4>;
 
 
 
  /// Payload information used to annotate an AST node.
 
  struct IslAstUserPayload {
 
    /// Construct and initialize the payload.
 
    IslAstUserPayload() = default;
 
 
 
    /// Does the dependence analysis determine that there are no loop-carried
 
    /// dependencies?
 
    bool IsParallel = false;
 
 
 
    /// Flag to mark innermost loops.
 
    bool IsInnermost = false;
 
 
 
    /// Flag to mark innermost parallel loops.
 
    bool IsInnermostParallel = false;
 
 
 
    /// Flag to mark outermost parallel loops.
 
    bool IsOutermostParallel = false;
 
 
 
    /// Flag to mark parallel loops which break reductions.
 
    bool IsReductionParallel = false;
 
 
 
    /// The minimal dependence distance for non parallel loops.
 
    isl::pw_aff MinimalDependenceDistance;
 
 
 
    /// The build environment at the time this node was constructed.
 
    isl::ast_build Build;
 
 
 
    /// Set of accesses which break reduction dependences.
 
    MemoryAccessSet BrokenReductions;
 
  };
 
 
 
private:
 
  Scop &S;
 
  IslAst Ast;
 
 
 
public:
 
  IslAstInfo(Scop &S, const Dependences &D) : S(S), Ast(IslAst::create(S, D)) {}
 
 
 
  /// Return the isl AST computed by this IslAstInfo.
 
  IslAst &getIslAst() { return Ast; }
 
 
 
  /// Return a copy of the AST root node.
 
  isl::ast_node getAst();
 
 
 
  /// Get the run condition.
 
  ///
 
  /// Only if the run condition evaluates at run-time to a non-zero value, the
 
  /// assumptions that have been taken hold. If the run condition evaluates to
 
  /// zero/false some assumptions do not hold and the original code needs to
 
  /// be executed.
 
  isl::ast_expr getRunCondition();
 
 
 
  void print(raw_ostream &O);
 
 
 
  /// @name Extract information attached to an isl ast (for) node.
 
  ///
 
  ///{
 
  /// Get the complete payload attached to @p Node.
 
  static IslAstUserPayload *getNodePayload(const isl::ast_node &Node);
 
 
 
  /// Is this loop an innermost loop?
 
  static bool isInnermost(const isl::ast_node &Node);
 
 
 
  /// Is this loop a parallel loop?
 
  static bool isParallel(const isl::ast_node &Node);
 
 
 
  /// Is this loop an outermost parallel loop?
 
  static bool isOutermostParallel(const isl::ast_node &Node);
 
 
 
  /// Is this loop an innermost parallel loop?
 
  static bool isInnermostParallel(const isl::ast_node &Node);
 
 
 
  /// Is this loop a reduction parallel loop?
 
  static bool isReductionParallel(const isl::ast_node &Node);
 
 
 
  /// Will the loop be run as thread parallel?
 
  static bool isExecutedInParallel(const isl::ast_node &Node);
 
 
 
  /// Get the nodes schedule or a nullptr if not available.
 
  static isl::union_map getSchedule(const isl::ast_node &Node);
 
 
 
  /// Get minimal dependence distance or nullptr if not available.
 
  static isl::pw_aff getMinimalDependenceDistance(const isl::ast_node &Node);
 
 
 
  /// Get the nodes broken reductions or a nullptr if not available.
 
  static MemoryAccessSet *getBrokenReductions(const isl::ast_node &Node);
 
 
 
  /// Get the nodes build context or a nullptr if not available.
 
  static isl::ast_build getBuild(const isl::ast_node &Node);
 
 
 
  ///}
 
};
 
 
 
struct IslAstAnalysis : AnalysisInfoMixin<IslAstAnalysis> {
 
  static AnalysisKey Key;
 
 
 
  using Result = IslAstInfo;
 
 
 
  IslAstInfo run(Scop &S, ScopAnalysisManager &SAM,
 
                 ScopStandardAnalysisResults &SAR);
 
};
 
 
 
class IslAstInfoWrapperPass final : public ScopPass {
 
  std::unique_ptr<IslAstInfo> Ast;
 
 
 
public:
 
  static char ID;
 
 
 
  IslAstInfoWrapperPass() : ScopPass(ID) {}
 
 
 
  IslAstInfo &getAI() { return *Ast; }
 
  const IslAstInfo &getAI() const { return *Ast; }
 
 
 
  /// Build the AST for the given SCoP @p S.
 
  bool runOnScop(Scop &S) override;
 
 
 
  /// Register all analyses and transformation required.
 
  void getAnalysisUsage(AnalysisUsage &AU) const override;
 
 
 
  /// Release the internal memory.
 
  void releaseMemory() override;
 
 
 
  /// Print a source code representation of the program.
 
  void printScop(raw_ostream &OS, Scop &S) const override;
 
};
 
 
 
llvm::Pass *createIslAstInfoWrapperPassPass();
 
llvm::Pass *createIslAstInfoPrinterLegacyPass(llvm::raw_ostream &OS);
 
 
 
struct IslAstPrinterPass final : PassInfoMixin<IslAstPrinterPass> {
 
  IslAstPrinterPass(raw_ostream &OS) : OS(OS) {}
 
 
 
  PreservedAnalyses run(Scop &S, ScopAnalysisManager &SAM,
 
                        ScopStandardAnalysisResults &, SPMUpdater &U);
 
 
 
  raw_ostream &OS;
 
};
 
} // namespace polly
 
 
 
namespace llvm {
 
void initializeIslAstInfoWrapperPassPass(llvm::PassRegistry &);
 
void initializeIslAstInfoPrinterLegacyPassPass(llvm::PassRegistry &);
 
} // namespace llvm
 
 
 
#endif // POLLY_ISLAST_H