//===------ PPCGCodeGeneration.cpp - Polly Accelerator Code Generation. ---===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Take a scop created by ScopInfo and map it to GPU code using the ppcg
// GPU mapping strategy.
//
//===----------------------------------------------------------------------===//

#include "polly/CodeGen/PPCGCodeGeneration.h"
#include "polly/CodeGen/CodeGeneration.h"
#include "polly/CodeGen/IslAst.h"
#include "polly/CodeGen/IslNodeBuilder.h"
#include "polly/CodeGen/PerfMonitor.h"
#include "polly/CodeGen/Utils.h"
#include "polly/DependenceInfo.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
#include "polly/ScopDetection.h"
#include "polly/ScopInfo.h"
#include "polly/Support/SCEVValidator.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/IntrinsicsNVPTX.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/InitializePasses.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "isl/union_map.h"
#include <algorithm>

extern "C" {
#include "ppcg/cuda.h"
#include "ppcg/gpu.h"
#include "ppcg/ppcg.h"
}

#include "llvm/Support/Debug.h"

using namespace polly;
using namespace llvm;

#define DEBUG_TYPE "polly-codegen-ppcg"

static cl::opt<bool> DumpSchedule("polly-acc-dump-schedule",
                                  cl::desc("Dump the computed GPU Schedule"),
                                  cl::Hidden, cl::init(false), cl::ZeroOrMore,
                                  cl::cat(PollyCategory));

static cl::opt<bool>
    DumpCode("polly-acc-dump-code",
             cl::desc("Dump C code describing the GPU mapping"), cl::Hidden,
             cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));

static cl::opt<bool> DumpKernelIR("polly-acc-dump-kernel-ir",
                                  cl::desc("Dump the kernel LLVM-IR"),
                                  cl::Hidden, cl::init(false), cl::ZeroOrMore,
                                  cl::cat(PollyCategory));

static cl::opt<bool> DumpKernelASM("polly-acc-dump-kernel-asm",
                                   cl::desc("Dump the kernel assembly code"),
                                   cl::Hidden, cl::init(false), cl::ZeroOrMore,
                                   cl::cat(PollyCategory));

static cl::opt<bool> FastMath("polly-acc-fastmath",
                              cl::desc("Allow unsafe math optimizations"),
                              cl::Hidden, cl::init(false), cl::ZeroOrMore,
                              cl::cat(PollyCategory));
static cl::opt<bool> SharedMemory("polly-acc-use-shared",
                                  cl::desc("Use shared memory"), cl::Hidden,
                                  cl::init(false), cl::ZeroOrMore,
                                  cl::cat(PollyCategory));
static cl::opt<bool> PrivateMemory("polly-acc-use-private",
                                   cl::desc("Use private memory"), cl::Hidden,
                                   cl::init(false), cl::ZeroOrMore,
                                   cl::cat(PollyCategory));

bool polly::PollyManagedMemory;
static cl::opt<bool, true>
    XManagedMemory("polly-acc-codegen-managed-memory",
                   cl::desc("Generate Host kernel code assuming"
                            " that all memory has been"
                            " declared as managed memory"),
                   cl::location(PollyManagedMemory), cl::Hidden,
                   cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));

static cl::opt<bool>
    FailOnVerifyModuleFailure("polly-acc-fail-on-verify-module-failure",
                              cl::desc("Fail and generate a backtrace if"
                                       " verifyModule fails on the GPU "
                                       " kernel module."),
                              cl::Hidden, cl::init(false), cl::ZeroOrMore,
                              cl::cat(PollyCategory));

static cl::opt<std::string> CUDALibDevice(
    "polly-acc-libdevice", cl::desc("Path to CUDA libdevice"), cl::Hidden,
    cl::init("/usr/local/cuda/nvvm/libdevice/libdevice.compute_20.10.ll"),
    cl::ZeroOrMore, cl::cat(PollyCategory));

static cl::opt<std::string>
    CudaVersion("polly-acc-cuda-version",
                cl::desc("The CUDA version to compile for"), cl::Hidden,
                cl::init("sm_30"), cl::ZeroOrMore, cl::cat(PollyCategory));

static cl::opt<int>
    MinCompute("polly-acc-mincompute",
               cl::desc("Minimal number of compute statements to run on GPU."),
               cl::Hidden, cl::init(10 * 512 * 512));

GPURuntime polly::GPURuntimeChoice;
static cl::opt<GPURuntime, true> XGPURuntimeChoice(
    "polly-gpu-runtime", cl::desc("The GPU Runtime API to target"),
    cl::values(clEnumValN(GPURuntime::CUDA, "libcudart",
                          "use the CUDA Runtime API"),
               clEnumValN(GPURuntime::OpenCL, "libopencl",
                          "use the OpenCL Runtime API")),
    cl::location(polly::GPURuntimeChoice), cl::init(GPURuntime::CUDA),
    cl::ZeroOrMore, cl::cat(PollyCategory));

GPUArch polly::GPUArchChoice;
static cl::opt<GPUArch, true>
    XGPUArchChoice("polly-gpu-arch", cl::desc("The GPU Architecture to target"),
                   cl::values(clEnumValN(GPUArch::NVPTX64, "nvptx64",
                                         "target NVIDIA 64-bit architecture"),
                              clEnumValN(GPUArch::SPIR32, "spir32",
                                         "target SPIR 32-bit architecture"),
                              clEnumValN(GPUArch::SPIR64, "spir64",
                                         "target SPIR 64-bit architecture")),
                   cl::location(polly::GPUArchChoice),
                   cl::init(GPUArch::NVPTX64), cl::ZeroOrMore,
                   cl::cat(PollyCategory));

extern bool polly::PerfMonitoring;

/// Return  a unique name for a Scop, which is the scop region with the
/// function name.
std::string getUniqueScopName(const Scop *S) {
  return "Scop Region: " + S->getNameStr() +
         " | Function: " + std::string(S->getFunction().getName());
}

/// Used to store information PPCG wants for kills. This information is
/// used by live range reordering.
///
/// @see computeLiveRangeReordering
/// @see GPUNodeBuilder::createPPCGScop
/// @see GPUNodeBuilder::createPPCGProg
struct MustKillsInfo {
  /// Collection of all kill statements that will be sequenced at the end of
  /// PPCGScop->schedule.
  ///
  /// The nodes in `KillsSchedule` will be merged using `isl_schedule_set`
  /// which merges schedules in *arbitrary* order.
  /// (we don't care about the order of the kills anyway).
  isl::schedule KillsSchedule;
  /// Map from kill statement instances to scalars that need to be
  /// killed.
  ///
  /// We currently derive kill information for:
  ///  1. phi nodes. PHI nodes are not alive outside the scop and can
  ///     consequently all be killed.
  ///  2. Scalar arrays that are not used outside the Scop. This is
  ///     checked by `isScalarUsesContainedInScop`.
  /// [params] -> { [Stmt_phantom[] -> ref_phantom[]] -> scalar_to_kill[] }
  isl::union_map TaggedMustKills;

  /// Tagged must kills stripped of the tags.
  /// [params] -> { Stmt_phantom[]  -> scalar_to_kill[] }
  isl::union_map MustKills;

  MustKillsInfo() : KillsSchedule() {}
};

/// Check if SAI's uses are entirely contained within Scop S.
/// If a scalar is used only with a Scop, we are free to kill it, as no data
/// can flow in/out of the value any more.
/// @see computeMustKillsInfo
static bool isScalarUsesContainedInScop(const Scop &S,
                                        const ScopArrayInfo *SAI) {
  assert(SAI->isValueKind() && "this function only deals with scalars."
                               " Dealing with arrays required alias analysis");

  const Region &R = S.getRegion();
  for (User *U : SAI->getBasePtr()->users()) {
    Instruction *I = dyn_cast<Instruction>(U);
    assert(I && "invalid user of scop array info");
    if (!R.contains(I))
      return false;
  }
  return true;
}

/// Compute must-kills needed to enable live range reordering with PPCG.
///
/// @params S The Scop to compute live range reordering information
/// @returns live range reordering information that can be used to setup
/// PPCG.
static MustKillsInfo computeMustKillsInfo(const Scop &S) {
  const isl::space ParamSpace = S.getParamSpace();
  MustKillsInfo Info;

  // 1. Collect all ScopArrayInfo that satisfy *any* of the criteria:
  //      1.1 phi nodes in scop.
  //      1.2 scalars that are only used within the scop
  SmallVector<isl::id, 4> KillMemIds;
  for (ScopArrayInfo *SAI : S.arrays()) {
    if (SAI->isPHIKind() ||
        (SAI->isValueKind() && isScalarUsesContainedInScop(S, SAI)))
      KillMemIds.push_back(isl::manage(SAI->getBasePtrId().release()));
  }

  Info.TaggedMustKills = isl::union_map::empty(ParamSpace);
  Info.MustKills = isl::union_map::empty(ParamSpace);

  // Initialising KillsSchedule to `isl_set_empty` creates an empty node in the
  // schedule:
  //     - filter: "[control] -> { }"
  // So, we choose to not create this to keep the output a little nicer,
  // at the cost of some code complexity.
  Info.KillsSchedule = {};

  for (isl::id &ToKillId : KillMemIds) {
    isl::id KillStmtId = isl::id::alloc(
        S.getIslCtx(),
        std::string("SKill_phantom_").append(ToKillId.get_name()), nullptr);

    // NOTE: construction of tagged_must_kill:
    // 2. We need to construct a map:
    //     [param] -> { [Stmt_phantom[] -> ref_phantom[]] -> scalar_to_kill[] }
    // To construct this, we use `isl_map_domain_product` on 2 maps`:
    // 2a. StmtToScalar:
    //         [param] -> { Stmt_phantom[] -> scalar_to_kill[] }
    // 2b. PhantomRefToScalar:
    //         [param] -> { ref_phantom[] -> scalar_to_kill[] }
    //
    // Combining these with `isl_map_domain_product` gives us
    // TaggedMustKill:
    //     [param] -> { [Stmt[] -> phantom_ref[]] -> scalar_to_kill[] }

    // 2a. [param] -> { Stmt[] -> scalar_to_kill[] }
    isl::map StmtToScalar = isl::map::universe(ParamSpace);
    StmtToScalar = StmtToScalar.set_tuple_id(isl::dim::in, isl::id(KillStmtId));
    StmtToScalar = StmtToScalar.set_tuple_id(isl::dim::out, isl::id(ToKillId));

    isl::id PhantomRefId = isl::id::alloc(
        S.getIslCtx(), std::string("ref_phantom") + ToKillId.get_name(),
        nullptr);

    // 2b. [param] -> { phantom_ref[] -> scalar_to_kill[] }
    isl::map PhantomRefToScalar = isl::map::universe(ParamSpace);
    PhantomRefToScalar =
        PhantomRefToScalar.set_tuple_id(isl::dim::in, PhantomRefId);
    PhantomRefToScalar =
        PhantomRefToScalar.set_tuple_id(isl::dim::out, ToKillId);

    // 2. [param] -> { [Stmt[] -> phantom_ref[]] -> scalar_to_kill[] }
    isl::map TaggedMustKill = StmtToScalar.domain_product(PhantomRefToScalar);
    Info.TaggedMustKills = Info.TaggedMustKills.unite(TaggedMustKill);

    // 2. [param] -> { Stmt[] -> scalar_to_kill[] }
    Info.MustKills = Info.TaggedMustKills.domain_factor_domain();

    // 3. Create the kill schedule of the form:
    //     "[param] -> { Stmt_phantom[] }"
    // Then add this to Info.KillsSchedule.
    isl::space KillStmtSpace = ParamSpace;
    KillStmtSpace = KillStmtSpace.set_tuple_id(isl::dim::set, KillStmtId);
    isl::union_set KillStmtDomain = isl::set::universe(KillStmtSpace);

    isl::schedule KillSchedule = isl::schedule::from_domain(KillStmtDomain);
    if (!Info.KillsSchedule.is_null())
      Info.KillsSchedule = isl::manage(
          isl_schedule_set(Info.KillsSchedule.release(), KillSchedule.copy()));
    else
      Info.KillsSchedule = KillSchedule;
  }

  return Info;
}

/// Create the ast expressions for a ScopStmt.
///
/// This function is a callback for to generate the ast expressions for each
/// of the scheduled ScopStmts.
static __isl_give isl_id_to_ast_expr *pollyBuildAstExprForStmt(
    void *StmtT, __isl_take isl_ast_build *Build_C,
    isl_multi_pw_aff *(*FunctionIndex)(__isl_take isl_multi_pw_aff *MPA,
                                       isl_id *Id, void *User),
    void *UserIndex,
    isl_ast_expr *(*FunctionExpr)(isl_ast_expr *Expr, isl_id *Id, void *User),
    void *UserExpr) {

  ScopStmt *Stmt = (ScopStmt *)StmtT;

  if (!Stmt || !Build_C)
    return NULL;

  isl::ast_build Build = isl::manage_copy(Build_C);
  isl::ctx Ctx = Build.get_ctx();
  isl::id_to_ast_expr RefToExpr = isl::id_to_ast_expr::alloc(Ctx, 0);

  Stmt->setAstBuild(Build);

  for (MemoryAccess *Acc : *Stmt) {
    isl::map AddrFunc = Acc->getAddressFunction();
    AddrFunc = AddrFunc.intersect_domain(Stmt->getDomain());

    isl::id RefId = Acc->getId();
    isl::pw_multi_aff PMA = isl::pw_multi_aff::from_map(AddrFunc);

    isl::multi_pw_aff MPA = isl::multi_pw_aff(PMA);
    MPA = MPA.coalesce();
    MPA = isl::manage(FunctionIndex(MPA.release(), RefId.get(), UserIndex));

    isl::ast_expr Access = Build.access_from(MPA);
    Access = isl::manage(FunctionExpr(Access.release(), RefId.get(), UserExpr));
    RefToExpr = RefToExpr.set(RefId, Access);
  }

  return RefToExpr.release();
}

/// Given a LLVM Type, compute its size in bytes,
static int computeSizeInBytes(const Type *T) {
  int bytes = T->getPrimitiveSizeInBits() / 8;
  if (bytes == 0)
    bytes = T->getScalarSizeInBits() / 8;
  return bytes;
}

/// Generate code for a GPU specific isl AST.
///
/// The GPUNodeBuilder augments the general existing IslNodeBuilder, which
/// generates code for general-purpose AST nodes, with special functionality
/// for generating GPU specific user nodes.
///
/// @see GPUNodeBuilder::createUser
class GPUNodeBuilder : public IslNodeBuilder {
public:
  GPUNodeBuilder(PollyIRBuilder &Builder, ScopAnnotator &Annotator,
                 const DataLayout &DL, LoopInfo &LI, ScalarEvolution &SE,
                 DominatorTree &DT, Scop &S, BasicBlock *StartBlock,
                 gpu_prog *Prog, GPURuntime Runtime, GPUArch Arch)
      : IslNodeBuilder(Builder, Annotator, DL, LI, SE, DT, S, StartBlock),
        Prog(Prog), Runtime(Runtime), Arch(Arch) {
    getExprBuilder().setIDToSAI(&IDToSAI);
  }

  /// Create after-run-time-check initialization code.
  void initializeAfterRTH();

  /// Finalize the generated scop.
  void finalize() override;

  /// Track if the full build process was successful.
  ///
  /// This value is set to false, if throughout the build process an error
  /// occurred which prevents us from generating valid GPU code.
  bool BuildSuccessful = true;

  /// The maximal number of loops surrounding a sequential kernel.
  unsigned DeepestSequential = 0;

  /// The maximal number of loops surrounding a parallel kernel.
  unsigned DeepestParallel = 0;

  /// Return the name to set for the ptx_kernel.
  std::string getKernelFuncName(int Kernel_id);

private:
  /// A vector of array base pointers for which a new ScopArrayInfo was created.
  ///
  /// This vector is used to delete the ScopArrayInfo when it is not needed any
  /// more.
  std::vector<Value *> LocalArrays;

  /// A map from ScopArrays to their corresponding device allocations.
  std::map<ScopArrayInfo *, Value *> DeviceAllocations;

  /// The current GPU context.
  Value *GPUContext;

  /// The set of isl_ids allocated in the kernel
  std::vector<isl_id *> KernelIds;

  /// A module containing GPU code.
  ///
  /// This pointer is only set in case we are currently generating GPU code.
  std::unique_ptr<Module> GPUModule;

  /// The GPU program we generate code for.
  gpu_prog *Prog;

  /// The GPU Runtime implementation to use (OpenCL or CUDA).
  GPURuntime Runtime;

  /// The GPU Architecture to target.
  GPUArch Arch;

  /// Class to free isl_ids.
  class IslIdDeleter {
  public:
    void operator()(__isl_take isl_id *Id) { isl_id_free(Id); };
  };

  /// A set containing all isl_ids allocated in a GPU kernel.
  ///
  /// By releasing this set all isl_ids will be freed.
  std::set<std::unique_ptr<isl_id, IslIdDeleter>> KernelIDs;

  IslExprBuilder::IDToScopArrayInfoTy IDToSAI;

  /// Create code for user-defined AST nodes.
  ///
  /// These AST nodes can be of type:
  ///
  ///   - ScopStmt:      A computational statement (TODO)
  ///   - Kernel:        A GPU kernel call (TODO)
  ///   - Data-Transfer: A GPU <-> CPU data-transfer
  ///   - In-kernel synchronization
  ///   - In-kernel memory copy statement
  ///
  /// @param UserStmt The ast node to generate code for.
  void createUser(__isl_take isl_ast_node *UserStmt) override;

  void createFor(__isl_take isl_ast_node *Node) override;

  enum DataDirection { HOST_TO_DEVICE, DEVICE_TO_HOST };

  /// Create code for a data transfer statement
  ///
  /// @param TransferStmt The data transfer statement.
  /// @param Direction The direction in which to transfer data.
  void createDataTransfer(__isl_take isl_ast_node *TransferStmt,
                          enum DataDirection Direction);

  /// Find llvm::Values referenced in GPU kernel.
  ///
  /// @param Kernel The kernel to scan for llvm::Values
  ///
  /// @returns A tuple, whose:
  ///          - First element contains the set of values referenced by the
  ///            kernel
  ///          - Second element contains the set of functions referenced by the
  ///             kernel. All functions in the set satisfy
  ///             `isValidFunctionInKernel`.
  ///          - Third element contains loops that have induction variables
  ///            which are used in the kernel, *and* these loops are *neither*
  ///            in the scop, nor do they immediately surroung the Scop.
  ///            See [Code generation of induction variables of loops outside
  ///            Scops]
  std::tuple<SetVector<Value *>, SetVector<Function *>, SetVector<const Loop *>,
             isl::space>
  getReferencesInKernel(ppcg_kernel *Kernel);

  /// Compute the sizes of the execution grid for a given kernel.
  ///
  /// @param Kernel The kernel to compute grid sizes for.
  ///
  /// @returns A tuple with grid sizes for X and Y dimension
  std::tuple<Value *, Value *> getGridSizes(ppcg_kernel *Kernel);

  /// Get the managed array pointer for sending host pointers to the device.
  /// \note
  /// This is to be used only with managed memory
  Value *getManagedDeviceArray(gpu_array_info *Array, ScopArrayInfo *ArrayInfo);

  /// Compute the sizes of the thread blocks for a given kernel.
  ///
  /// @param Kernel The kernel to compute thread block sizes for.
  ///
  /// @returns A tuple with thread block sizes for X, Y, and Z dimensions.
  std::tuple<Value *, Value *, Value *> getBlockSizes(ppcg_kernel *Kernel);

  /// Store a specific kernel launch parameter in the array of kernel launch
  /// parameters.
  ///
  /// @param Parameters The list of parameters in which to store.
  /// @param Param      The kernel launch parameter to store.
  /// @param Index      The index in the parameter list, at which to store the
  ///                   parameter.
  void insertStoreParameter(Instruction *Parameters, Instruction *Param,
                            int Index);

  /// Create kernel launch parameters.
  ///
  /// @param Kernel        The kernel to create parameters for.
  /// @param F             The kernel function that has been created.
  /// @param SubtreeValues The set of llvm::Values referenced by this kernel.
  ///
  /// @returns A stack allocated array with pointers to the parameter
  ///          values that are passed to the kernel.
  Value *createLaunchParameters(ppcg_kernel *Kernel, Function *F,
                                SetVector<Value *> SubtreeValues);

  /// Create declarations for kernel variable.
  ///
  /// This includes shared memory declarations.
  ///
  /// @param Kernel        The kernel definition to create variables for.
  /// @param FN            The function into which to generate the variables.
  void createKernelVariables(ppcg_kernel *Kernel, Function *FN);

  /// Add CUDA annotations to module.
  ///
  /// Add a set of CUDA annotations that declares the maximal block dimensions
  /// that will be used to execute the CUDA kernel. This allows the NVIDIA
  /// PTX compiler to bound the number of allocated registers to ensure the
  /// resulting kernel is known to run with up to as many block dimensions
  /// as specified here.
  ///
  /// @param M         The module to add the annotations to.
  /// @param BlockDimX The size of block dimension X.
  /// @param BlockDimY The size of block dimension Y.
  /// @param BlockDimZ The size of block dimension Z.
  void addCUDAAnnotations(Module *M, Value *BlockDimX, Value *BlockDimY,
                          Value *BlockDimZ);

  /// Create GPU kernel.
  ///
  /// Code generate the kernel described by @p KernelStmt.
  ///
  /// @param KernelStmt The ast node to generate kernel code for.
  void createKernel(__isl_take isl_ast_node *KernelStmt);

  /// Generate code that computes the size of an array.
  ///
  /// @param Array The array for which to compute a size.
  Value *getArraySize(gpu_array_info *Array);

  /// Generate code to compute the minimal offset at which an array is accessed.
  ///
  /// The offset of an array is the minimal array location accessed in a scop.
  ///
  /// Example:
  ///
  ///   for (long i = 0; i < 100; i++)
  ///     A[i + 42] += ...
  ///
  ///   getArrayOffset(A) results in 42.
  ///
  /// @param Array The array for which to compute the offset.
  /// @returns An llvm::Value that contains the offset of the array.
  Value *getArrayOffset(gpu_array_info *Array);

  /// Prepare the kernel arguments for kernel code generation
  ///
  /// @param Kernel The kernel to generate code for.
  /// @param FN     The function created for the kernel.
  void prepareKernelArguments(ppcg_kernel *Kernel, Function *FN);

  /// Create kernel function.
  ///
  /// Create a kernel function located in a newly created module that can serve
  /// as target for device code generation. Set the Builder to point to the
  /// start block of this newly created function.
  ///
  /// @param Kernel The kernel to generate code for.
  /// @param SubtreeValues The set of llvm::Values referenced by this kernel.
  /// @param SubtreeFunctions The set of llvm::Functions referenced by this
  ///                         kernel.
  void createKernelFunction(ppcg_kernel *Kernel,
                            SetVector<Value *> &SubtreeValues,
                            SetVector<Function *> &SubtreeFunctions);

  /// Create the declaration of a kernel function.
  ///
  /// The kernel function takes as arguments:
  ///
  ///   - One i8 pointer for each external array reference used in the kernel.
  ///   - Host iterators
  ///   - Parameters
  ///   - Other LLVM Value references (TODO)
  ///
  /// @param Kernel The kernel to generate the function declaration for.
  /// @param SubtreeValues The set of llvm::Values referenced by this kernel.
  ///
  /// @returns The newly declared function.
  Function *createKernelFunctionDecl(ppcg_kernel *Kernel,
                                     SetVector<Value *> &SubtreeValues);

  /// Insert intrinsic functions to obtain thread and block ids.
  ///
  /// @param The kernel to generate the intrinsic functions for.
  void insertKernelIntrinsics(ppcg_kernel *Kernel);

  /// Insert function calls to retrieve the SPIR group/local ids.
  ///
  /// @param Kernel The kernel to generate the function calls for.
  /// @param SizeTypeIs64Bit Whether size_t of the openCl device is 64bit.
  void insertKernelCallsSPIR(ppcg_kernel *Kernel, bool SizeTypeIs64bit);

  /// Setup the creation of functions referenced by the GPU kernel.
  ///
  /// 1. Create new function declarations in GPUModule which are the same as
  /// SubtreeFunctions.
  ///
  /// 2. Populate IslNodeBuilder::ValueMap with mappings from
  /// old functions (that come from the original module) to new functions
  /// (that are created within GPUModule). That way, we generate references
  /// to the correct function (in GPUModule) in BlockGenerator.
  ///
  /// @see IslNodeBuilder::ValueMap
  /// @see BlockGenerator::GlobalMap
  /// @see BlockGenerator::getNewValue
  /// @see GPUNodeBuilder::getReferencesInKernel.
  ///
  /// @param SubtreeFunctions The set of llvm::Functions referenced by
  ///                         this kernel.
  void setupKernelSubtreeFunctions(SetVector<Function *> SubtreeFunctions);

  /// Create a global-to-shared or shared-to-global copy statement.
  ///
  /// @param CopyStmt The copy statement to generate code for
  void createKernelCopy(ppcg_kernel_stmt *CopyStmt);

  /// Create code for a ScopStmt called in @p Expr.
  ///
  /// @param Expr The expression containing the call.
  /// @param KernelStmt The kernel statement referenced in the call.
  void createScopStmt(isl_ast_expr *Expr, ppcg_kernel_stmt *KernelStmt);

  /// Create an in-kernel synchronization call.
  void createKernelSync();

  /// Create a PTX assembly string for the current GPU kernel.
  ///
  /// @returns A string containing the corresponding PTX assembly code.
  std::string createKernelASM();

  /// Remove references from the dominator tree to the kernel function @p F.
  ///
  /// @param F The function to remove references to.
  void clearDominators(Function *F);

  /// Remove references from scalar evolution to the kernel function @p F.
  ///
  /// @param F The function to remove references to.
  void clearScalarEvolution(Function *F);

  /// Remove references from loop info to the kernel function @p F.
  ///
  /// @param F The function to remove references to.
  void clearLoops(Function *F);

  /// Check if the scop requires to be linked with CUDA's libdevice.
  bool requiresCUDALibDevice();

  /// Link with the NVIDIA libdevice library (if needed and available).
  void addCUDALibDevice();

  /// Finalize the generation of the kernel function.
  ///
  /// Free the LLVM-IR module corresponding to the kernel and -- if requested --
  /// dump its IR to stderr.
  ///
  /// @returns The Assembly string of the kernel.
  std::string finalizeKernelFunction();

  /// Finalize the generation of the kernel arguments.
  ///
  /// This function ensures that not-read-only scalars used in a kernel are
  /// stored back to the global memory location they are backed with before
  /// the kernel terminates.
  ///
  /// @params Kernel The kernel to finalize kernel arguments for.
  void finalizeKernelArguments(ppcg_kernel *Kernel);

  /// Create code that allocates memory to store arrays on device.
  void allocateDeviceArrays();

  /// Create code to prepare the managed device pointers.
  void prepareManagedDeviceArrays();

  /// Free all allocated device arrays.
  void freeDeviceArrays();

  /// Create a call to initialize the GPU context.
  ///
  /// @returns A pointer to the newly initialized context.
  Value *createCallInitContext();

  /// Create a call to get the device pointer for a kernel allocation.
  ///
  /// @param Allocation The Polly GPU allocation
  ///
  /// @returns The device parameter corresponding to this allocation.
  Value *createCallGetDevicePtr(Value *Allocation);

  /// Create a call to free the GPU context.
  ///
  /// @param Context A pointer to an initialized GPU context.
  void createCallFreeContext(Value *Context);

  /// Create a call to allocate memory on the device.
  ///
  /// @param Size The size of memory to allocate
  ///
  /// @returns A pointer that identifies this allocation.
  Value *createCallAllocateMemoryForDevice(Value *Size);

  /// Create a call to free a device array.
  ///
  /// @param Array The device array to free.
  void createCallFreeDeviceMemory(Value *Array);

  /// Create a call to copy data from host to device.
  ///
  /// @param HostPtr A pointer to the host data that should be copied.
  /// @param DevicePtr A device pointer specifying the location to copy to.
  void createCallCopyFromHostToDevice(Value *HostPtr, Value *DevicePtr,
                                      Value *Size);

  /// Create a call to copy data from device to host.
  ///
  /// @param DevicePtr A pointer to the device data that should be copied.
  /// @param HostPtr A host pointer specifying the location to copy to.
  void createCallCopyFromDeviceToHost(Value *DevicePtr, Value *HostPtr,
                                      Value *Size);

  /// Create a call to synchronize Host & Device.
  /// \note
  /// This is to be used only with managed memory.
  void createCallSynchronizeDevice();

  /// Create a call to get a kernel from an assembly string.
  ///
  /// @param Buffer The string describing the kernel.
  /// @param Entry  The name of the kernel function to call.
  ///
  /// @returns A pointer to a kernel object
  Value *createCallGetKernel(Value *Buffer, Value *Entry);

  /// Create a call to free a GPU kernel.
  ///
  /// @param GPUKernel THe kernel to free.
  void createCallFreeKernel(Value *GPUKernel);

  /// Create a call to launch a GPU kernel.
  ///
  /// @param GPUKernel  The kernel to launch.
  /// @param GridDimX   The size of the first grid dimension.
  /// @param GridDimY   The size of the second grid dimension.
  /// @param GridBlockX The size of the first block dimension.
  /// @param GridBlockY The size of the second block dimension.
  /// @param GridBlockZ The size of the third block dimension.
  /// @param Parameters A pointer to an array that contains itself pointers to
  ///                   the parameter values passed for each kernel argument.
  void createCallLaunchKernel(Value *GPUKernel, Value *GridDimX,
                              Value *GridDimY, Value *BlockDimX,
                              Value *BlockDimY, Value *BlockDimZ,
                              Value *Parameters);
};

std::string GPUNodeBuilder::getKernelFuncName(int Kernel_id) {
  return "FUNC_" + S.getFunction().getName().str() + "_SCOP_" +
         std::to_string(S.getID()) + "_KERNEL_" + std::to_string(Kernel_id);
}

void GPUNodeBuilder::initializeAfterRTH() {
  BasicBlock *NewBB = SplitBlock(Builder.GetInsertBlock(),
                                 &*Builder.GetInsertPoint(), &DT, &LI);
  NewBB->setName("polly.acc.initialize");
  Builder.SetInsertPoint(&NewBB->front());

  GPUContext = createCallInitContext();

  if (!PollyManagedMemory)
    allocateDeviceArrays();
  else
    prepareManagedDeviceArrays();
}

void GPUNodeBuilder::finalize() {
  if (!PollyManagedMemory)
    freeDeviceArrays();

  createCallFreeContext(GPUContext);
  IslNodeBuilder::finalize();
}

void GPUNodeBuilder::allocateDeviceArrays() {
  assert(!PollyManagedMemory &&
         "Managed memory will directly send host pointers "
         "to the kernel. There is no need for device arrays");
  isl_ast_build *Build = isl_ast_build_from_context(S.getContext().release());

  for (int i = 0; i < Prog->n_array; ++i) {
    gpu_array_info *Array = &Prog->array[i];
    auto *ScopArray = (ScopArrayInfo *)Array->user;
    std::string DevArrayName("p_dev_array_");
    DevArrayName.append(Array->name);

    Value *ArraySize = getArraySize(Array);
    Value *Offset = getArrayOffset(Array);
    if (Offset)
      ArraySize = Builder.CreateSub(
          ArraySize,
          Builder.CreateMul(Offset,
                            Builder.getInt64(ScopArray->getElemSizeInBytes())));
    const SCEV *SizeSCEV = SE.getSCEV(ArraySize);
    // It makes no sense to have an array of size 0. The CUDA API will
    // throw an error anyway if we invoke `cuMallocManaged` with size `0`. We
    // choose to be defensive and catch this at the compile phase. It is
    // most likely that we are doing something wrong with size computation.
    if (SizeSCEV->isZero()) {
      errs() << getUniqueScopName(&S)
             << " has computed array size 0: " << *ArraySize
             << " | for array: " << *(ScopArray->getBasePtr())
             << ". This is illegal, exiting.\n";
      report_fatal_error("array size was computed to be 0");
    }

    Value *DevArray = createCallAllocateMemoryForDevice(ArraySize);
    DevArray->setName(DevArrayName);
    DeviceAllocations[ScopArray] = DevArray;
  }

  isl_ast_build_free(Build);
}

void GPUNodeBuilder::prepareManagedDeviceArrays() {
  assert(PollyManagedMemory &&
         "Device array most only be prepared in managed-memory mode");
  for (int i = 0; i < Prog->n_array; ++i) {
    gpu_array_info *Array = &Prog->array[i];
    ScopArrayInfo *ScopArray = (ScopArrayInfo *)Array->user;
    Value *HostPtr;

    if (gpu_array_is_scalar(Array))
      HostPtr = BlockGen.getOrCreateAlloca(ScopArray);
    else
      HostPtr = ScopArray->getBasePtr();
    HostPtr = getLatestValue(HostPtr);

    Value *Offset = getArrayOffset(Array);
    if (Offset) {
      HostPtr = Builder.CreatePointerCast(
          HostPtr, ScopArray->getElementType()->getPointerTo());
      HostPtr = Builder.CreateGEP(HostPtr, Offset);
    }

    HostPtr = Builder.CreatePointerCast(HostPtr, Builder.getInt8PtrTy());
    DeviceAllocations[ScopArray] = HostPtr;
  }
}

void GPUNodeBuilder::addCUDAAnnotations(Module *M, Value *BlockDimX,
                                        Value *BlockDimY, Value *BlockDimZ) {
  auto AnnotationNode = M->getOrInsertNamedMetadata("nvvm.annotations");

  for (auto &F : *M) {
    if (F.getCallingConv() != CallingConv::PTX_Kernel)
      continue;

    Value *V[] = {BlockDimX, BlockDimY, BlockDimZ};

    Metadata *Elements[] = {
        ValueAsMetadata::get(&F),   MDString::get(M->getContext(), "maxntidx"),
        ValueAsMetadata::get(V[0]), MDString::get(M->getContext(), "maxntidy"),
        ValueAsMetadata::get(V[1]), MDString::get(M->getContext(), "maxntidz"),
        ValueAsMetadata::get(V[2]),
    };
    MDNode *Node = MDNode::get(M->getContext(), Elements);
    AnnotationNode->addOperand(Node);
  }
}

void GPUNodeBuilder::freeDeviceArrays() {
  assert(!PollyManagedMemory && "Managed memory does not use device arrays");
  for (auto &Array : DeviceAllocations)
    createCallFreeDeviceMemory(Array.second);
}

Value *GPUNodeBuilder::createCallGetKernel(Value *Buffer, Value *Entry) {
  const char *Name = "polly_getKernel";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt8PtrTy());
    Args.push_back(Builder.getInt8PtrTy());
    FunctionType *Ty = FunctionType::get(Builder.getInt8PtrTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  return Builder.CreateCall(F, {Buffer, Entry});
}

Value *GPUNodeBuilder::createCallGetDevicePtr(Value *Allocation) {
  const char *Name = "polly_getDevicePtr";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt8PtrTy());
    FunctionType *Ty = FunctionType::get(Builder.getInt8PtrTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  return Builder.CreateCall(F, {Allocation});
}

void GPUNodeBuilder::createCallLaunchKernel(Value *GPUKernel, Value *GridDimX,
                                            Value *GridDimY, Value *BlockDimX,
                                            Value *BlockDimY, Value *BlockDimZ,
                                            Value *Parameters) {
  const char *Name = "polly_launchKernel";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt8PtrTy());
    Args.push_back(Builder.getInt32Ty());
    Args.push_back(Builder.getInt32Ty());
    Args.push_back(Builder.getInt32Ty());
    Args.push_back(Builder.getInt32Ty());
    Args.push_back(Builder.getInt32Ty());
    Args.push_back(Builder.getInt8PtrTy());
    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  Builder.CreateCall(F, {GPUKernel, GridDimX, GridDimY, BlockDimX, BlockDimY,
                         BlockDimZ, Parameters});
}

void GPUNodeBuilder::createCallFreeKernel(Value *GPUKernel) {
  const char *Name = "polly_freeKernel";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt8PtrTy());
    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  Builder.CreateCall(F, {GPUKernel});
}

void GPUNodeBuilder::createCallFreeDeviceMemory(Value *Array) {
  assert(!PollyManagedMemory &&
         "Managed memory does not allocate or free memory "
         "for device");
  const char *Name = "polly_freeDeviceMemory";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt8PtrTy());
    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  Builder.CreateCall(F, {Array});
}

Value *GPUNodeBuilder::createCallAllocateMemoryForDevice(Value *Size) {
  assert(!PollyManagedMemory &&
         "Managed memory does not allocate or free memory "
         "for device");
  const char *Name = "polly_allocateMemoryForDevice";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt64Ty());
    FunctionType *Ty = FunctionType::get(Builder.getInt8PtrTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  return Builder.CreateCall(F, {Size});
}

void GPUNodeBuilder::createCallCopyFromHostToDevice(Value *HostData,
                                                    Value *DeviceData,
                                                    Value *Size) {
  assert(!PollyManagedMemory &&
         "Managed memory does not transfer memory between "
         "device and host");
  const char *Name = "polly_copyFromHostToDevice";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt8PtrTy());
    Args.push_back(Builder.getInt8PtrTy());
    Args.push_back(Builder.getInt64Ty());
    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  Builder.CreateCall(F, {HostData, DeviceData, Size});
}

void GPUNodeBuilder::createCallCopyFromDeviceToHost(Value *DeviceData,
                                                    Value *HostData,
                                                    Value *Size) {
  assert(!PollyManagedMemory &&
         "Managed memory does not transfer memory between "
         "device and host");
  const char *Name = "polly_copyFromDeviceToHost";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt8PtrTy());
    Args.push_back(Builder.getInt8PtrTy());
    Args.push_back(Builder.getInt64Ty());
    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  Builder.CreateCall(F, {DeviceData, HostData, Size});
}

void GPUNodeBuilder::createCallSynchronizeDevice() {
  assert(PollyManagedMemory && "explicit synchronization is only necessary for "
                               "managed memory");
  const char *Name = "polly_synchronizeDevice";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  Builder.CreateCall(F);
}

Value *GPUNodeBuilder::createCallInitContext() {
  const char *Name;

  switch (Runtime) {
  case GPURuntime::CUDA:
    Name = "polly_initContextCUDA";
    break;
  case GPURuntime::OpenCL:
    Name = "polly_initContextCL";
    break;
  }

  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    FunctionType *Ty = FunctionType::get(Builder.getInt8PtrTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  return Builder.CreateCall(F, {});
}

void GPUNodeBuilder::createCallFreeContext(Value *Context) {
  const char *Name = "polly_freeContext";
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  Function *F = M->getFunction(Name);

  // If F is not available, declare it.
  if (!F) {
    GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
    std::vector<Type *> Args;
    Args.push_back(Builder.getInt8PtrTy());
    FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
    F = Function::Create(Ty, Linkage, Name, M);
  }

  Builder.CreateCall(F, {Context});
}

/// Check if one string is a prefix of another.
///
/// @param String The string in which to look for the prefix.
/// @param Prefix The prefix to look for.
static bool isPrefix(std::string String, std::string Prefix) {
  return String.find(Prefix) == 0;
}

Value *GPUNodeBuilder::getArraySize(gpu_array_info *Array) {
  isl::ast_build Build = isl::ast_build::from_context(S.getContext());
  Value *ArraySize = ConstantInt::get(Builder.getInt64Ty(), Array->size);

  if (!gpu_array_is_scalar(Array)) {
    isl::multi_pw_aff ArrayBound = isl::manage_copy(Array->bound);

    isl::pw_aff OffsetDimZero = ArrayBound.get_pw_aff(0);
    isl::ast_expr Res = Build.expr_from(OffsetDimZero);

    for (unsigned int i = 1; i < Array->n_index; i++) {
      isl::pw_aff Bound_I = ArrayBound.get_pw_aff(i);
      isl::ast_expr Expr = Build.expr_from(Bound_I);
      Res = Res.mul(Expr);
    }

    Value *NumElements = ExprBuilder.create(Res.release());
    if (NumElements->getType() != ArraySize->getType())
      NumElements = Builder.CreateSExt(NumElements, ArraySize->getType());
    ArraySize = Builder.CreateMul(ArraySize, NumElements);
  }
  return ArraySize;
}

Value *GPUNodeBuilder::getArrayOffset(gpu_array_info *Array) {
  if (gpu_array_is_scalar(Array))
    return nullptr;

  isl::ast_build Build = isl::ast_build::from_context(S.getContext());

  isl::set Min = isl::manage_copy(Array->extent).lexmin();

  isl::set ZeroSet = isl::set::universe(Min.get_space());

  for (long i = 0, n = Min.dim(isl::dim::set); i < n; i++)
    ZeroSet = ZeroSet.fix_si(isl::dim::set, i, 0);

  if (Min.is_subset(ZeroSet)) {
    return nullptr;
  }

  isl::ast_expr Result = isl::ast_expr::from_val(isl::val(Min.get_ctx(), 0));

  for (long i = 0, n = Min.dim(isl::dim::set); i < n; i++) {
    if (i > 0) {
      isl::pw_aff Bound_I =
          isl::manage(isl_multi_pw_aff_get_pw_aff(Array->bound, i - 1));
      isl::ast_expr BExpr = Build.expr_from(Bound_I);
      Result = Result.mul(BExpr);
    }
    isl::pw_aff DimMin = Min.dim_min(i);
    isl::ast_expr MExpr = Build.expr_from(DimMin);
    Result = Result.add(MExpr);
  }

  return ExprBuilder.create(Result.release());
}

Value *GPUNodeBuilder::getManagedDeviceArray(gpu_array_info *Array,
                                             ScopArrayInfo *ArrayInfo) {
  assert(PollyManagedMemory && "Only used when you wish to get a host "
                               "pointer for sending data to the kernel, "
                               "with managed memory");
  std::map<ScopArrayInfo *, Value *>::iterator it;
  it = DeviceAllocations.find(ArrayInfo);
  assert(it != DeviceAllocations.end() &&
         "Device array expected to be available");
  return it->second;
}

void GPUNodeBuilder::createDataTransfer(__isl_take isl_ast_node *TransferStmt,
                                        enum DataDirection Direction) {
  assert(!PollyManagedMemory && "Managed memory needs no data transfers");
  isl_ast_expr *Expr = isl_ast_node_user_get_expr(TransferStmt);
  isl_ast_expr *Arg = isl_ast_expr_get_op_arg(Expr, 0);
  isl_id *Id = isl_ast_expr_get_id(Arg);
  auto Array = (gpu_array_info *)isl_id_get_user(Id);
  auto ScopArray = (ScopArrayInfo *)(Array->user);

  Value *Size = getArraySize(Array);
  Value *Offset = getArrayOffset(Array);
  Value *DevPtr = DeviceAllocations[ScopArray];

  Value *HostPtr;

  if (gpu_array_is_scalar(Array))
    HostPtr = BlockGen.getOrCreateAlloca(ScopArray);
  else
    HostPtr = ScopArray->getBasePtr();
  HostPtr = getLatestValue(HostPtr);

  if (Offset) {
    HostPtr = Builder.CreatePointerCast(
        HostPtr, ScopArray->getElementType()->getPointerTo());
    HostPtr = Builder.CreateGEP(HostPtr, Offset);
  }

  HostPtr = Builder.CreatePointerCast(HostPtr, Builder.getInt8PtrTy());

  if (Offset) {
    Size = Builder.CreateSub(
        Size, Builder.CreateMul(
                  Offset, Builder.getInt64(ScopArray->getElemSizeInBytes())));
  }

  if (Direction == HOST_TO_DEVICE)
    createCallCopyFromHostToDevice(HostPtr, DevPtr, Size);
  else
    createCallCopyFromDeviceToHost(DevPtr, HostPtr, Size);

  isl_id_free(Id);
  isl_ast_expr_free(Arg);
  isl_ast_expr_free(Expr);
  isl_ast_node_free(TransferStmt);
}

void GPUNodeBuilder::createUser(__isl_take isl_ast_node *UserStmt) {
  isl_ast_expr *Expr = isl_ast_node_user_get_expr(UserStmt);
  isl_ast_expr *StmtExpr = isl_ast_expr_get_op_arg(Expr, 0);
  isl_id *Id = isl_ast_expr_get_id(StmtExpr);
  isl_id_free(Id);
  isl_ast_expr_free(StmtExpr);

  const char *Str = isl_id_get_name(Id);
  if (!strcmp(Str, "kernel")) {
    createKernel(UserStmt);
    if (PollyManagedMemory)
      createCallSynchronizeDevice();
    isl_ast_expr_free(Expr);
    return;
  }
  if (!strcmp(Str, "init_device")) {
    initializeAfterRTH();
    isl_ast_node_free(UserStmt);
    isl_ast_expr_free(Expr);
    return;
  }
  if (!strcmp(Str, "clear_device")) {
    finalize();
    isl_ast_node_free(UserStmt);
    isl_ast_expr_free(Expr);
    return;
  }
  if (isPrefix(Str, "to_device")) {
    if (!PollyManagedMemory)
      createDataTransfer(UserStmt, HOST_TO_DEVICE);
    else
      isl_ast_node_free(UserStmt);

    isl_ast_expr_free(Expr);
    return;
  }

  if (isPrefix(Str, "from_device")) {
    if (!PollyManagedMemory) {
      createDataTransfer(UserStmt, DEVICE_TO_HOST);
    } else {
      isl_ast_node_free(UserStmt);
    }
    isl_ast_expr_free(Expr);
    return;
  }

  isl_id *Anno = isl_ast_node_get_annotation(UserStmt);
  struct ppcg_kernel_stmt *KernelStmt =
      (struct ppcg_kernel_stmt *)isl_id_get_user(Anno);
  isl_id_free(Anno);

  switch (KernelStmt->type) {
  case ppcg_kernel_domain:
    createScopStmt(Expr, KernelStmt);
    isl_ast_node_free(UserStmt);
    return;
  case ppcg_kernel_copy:
    createKernelCopy(KernelStmt);
    isl_ast_expr_free(Expr);
    isl_ast_node_free(UserStmt);
    return;
  case ppcg_kernel_sync:
    createKernelSync();
    isl_ast_expr_free(Expr);
    isl_ast_node_free(UserStmt);
    return;
  }

  isl_ast_expr_free(Expr);
  isl_ast_node_free(UserStmt);
}

void GPUNodeBuilder::createFor(__isl_take isl_ast_node *Node) {
  createForSequential(isl::manage(Node), false);
}

void GPUNodeBuilder::createKernelCopy(ppcg_kernel_stmt *KernelStmt) {
  isl_ast_expr *LocalIndex = isl_ast_expr_copy(KernelStmt->u.c.local_index);
  LocalIndex = isl_ast_expr_address_of(LocalIndex);
  Value *LocalAddr = ExprBuilder.create(LocalIndex);
  isl_ast_expr *Index = isl_ast_expr_copy(KernelStmt->u.c.index);
  Index = isl_ast_expr_address_of(Index);
  Value *GlobalAddr = ExprBuilder.create(Index);
  Type *IndexTy = cast<PointerType>(GlobalAddr->getType())->getElementType();

  if (KernelStmt->u.c.read) {
    LoadInst *Load = Builder.CreateLoad(IndexTy, GlobalAddr, "shared.read");
    Builder.CreateStore(Load, LocalAddr);
  } else {
    LoadInst *Load = Builder.CreateLoad(IndexTy, LocalAddr, "shared.write");
    Builder.CreateStore(Load, GlobalAddr);
  }
}

void GPUNodeBuilder::createScopStmt(isl_ast_expr *Expr,
                                    ppcg_kernel_stmt *KernelStmt) {
  auto Stmt = (ScopStmt *)KernelStmt->u.d.stmt->stmt;
  isl_id_to_ast_expr *Indexes = KernelStmt->u.d.ref2expr;

  LoopToScevMapT LTS;
  LTS.insert(OutsideLoopIterations.begin(), OutsideLoopIterations.end());

  createSubstitutions(Expr, Stmt, LTS);

  if (Stmt->isBlockStmt())
    BlockGen.copyStmt(*Stmt, LTS, Indexes);
  else
    RegionGen.copyStmt(*Stmt, LTS, Indexes);
}

void GPUNodeBuilder::createKernelSync() {
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();
  const char *SpirName = "__gen_ocl_barrier_global";

  Function *Sync;

  switch (Arch) {
  case GPUArch::SPIR64:
  case GPUArch::SPIR32:
    Sync = M->getFunction(SpirName);

    // If Sync is not available, declare it.
    if (!Sync) {
      GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
      std::vector<Type *> Args;
      FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), Args, false);
      Sync = Function::Create(Ty, Linkage, SpirName, M);
      Sync->setCallingConv(CallingConv::SPIR_FUNC);
    }
    break;
  case GPUArch::NVPTX64:
    Sync = Intrinsic::getDeclaration(M, Intrinsic::nvvm_barrier0);
    break;
  }

  Builder.CreateCall(Sync, {});
}

/// Collect llvm::Values referenced from @p Node
///
/// This function only applies to isl_ast_nodes that are user_nodes referring
/// to a ScopStmt. All other node types are ignore.
///
/// @param Node The node to collect references for.
/// @param User A user pointer used as storage for the data that is collected.
///
/// @returns isl_bool_true if data could be collected successfully.
isl_bool collectReferencesInGPUStmt(__isl_keep isl_ast_node *Node, void *User) {
  if (isl_ast_node_get_type(Node) != isl_ast_node_user)
    return isl_bool_true;

  isl_ast_expr *Expr = isl_ast_node_user_get_expr(Node);
  isl_ast_expr *StmtExpr = isl_ast_expr_get_op_arg(Expr, 0);
  isl_id *Id = isl_ast_expr_get_id(StmtExpr);
  const char *Str = isl_id_get_name(Id);
  isl_id_free(Id);
  isl_ast_expr_free(StmtExpr);
  isl_ast_expr_free(Expr);

  if (!isPrefix(Str, "Stmt"))
    return isl_bool_true;

  Id = isl_ast_node_get_annotation(Node);
  auto *KernelStmt = (ppcg_kernel_stmt *)isl_id_get_user(Id);
  auto Stmt = (ScopStmt *)KernelStmt->u.d.stmt->stmt;
  isl_id_free(Id);

  addReferencesFromStmt(Stmt, User, false /* CreateScalarRefs */);

  return isl_bool_true;
}

/// A list of functions that are available in NVIDIA's libdevice.
const std::set<std::string> CUDALibDeviceFunctions = {
    "exp",      "expf",      "expl",      "cos", "cosf", "sqrt", "sqrtf",
    "copysign", "copysignf", "copysignl", "log", "logf", "powi", "powif"};

// A map from intrinsics to their corresponding libdevice functions.
const std::map<std::string, std::string> IntrinsicToLibdeviceFunc = {
    {"llvm.exp.f64", "exp"},
    {"llvm.exp.f32", "expf"},
    {"llvm.powi.f64.i32", "powi"},
    {"llvm.powi.f32.i32", "powif"}};

/// Return the corresponding CUDA libdevice function name @p Name.
/// Note that this function will try to convert instrinsics in the list
/// IntrinsicToLibdeviceFunc into libdevice functions.
/// This is because some intrinsics such as `exp`
/// are not supported by the NVPTX backend.
/// If this restriction of the backend is lifted, we should refactor our code
/// so that we use intrinsics whenever possible.
///
/// Return "" if we are not compiling for CUDA.
std::string getCUDALibDeviceFuntion(StringRef NameRef) {
  std::string Name = NameRef.str();
  auto It = IntrinsicToLibdeviceFunc.find(Name);
  if (It != IntrinsicToLibdeviceFunc.end())
    return getCUDALibDeviceFuntion(It->second);

  if (CUDALibDeviceFunctions.count(Name))
    return ("__nv_" + Name);

  return "";
}

/// Check if F is a function that we can code-generate in a GPU kernel.
static bool isValidFunctionInKernel(llvm::Function *F, bool AllowLibDevice) {
  assert(F && "F is an invalid pointer");
  // We string compare against the name of the function to allow
  // all variants of the intrinsic "llvm.sqrt.*", "llvm.fabs", and
  // "llvm.copysign".
  const StringRef Name = F->getName();

  if (AllowLibDevice && getCUDALibDeviceFuntion(Name).length() > 0)
    return true;

  return F->isIntrinsic() &&
         (Name.startswith("llvm.sqrt") || Name.startswith("llvm.fabs") ||
          Name.startswith("llvm.copysign"));
}

/// Do not take `Function` as a subtree value.
///
/// We try to take the reference of all subtree values and pass them along
/// to the kernel from the host. Taking an address of any function and
/// trying to pass along is nonsensical. Only allow `Value`s that are not
/// `Function`s.
static bool isValidSubtreeValue(llvm::Value *V) { return !isa<Function>(V); }

/// Return `Function`s from `RawSubtreeValues`.
static SetVector<Function *>
getFunctionsFromRawSubtreeValues(SetVector<Value *> RawSubtreeValues,
                                 bool AllowCUDALibDevice) {
  SetVector<Function *> SubtreeFunctions;
  for (Value *It : RawSubtreeValues) {
    Function *F = dyn_cast<Function>(It);
    if (F) {
      assert(isValidFunctionInKernel(F, AllowCUDALibDevice) &&
             "Code should have bailed out by "
             "this point if an invalid function "
             "were present in a kernel.");
      SubtreeFunctions.insert(F);
    }
  }
  return SubtreeFunctions;
}

std::tuple<SetVector<Value *>, SetVector<Function *>, SetVector<const Loop *>,
           isl::space>
GPUNodeBuilder::getReferencesInKernel(ppcg_kernel *Kernel) {
  SetVector<Value *> SubtreeValues;
  SetVector<const SCEV *> SCEVs;
  SetVector<const Loop *> Loops;
  isl::space ParamSpace = isl::space(S.getIslCtx(), 0, 0).params();
  SubtreeReferences References = {
      LI,         SE, S, ValueMap, SubtreeValues, SCEVs, getBlockGenerator(),
      &ParamSpace};

  for (const auto &I : IDToValue)
    SubtreeValues.insert(I.second);

  // NOTE: this is populated in IslNodeBuilder::addParameters
  // See [Code generation of induction variables of loops outside Scops].
  for (const auto &I : OutsideLoopIterations)
    SubtreeValues.insert(cast<SCEVUnknown>(I.second)->getValue());

  isl_ast_node_foreach_descendant_top_down(
      Kernel->tree, collectReferencesInGPUStmt, &References);

  for (const SCEV *Expr : SCEVs) {
    findValues(Expr, SE, SubtreeValues);
    findLoops(Expr, Loops);
  }

  Loops.remove_if([this](const Loop *L) {
    return S.contains(L) || L->contains(S.getEntry());
  });

  for (auto &SAI : S.arrays())
    SubtreeValues.remove(SAI->getBasePtr());

  isl_space *Space = S.getParamSpace().release();
  for (long i = 0, n = isl_space_dim(Space, isl_dim_param); i < n; i++) {
    isl_id *Id = isl_space_get_dim_id(Space, isl_dim_param, i);
    assert(IDToValue.count(Id));
    Value *Val = IDToValue[Id];
    SubtreeValues.remove(Val);
    isl_id_free(Id);
  }
  isl_space_free(Space);

  for (long i = 0, n = isl_space_dim(Kernel->space, isl_dim_set); i < n; i++) {
    isl_id *Id = isl_space_get_dim_id(Kernel->space, isl_dim_set, i);
    assert(IDToValue.count(Id));
    Value *Val = IDToValue[Id];
    SubtreeValues.remove(Val);
    isl_id_free(Id);
  }

  // Note: { ValidSubtreeValues, ValidSubtreeFunctions } partitions
  // SubtreeValues. This is important, because we should not lose any
  // SubtreeValues in the process of constructing the
  // "ValidSubtree{Values, Functions} sets. Nor should the set
  // ValidSubtree{Values, Functions} have any common element.
  auto ValidSubtreeValuesIt =
      make_filter_range(SubtreeValues, isValidSubtreeValue);
  SetVector<Value *> ValidSubtreeValues(ValidSubtreeValuesIt.begin(),
                                        ValidSubtreeValuesIt.end());

  bool AllowCUDALibDevice = Arch == GPUArch::NVPTX64;

  SetVector<Function *> ValidSubtreeFunctions(
      getFunctionsFromRawSubtreeValues(SubtreeValues, AllowCUDALibDevice));

  // @see IslNodeBuilder::getReferencesInSubtree
  SetVector<Value *> ReplacedValues;
  for (Value *V : ValidSubtreeValues) {
    auto It = ValueMap.find(V);
    if (It == ValueMap.end())
      ReplacedValues.insert(V);
    else
      ReplacedValues.insert(It->second);
  }
  return std::make_tuple(ReplacedValues, ValidSubtreeFunctions, Loops,
                         ParamSpace);
}

void GPUNodeBuilder::clearDominators(Function *F) {
  DomTreeNode *N = DT.getNode(&F->getEntryBlock());
  std::vector<BasicBlock *> Nodes;
  for (po_iterator<DomTreeNode *> I = po_begin(N), E = po_end(N); I != E; ++I)
    Nodes.push_back(I->getBlock());

  for (BasicBlock *BB : Nodes)
    DT.eraseNode(BB);
}

void GPUNodeBuilder::clearScalarEvolution(Function *F) {
  for (BasicBlock &BB : *F) {
    Loop *L = LI.getLoopFor(&BB);
    if (L)
      SE.forgetLoop(L);
  }
}

void GPUNodeBuilder::clearLoops(Function *F) {
  SmallSet<Loop *, 1> WorkList;
  for (BasicBlock &BB : *F) {
    Loop *L = LI.getLoopFor(&BB);
    if (L)
      WorkList.insert(L);
  }
  for (auto *L : WorkList)
    LI.erase(L);
}

std::tuple<Value *, Value *> GPUNodeBuilder::getGridSizes(ppcg_kernel *Kernel) {
  std::vector<Value *> Sizes;
  isl::ast_build Context = isl::ast_build::from_context(S.getContext());

  isl::multi_pw_aff GridSizePwAffs = isl::manage_copy(Kernel->grid_size);
  for (long i = 0; i < Kernel->n_grid; i++) {
    isl::pw_aff Size = GridSizePwAffs.get_pw_aff(i);
    isl::ast_expr GridSize = Context.expr_from(Size);
    Value *Res = ExprBuilder.create(GridSize.release());
    Res = Builder.CreateTrunc(Res, Builder.getInt32Ty());
    Sizes.push_back(Res);
  }

  for (long i = Kernel->n_grid; i < 3; i++)
    Sizes.push_back(ConstantInt::get(Builder.getInt32Ty(), 1));

  return std::make_tuple(Sizes[0], Sizes[1]);
}

std::tuple<Value *, Value *, Value *>
GPUNodeBuilder::getBlockSizes(ppcg_kernel *Kernel) {
  std::vector<Value *> Sizes;

  for (long i = 0; i < Kernel->n_block; i++) {
    Value *Res = ConstantInt::get(Builder.getInt32Ty(), Kernel->block_dim[i]);
    Sizes.push_back(Res);
  }

  for (long i = Kernel->n_block; i < 3; i++)
    Sizes.push_back(ConstantInt::get(Builder.getInt32Ty(), 1));

  return std::make_tuple(Sizes[0], Sizes[1], Sizes[2]);
}

void GPUNodeBuilder::insertStoreParameter(Instruction *Parameters,
                                          Instruction *Param, int Index) {
  Value *Slot = Builder.CreateGEP(
      Parameters, {Builder.getInt64(0), Builder.getInt64(Index)});
  Value *ParamTyped = Builder.CreatePointerCast(Param, Builder.getInt8PtrTy());
  Builder.CreateStore(ParamTyped, Slot);
}

Value *
GPUNodeBuilder::createLaunchParameters(ppcg_kernel *Kernel, Function *F,
                                       SetVector<Value *> SubtreeValues) {
  const int NumArgs = F->arg_size();
  std::vector<int> ArgSizes(NumArgs);

  // If we are using the OpenCL Runtime, we need to add the kernel argument
  // sizes to the end of the launch-parameter list, so OpenCL can determine
  // how big the respective kernel arguments are.
  // Here we need to reserve adequate space for that.
  Type *ArrayTy;
  if (Runtime == GPURuntime::OpenCL)
    ArrayTy = ArrayType::get(Builder.getInt8PtrTy(), 2 * NumArgs);
  else
    ArrayTy = ArrayType::get(Builder.getInt8PtrTy(), NumArgs);

  BasicBlock *EntryBlock =
      &Builder.GetInsertBlock()->getParent()->getEntryBlock();
  auto AddressSpace = F->getParent()->getDataLayout().getAllocaAddrSpace();
  std::string Launch = "polly_launch_" + std::to_string(Kernel->id);
  Instruction *Parameters = new AllocaInst(
      ArrayTy, AddressSpace, Launch + "_params", EntryBlock->getTerminator());

  int Index = 0;
  for (long i = 0; i < Prog->n_array; i++) {
    if (!ppcg_kernel_requires_array_argument(Kernel, i))
      continue;

    isl_id *Id = isl_space_get_tuple_id(Prog->array[i].space, isl_dim_set);
    const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(isl::manage(Id));

    if (Runtime == GPURuntime::OpenCL)
      ArgSizes[Index] = SAI->getElemSizeInBytes();

    Value *DevArray = nullptr;
    if (PollyManagedMemory) {
      DevArray = getManagedDeviceArray(&Prog->array[i],
                                       const_cast<ScopArrayInfo *>(SAI));
    } else {
      DevArray = DeviceAllocations[const_cast<ScopArrayInfo *>(SAI)];
      DevArray = createCallGetDevicePtr(DevArray);
    }
    assert(DevArray != nullptr && "Array to be offloaded to device not "
                                  "initialized");
    Value *Offset = getArrayOffset(&Prog->array[i]);

    if (Offset) {
      DevArray = Builder.CreatePointerCast(
          DevArray, SAI->getElementType()->getPointerTo());
      DevArray = Builder.CreateGEP(DevArray, Builder.CreateNeg(Offset));
      DevArray = Builder.CreatePointerCast(DevArray, Builder.getInt8PtrTy());
    }
    Value *Slot = Builder.CreateGEP(
        Parameters, {Builder.getInt64(0), Builder.getInt64(Index)});

    if (gpu_array_is_read_only_scalar(&Prog->array[i])) {
      Value *ValPtr = nullptr;
      if (PollyManagedMemory)
        ValPtr = DevArray;
      else
        ValPtr = BlockGen.getOrCreateAlloca(SAI);

      assert(ValPtr != nullptr && "ValPtr that should point to a valid object"
                                  " to be stored into Parameters");
      Value *ValPtrCast =
          Builder.CreatePointerCast(ValPtr, Builder.getInt8PtrTy());
      Builder.CreateStore(ValPtrCast, Slot);
    } else {
      Instruction *Param =
          new AllocaInst(Builder.getInt8PtrTy(), AddressSpace,
                         Launch + "_param_" + std::to_string(Index),
                         EntryBlock->getTerminator());
      Builder.CreateStore(DevArray, Param);
      Value *ParamTyped =
          Builder.CreatePointerCast(Param, Builder.getInt8PtrTy());
      Builder.CreateStore(ParamTyped, Slot);
    }
    Index++;
  }

  int NumHostIters = isl_space_dim(Kernel->space, isl_dim_set);

  for (long i = 0; i < NumHostIters; i++) {
    isl_id *Id = isl_space_get_dim_id(Kernel->space, isl_dim_set, i);
    Value *Val = IDToValue[Id];
    isl_id_free(Id);

    if (Runtime == GPURuntime::OpenCL)
      ArgSizes[Index] = computeSizeInBytes(Val->getType());

    Instruction *Param =
        new AllocaInst(Val->getType(), AddressSpace,
                       Launch + "_param_" + std::to_string(Index),
                       EntryBlock->getTerminator());
    Builder.CreateStore(Val, Param);
    insertStoreParameter(Parameters, Param, Index);
    Index++;
  }

  int NumVars = isl_space_dim(Kernel->space, isl_dim_param);

  for (long i = 0; i < NumVars; i++) {
    isl_id *Id = isl_space_get_dim_id(Kernel->space, isl_dim_param, i);
    Value *Val = IDToValue[Id];
    if (ValueMap.count(Val))
      Val = ValueMap[Val];
    isl_id_free(Id);

    if (Runtime == GPURuntime::OpenCL)
      ArgSizes[Index] = computeSizeInBytes(Val->getType());

    Instruction *Param =
        new AllocaInst(Val->getType(), AddressSpace,
                       Launch + "_param_" + std::to_string(Index),
                       EntryBlock->getTerminator());
    Builder.CreateStore(Val, Param);
    insertStoreParameter(Parameters, Param, Index);
    Index++;
  }

  for (auto Val : SubtreeValues) {
    if (Runtime == GPURuntime::OpenCL)
      ArgSizes[Index] = computeSizeInBytes(Val->getType());

    Instruction *Param =
        new AllocaInst(Val->getType(), AddressSpace,
                       Launch + "_param_" + std::to_string(Index),
                       EntryBlock->getTerminator());
    Builder.CreateStore(Val, Param);
    insertStoreParameter(Parameters, Param, Index);
    Index++;
  }

  if (Runtime == GPURuntime::OpenCL) {
    for (int i = 0; i < NumArgs; i++) {
      Value *Val = ConstantInt::get(Builder.getInt32Ty(), ArgSizes[i]);
      Instruction *Param =
          new AllocaInst(Builder.getInt32Ty(), AddressSpace,
                         Launch + "_param_size_" + std::to_string(i),
                         EntryBlock->getTerminator());
      Builder.CreateStore(Val, Param);
      insertStoreParameter(Parameters, Param, Index);
      Index++;
    }
  }

  auto Location = EntryBlock->getTerminator();
  return new BitCastInst(Parameters, Builder.getInt8PtrTy(),
                         Launch + "_params_i8ptr", Location);
}

void GPUNodeBuilder::setupKernelSubtreeFunctions(
    SetVector<Function *> SubtreeFunctions) {
  for (auto Fn : SubtreeFunctions) {
    const std::string ClonedFnName = Fn->getName().str();
    Function *Clone = GPUModule->getFunction(ClonedFnName);
    if (!Clone)
      Clone =
          Function::Create(Fn->getFunctionType(), GlobalValue::ExternalLinkage,
                           ClonedFnName, GPUModule.get());
    assert(Clone && "Expected cloned function to be initialized.");
    assert(ValueMap.find(Fn) == ValueMap.end() &&
           "Fn already present in ValueMap");
    ValueMap[Fn] = Clone;
  }
}
void GPUNodeBuilder::createKernel(__isl_take isl_ast_node *KernelStmt) {
  isl_id *Id = isl_ast_node_get_annotation(KernelStmt);
  ppcg_kernel *Kernel = (ppcg_kernel *)isl_id_get_user(Id);
  isl_id_free(Id);
  isl_ast_node_free(KernelStmt);

  if (Kernel->n_grid > 1)
    DeepestParallel = std::max(
        DeepestParallel, (unsigned)isl_space_dim(Kernel->space, isl_dim_set));
  else
    DeepestSequential = std::max(
        DeepestSequential, (unsigned)isl_space_dim(Kernel->space, isl_dim_set));

  Value *BlockDimX, *BlockDimY, *BlockDimZ;
  std::tie(BlockDimX, BlockDimY, BlockDimZ) = getBlockSizes(Kernel);

  SetVector<Value *> SubtreeValues;
  SetVector<Function *> SubtreeFunctions;
  SetVector<const Loop *> Loops;
  isl::space ParamSpace;
  std::tie(SubtreeValues, SubtreeFunctions, Loops, ParamSpace) =
      getReferencesInKernel(Kernel);

  // Add parameters that appear only in the access function to the kernel
  // space. This is important to make sure that all isl_ids are passed as
  // parameters to the kernel, even though we may not have all parameters
  // in the context to improve compile time.
  Kernel->space = isl_space_align_params(Kernel->space, ParamSpace.release());

  assert(Kernel->tree && "Device AST of kernel node is empty");

  Instruction &HostInsertPoint = *Builder.GetInsertPoint();
  IslExprBuilder::IDToValueTy HostIDs = IDToValue;
  ValueMapT HostValueMap = ValueMap;
  BlockGenerator::AllocaMapTy HostScalarMap = ScalarMap;
  ScalarMap.clear();
  BlockGenerator::EscapeUsersAllocaMapTy HostEscapeMap = EscapeMap;
  EscapeMap.clear();

  // Create for all loops we depend on values that contain the current loop
  // iteration. These values are necessary to generate code for SCEVs that
  // depend on such loops. As a result we need to pass them to the subfunction.
  for (const Loop *L : Loops) {
    const SCEV *OuterLIV = SE.getAddRecExpr(SE.getUnknown(Builder.getInt64(0)),
                                            SE.getUnknown(Builder.getInt64(1)),
                                            L, SCEV::FlagAnyWrap);
    Value *V = generateSCEV(OuterLIV);
    OutsideLoopIterations[L] = SE.getUnknown(V);
    SubtreeValues.insert(V);
  }

  createKernelFunction(Kernel, SubtreeValues, SubtreeFunctions);
  setupKernelSubtreeFunctions(SubtreeFunctions);

  create(isl_ast_node_copy(Kernel->tree));

  finalizeKernelArguments(Kernel);
  Function *F = Builder.GetInsertBlock()->getParent();
  if (Arch == GPUArch::NVPTX64)
    addCUDAAnnotations(F->getParent(), BlockDimX, BlockDimY, BlockDimZ);
  clearDominators(F);
  clearScalarEvolution(F);
  clearLoops(F);

  IDToValue = HostIDs;

  ValueMap = std::move(HostValueMap);
  ScalarMap = std::move(HostScalarMap);
  EscapeMap = std::move(HostEscapeMap);
  IDToSAI.clear();
  Annotator.resetAlternativeAliasBases();
  for (auto &BasePtr : LocalArrays)
    S.invalidateScopArrayInfo(BasePtr, MemoryKind::Array);
  LocalArrays.clear();

  std::string ASMString = finalizeKernelFunction();
  Builder.SetInsertPoint(&HostInsertPoint);
  Value *Parameters = createLaunchParameters(Kernel, F, SubtreeValues);

  std::string Name = getKernelFuncName(Kernel->id);
  Value *KernelString = Builder.CreateGlobalStringPtr(ASMString, Name);
  Value *NameString = Builder.CreateGlobalStringPtr(Name, Name + "_name");
  Value *GPUKernel = createCallGetKernel(KernelString, NameString);

  Value *GridDimX, *GridDimY;
  std::tie(GridDimX, GridDimY) = getGridSizes(Kernel);

  createCallLaunchKernel(GPUKernel, GridDimX, GridDimY, BlockDimX, BlockDimY,
                         BlockDimZ, Parameters);
  createCallFreeKernel(GPUKernel);

  for (auto Id : KernelIds)
    isl_id_free(Id);

  KernelIds.clear();
}

/// Compute the DataLayout string for the NVPTX backend.
///
/// @param is64Bit Are we looking for a 64 bit architecture?
static std::string computeNVPTXDataLayout(bool is64Bit) {
  std::string Ret = "";

  if (!is64Bit) {
    Ret += "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:"
           "64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:"
           "64-v128:128:128-n16:32:64";
  } else {
    Ret += "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:"
           "64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:"
           "64-v128:128:128-n16:32:64";
  }

  return Ret;
}

/// Compute the DataLayout string for a SPIR kernel.
///
/// @param is64Bit Are we looking for a 64 bit architecture?
static std::string computeSPIRDataLayout(bool is64Bit) {
  std::string Ret = "";

  if (!is64Bit) {
    Ret += "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:"
           "64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:"
           "32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:"
           "256:256-v256:256:256-v512:512:512-v1024:1024:1024";
  } else {
    Ret += "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:"
           "64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:"
           "32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:"
           "256:256-v256:256:256-v512:512:512-v1024:1024:1024";
  }

  return Ret;
}

Function *
GPUNodeBuilder::createKernelFunctionDecl(ppcg_kernel *Kernel,
                                         SetVector<Value *> &SubtreeValues) {
  std::vector<Type *> Args;
  std::string Identifier = getKernelFuncName(Kernel->id);

  std::vector<Metadata *> MemoryType;

  for (long i = 0; i < Prog->n_array; i++) {
    if (!ppcg_kernel_requires_array_argument(Kernel, i))
      continue;

    if (gpu_array_is_read_only_scalar(&Prog->array[i])) {
      isl_id *Id = isl_space_get_tuple_id(Prog->array[i].space, isl_dim_set);
      const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(isl::manage(Id));
      Args.push_back(SAI->getElementType());
      MemoryType.push_back(
          ConstantAsMetadata::get(ConstantInt::get(Builder.getInt32Ty(), 0)));
    } else {
      static const int UseGlobalMemory = 1;
      Args.push_back(Builder.getInt8PtrTy(UseGlobalMemory));
      MemoryType.push_back(
          ConstantAsMetadata::get(ConstantInt::get(Builder.getInt32Ty(), 1)));
    }
  }

  int NumHostIters = isl_space_dim(Kernel->space, isl_dim_set);

  for (long i = 0; i < NumHostIters; i++) {
    Args.push_back(Builder.getInt64Ty());
    MemoryType.push_back(
        ConstantAsMetadata::get(ConstantInt::get(Builder.getInt32Ty(), 0)));
  }

  int NumVars = isl_space_dim(Kernel->space, isl_dim_param);

  for (long i = 0; i < NumVars; i++) {
    isl_id *Id = isl_space_get_dim_id(Kernel->space, isl_dim_param, i);
    Value *Val = IDToValue[Id];
    isl_id_free(Id);
    Args.push_back(Val->getType());
    MemoryType.push_back(
        ConstantAsMetadata::get(ConstantInt::get(Builder.getInt32Ty(), 0)));
  }

  for (auto *V : SubtreeValues) {
    Args.push_back(V->getType());
    MemoryType.push_back(
        ConstantAsMetadata::get(ConstantInt::get(Builder.getInt32Ty(), 0)));
  }

  auto *FT = FunctionType::get(Builder.getVoidTy(), Args, false);
  auto *FN = Function::Create(FT, Function::ExternalLinkage, Identifier,
                              GPUModule.get());

  std::vector<Metadata *> EmptyStrings;

  for (unsigned int i = 0; i < MemoryType.size(); i++) {
    EmptyStrings.push_back(MDString::get(FN->getContext(), ""));
  }

  if (Arch == GPUArch::SPIR32 || Arch == GPUArch::SPIR64) {
    FN->setMetadata("kernel_arg_addr_space",
                    MDNode::get(FN->getContext(), MemoryType));
    FN->setMetadata("kernel_arg_name",
                    MDNode::get(FN->getContext(), EmptyStrings));
    FN->setMetadata("kernel_arg_access_qual",
                    MDNode::get(FN->getContext(), EmptyStrings));
    FN->setMetadata("kernel_arg_type",
                    MDNode::get(FN->getContext(), EmptyStrings));
    FN->setMetadata("kernel_arg_type_qual",
                    MDNode::get(FN->getContext(), EmptyStrings));
    FN->setMetadata("kernel_arg_base_type",
                    MDNode::get(FN->getContext(), EmptyStrings));
  }

  switch (Arch) {
  case GPUArch::NVPTX64:
    FN->setCallingConv(CallingConv::PTX_Kernel);
    break;
  case GPUArch::SPIR32:
  case GPUArch::SPIR64:
    FN->setCallingConv(CallingConv::SPIR_KERNEL);
    break;
  }

  auto Arg = FN->arg_begin();
  for (long i = 0; i < Kernel->n_array; i++) {
    if (!ppcg_kernel_requires_array_argument(Kernel, i))
      continue;

    Arg->setName(Kernel->array[i].array->name);

    isl_id *Id = isl_space_get_tuple_id(Prog->array[i].space, isl_dim_set);
    const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(isl::manage_copy(Id));
    Type *EleTy = SAI->getElementType();
    Value *Val = &*Arg;
    SmallVector<const SCEV *, 4> Sizes;
    isl_ast_build *Build =
        isl_ast_build_from_context(isl_set_copy(Prog->context));
    Sizes.push_back(nullptr);
    for (long j = 1, n = Kernel->array[i].array->n_index; j < n; j++) {
      isl_ast_expr *DimSize = isl_ast_build_expr_from_pw_aff(
          Build, isl_multi_pw_aff_get_pw_aff(Kernel->array[i].array->bound, j));
      auto V = ExprBuilder.create(DimSize);
      Sizes.push_back(SE.getSCEV(V));
    }
    const ScopArrayInfo *SAIRep =
        S.getOrCreateScopArrayInfo(Val, EleTy, Sizes, MemoryKind::Array);
    LocalArrays.push_back(Val);

    isl_ast_build_free(Build);
    KernelIds.push_back(Id);
    IDToSAI[Id] = SAIRep;
    Arg++;
  }

  for (long i = 0; i < NumHostIters; i++) {
    isl_id *Id = isl_space_get_dim_id(Kernel->space, isl_dim_set, i);
    Arg->setName(isl_id_get_name(Id));
    IDToValue[Id] = &*Arg;
    KernelIDs.insert(std::unique_ptr<isl_id, IslIdDeleter>(Id));
    Arg++;
  }

  for (long i = 0; i < NumVars; i++) {
    isl_id *Id = isl_space_get_dim_id(Kernel->space, isl_dim_param, i);
    Arg->setName(isl_id_get_name(Id));
    Value *Val = IDToValue[Id];
    ValueMap[Val] = &*Arg;
    IDToValue[Id] = &*Arg;
    KernelIDs.insert(std::unique_ptr<isl_id, IslIdDeleter>(Id));
    Arg++;
  }

  for (auto *V : SubtreeValues) {
    Arg->setName(V->getName());
    ValueMap[V] = &*Arg;
    Arg++;
  }

  return FN;
}

void GPUNodeBuilder::insertKernelIntrinsics(ppcg_kernel *Kernel) {
  Intrinsic::ID IntrinsicsBID[2];
  Intrinsic::ID IntrinsicsTID[3];

  switch (Arch) {
  case GPUArch::SPIR64:
  case GPUArch::SPIR32:
    llvm_unreachable("Cannot generate NVVM intrinsics for SPIR");
  case GPUArch::NVPTX64:
    IntrinsicsBID[0] = Intrinsic::nvvm_read_ptx_sreg_ctaid_x;
    IntrinsicsBID[1] = Intrinsic::nvvm_read_ptx_sreg_ctaid_y;

    IntrinsicsTID[0] = Intrinsic::nvvm_read_ptx_sreg_tid_x;
    IntrinsicsTID[1] = Intrinsic::nvvm_read_ptx_sreg_tid_y;
    IntrinsicsTID[2] = Intrinsic::nvvm_read_ptx_sreg_tid_z;
    break;
  }

  auto addId = [this](__isl_take isl_id *Id, Intrinsic::ID Intr) mutable {
    std::string Name = isl_id_get_name(Id);
    Module *M = Builder.GetInsertBlock()->getParent()->getParent();
    Function *IntrinsicFn = Intrinsic::getDeclaration(M, Intr);
    Value *Val = Builder.CreateCall(IntrinsicFn, {});
    Val = Builder.CreateIntCast(Val, Builder.getInt64Ty(), false, Name);
    IDToValue[Id] = Val;
    KernelIDs.insert(std::unique_ptr<isl_id, IslIdDeleter>(Id));
  };

  for (int i = 0; i < Kernel->n_grid; ++i) {
    isl_id *Id = isl_id_list_get_id(Kernel->block_ids, i);
    addId(Id, IntrinsicsBID[i]);
  }

  for (int i = 0; i < Kernel->n_block; ++i) {
    isl_id *Id = isl_id_list_get_id(Kernel->thread_ids, i);
    addId(Id, IntrinsicsTID[i]);
  }
}

void GPUNodeBuilder::insertKernelCallsSPIR(ppcg_kernel *Kernel,
                                           bool SizeTypeIs64bit) {
  const char *GroupName[3] = {"__gen_ocl_get_group_id0",
                              "__gen_ocl_get_group_id1",
                              "__gen_ocl_get_group_id2"};

  const char *LocalName[3] = {"__gen_ocl_get_local_id0",
                              "__gen_ocl_get_local_id1",
                              "__gen_ocl_get_local_id2"};
  IntegerType *SizeT =
      SizeTypeIs64bit ? Builder.getInt64Ty() : Builder.getInt32Ty();

  auto createFunc = [this](const char *Name, __isl_take isl_id *Id,
                           IntegerType *SizeT) mutable {
    Module *M = Builder.GetInsertBlock()->getParent()->getParent();
    Function *FN = M->getFunction(Name);

    // If FN is not available, declare it.
    if (!FN) {
      GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
      std::vector<Type *> Args;
      FunctionType *Ty = FunctionType::get(SizeT, Args, false);
      FN = Function::Create(Ty, Linkage, Name, M);
      FN->setCallingConv(CallingConv::SPIR_FUNC);
    }

    Value *Val = Builder.CreateCall(FN, {});
    if (SizeT == Builder.getInt32Ty())
      Val = Builder.CreateIntCast(Val, Builder.getInt64Ty(), false, Name);
    IDToValue[Id] = Val;
    KernelIDs.insert(std::unique_ptr<isl_id, IslIdDeleter>(Id));
  };

  for (int i = 0; i < Kernel->n_grid; ++i)
    createFunc(GroupName[i], isl_id_list_get_id(Kernel->block_ids, i), SizeT);

  for (int i = 0; i < Kernel->n_block; ++i)
    createFunc(LocalName[i], isl_id_list_get_id(Kernel->thread_ids, i), SizeT);
}

void GPUNodeBuilder::prepareKernelArguments(ppcg_kernel *Kernel, Function *FN) {
  auto Arg = FN->arg_begin();
  for (long i = 0; i < Kernel->n_array; i++) {
    if (!ppcg_kernel_requires_array_argument(Kernel, i))
      continue;

    isl_id *Id = isl_space_get_tuple_id(Prog->array[i].space, isl_dim_set);
    const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(isl::manage_copy(Id));
    isl_id_free(Id);

    if (SAI->getNumberOfDimensions() > 0) {
      Arg++;
      continue;
    }

    Value *Val = &*Arg;

    if (!gpu_array_is_read_only_scalar(&Prog->array[i])) {
      Type *TypePtr = SAI->getElementType()->getPointerTo();
      Value *TypedArgPtr = Builder.CreatePointerCast(Val, TypePtr);
      Val = Builder.CreateLoad(SAI->getElementType(), TypedArgPtr);
    }

    Value *Alloca = BlockGen.getOrCreateAlloca(SAI);
    Builder.CreateStore(Val, Alloca);

    Arg++;
  }
}

void GPUNodeBuilder::finalizeKernelArguments(ppcg_kernel *Kernel) {
  auto *FN = Builder.GetInsertBlock()->getParent();
  auto Arg = FN->arg_begin();

  bool StoredScalar = false;
  for (long i = 0; i < Kernel->n_array; i++) {
    if (!ppcg_kernel_requires_array_argument(Kernel, i))
      continue;

    isl_id *Id = isl_space_get_tuple_id(Prog->array[i].space, isl_dim_set);
    const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(isl::manage_copy(Id));
    isl_id_free(Id);

    if (SAI->getNumberOfDimensions() > 0) {
      Arg++;
      continue;
    }

    if (gpu_array_is_read_only_scalar(&Prog->array[i])) {
      Arg++;
      continue;
    }

    Value *Alloca = BlockGen.getOrCreateAlloca(SAI);
    Value *ArgPtr = &*Arg;
    Type *TypePtr = SAI->getElementType()->getPointerTo();
    Value *TypedArgPtr = Builder.CreatePointerCast(ArgPtr, TypePtr);
    Value *Val = Builder.CreateLoad(SAI->getElementType(), Alloca);
    Builder.CreateStore(Val, TypedArgPtr);
    StoredScalar = true;

    Arg++;
  }

  if (StoredScalar) {
    /// In case more than one thread contains scalar stores, the generated
    /// code might be incorrect, if we only store at the end of the kernel.
    /// To support this case we need to store these scalars back at each
    /// memory store or at least before each kernel barrier.
    if (Kernel->n_block != 0 || Kernel->n_grid != 0) {
      BuildSuccessful = 0;
      LLVM_DEBUG(
          dbgs() << getUniqueScopName(&S)
                 << " has a store to a scalar value that"
                    " would be undefined to run in parallel. Bailing out.\n";);
    }
  }
}

void GPUNodeBuilder::createKernelVariables(ppcg_kernel *Kernel, Function *FN) {
  Module *M = Builder.GetInsertBlock()->getParent()->getParent();

  for (int i = 0; i < Kernel->n_var; ++i) {
    struct ppcg_kernel_var &Var = Kernel->var[i];
    isl_id *Id = isl_space_get_tuple_id(Var.array->space, isl_dim_set);
    Type *EleTy = ScopArrayInfo::getFromId(isl::manage(Id))->getElementType();

    Type *ArrayTy = EleTy;
    SmallVector<const SCEV *, 4> Sizes;

    Sizes.push_back(nullptr);
    for (unsigned int j = 1; j < Var.array->n_index; ++j) {
      isl_val *Val = isl_vec_get_element_val(Var.size, j);
      long Bound = isl_val_get_num_si(Val);
      isl_val_free(Val);
      Sizes.push_back(S.getSE()->getConstant(Builder.getInt64Ty(), Bound));
    }

    for (int j = Var.array->n_index - 1; j >= 0; --j) {
      isl_val *Val = isl_vec_get_element_val(Var.size, j);
      long Bound = isl_val_get_num_si(Val);
      isl_val_free(Val);
      ArrayTy = ArrayType::get(ArrayTy, Bound);
    }

    const ScopArrayInfo *SAI;
    Value *Allocation;
    if (Var.type == ppcg_access_shared) {
      auto GlobalVar = new GlobalVariable(
          *M, ArrayTy, false, GlobalValue::InternalLinkage, 0, Var.name,
          nullptr, GlobalValue::ThreadLocalMode::NotThreadLocal, 3);
      GlobalVar->setAlignment(llvm::Align(EleTy->getPrimitiveSizeInBits() / 8));
      GlobalVar->setInitializer(Constant::getNullValue(ArrayTy));

      Allocation = GlobalVar;
    } else if (Var.type == ppcg_access_private) {
      Allocation = Builder.CreateAlloca(ArrayTy, 0, "private_array");
    } else {
      llvm_unreachable("unknown variable type");
    }
    SAI =
        S.getOrCreateScopArrayInfo(Allocation, EleTy, Sizes, MemoryKind::Array);
    Id = isl_id_alloc(S.getIslCtx().get(), Var.name, nullptr);
    IDToValue[Id] = Allocation;
    LocalArrays.push_back(Allocation);
    KernelIds.push_back(Id);
    IDToSAI[Id] = SAI;
  }
}

void GPUNodeBuilder::createKernelFunction(
    ppcg_kernel *Kernel, SetVector<Value *> &SubtreeValues,
    SetVector<Function *> &SubtreeFunctions) {
  std::string Identifier = getKernelFuncName(Kernel->id);
  GPUModule.reset(new Module(Identifier, Builder.getContext()));

  switch (Arch) {
  case GPUArch::NVPTX64:
    if (Runtime == GPURuntime::CUDA)
      GPUModule->setTargetTriple(Triple::normalize("nvptx64-nvidia-cuda"));
    else if (Runtime == GPURuntime::OpenCL)
      GPUModule->setTargetTriple(Triple::normalize("nvptx64-nvidia-nvcl"));
    GPUModule->setDataLayout(computeNVPTXDataLayout(true /* is64Bit */));
    break;
  case GPUArch::SPIR32:
    GPUModule->setTargetTriple(Triple::normalize("spir-unknown-unknown"));
    GPUModule->setDataLayout(computeSPIRDataLayout(false /* is64Bit */));
    break;
  case GPUArch::SPIR64:
    GPUModule->setTargetTriple(Triple::normalize("spir64-unknown-unknown"));
    GPUModule->setDataLayout(computeSPIRDataLayout(true /* is64Bit */));
    break;
  }

  Function *FN = createKernelFunctionDecl(Kernel, SubtreeValues);

  BasicBlock *PrevBlock = Builder.GetInsertBlock();
  auto EntryBlock = BasicBlock::Create(Builder.getContext(), "entry", FN);

  DT.addNewBlock(EntryBlock, PrevBlock);

  Builder.SetInsertPoint(EntryBlock);
  Builder.CreateRetVoid();
  Builder.SetInsertPoint(EntryBlock, EntryBlock->begin());

  ScopDetection::markFunctionAsInvalid(FN);

  prepareKernelArguments(Kernel, FN);
  createKernelVariables(Kernel, FN);

  switch (Arch) {
  case GPUArch::NVPTX64:
    insertKernelIntrinsics(Kernel);
    break;
  case GPUArch::SPIR32:
    insertKernelCallsSPIR(Kernel, false);
    break;
  case GPUArch::SPIR64:
    insertKernelCallsSPIR(Kernel, true);
    break;
  }
}

std::string GPUNodeBuilder::createKernelASM() {
  llvm::Triple GPUTriple;

  switch (Arch) {
  case GPUArch::NVPTX64:
    switch (Runtime) {
    case GPURuntime::CUDA:
      GPUTriple = llvm::Triple(Triple::normalize("nvptx64-nvidia-cuda"));
      break;
    case GPURuntime::OpenCL:
      GPUTriple = llvm::Triple(Triple::normalize("nvptx64-nvidia-nvcl"));
      break;
    }
    break;
  case GPUArch::SPIR64:
  case GPUArch::SPIR32:
    std::string SPIRAssembly;
    raw_string_ostream IROstream(SPIRAssembly);
    IROstream << *GPUModule;
    IROstream.flush();
    return SPIRAssembly;
  }

  std::string ErrMsg;
  auto GPUTarget = TargetRegistry::lookupTarget(GPUTriple.getTriple(), ErrMsg);

  if (!GPUTarget) {
    errs() << ErrMsg << "\n";
    return "";
  }

  TargetOptions Options;
  Options.UnsafeFPMath = FastMath;

  std::string subtarget;

  switch (Arch) {
  case GPUArch::NVPTX64:
    subtarget = CudaVersion;
    break;
  case GPUArch::SPIR32:
  case GPUArch::SPIR64:
    llvm_unreachable("No subtarget for SPIR architecture");
  }

  std::unique_ptr<TargetMachine> TargetM(GPUTarget->createTargetMachine(
      GPUTriple.getTriple(), subtarget, "", Options, Optional<Reloc::Model>()));

  SmallString<0> ASMString;
  raw_svector_ostream ASMStream(ASMString);
  llvm::legacy::PassManager PM;

  PM.add(createTargetTransformInfoWrapperPass(TargetM->getTargetIRAnalysis()));

  if (TargetM->addPassesToEmitFile(PM, ASMStream, nullptr, CGFT_AssemblyFile,
                                   true /* verify */)) {
    errs() << "The target does not support generation of this file type!\n";
    return "";
  }

  PM.run(*GPUModule);

  return ASMStream.str().str();
}

bool GPUNodeBuilder::requiresCUDALibDevice() {
  bool RequiresLibDevice = false;
  for (Function &F : GPUModule->functions()) {
    if (!F.isDeclaration())
      continue;

    const std::string CUDALibDeviceFunc = getCUDALibDeviceFuntion(F.getName());
    if (CUDALibDeviceFunc.length() != 0) {
      // We need to handle the case where a module looks like this:
      // @expf(..)
      // @llvm.exp.f64(..)
      // Both of these functions would be renamed to `__nv_expf`.
      //
      // So, we must first check for the existence of the libdevice function.
      // If this exists, we replace our current function with it.
      //
      // If it does not exist, we rename the current function to the
      // libdevice functiono name.
      if (Function *Replacement = F.getParent()->getFunction(CUDALibDeviceFunc))
        F.replaceAllUsesWith(Replacement);
      else
        F.setName(CUDALibDeviceFunc);
      RequiresLibDevice = true;
    }
  }

  return RequiresLibDevice;
}

void GPUNodeBuilder::addCUDALibDevice() {
  if (Arch != GPUArch::NVPTX64)
    return;

  if (requiresCUDALibDevice()) {
    SMDiagnostic Error;

    errs() << CUDALibDevice << "\n";
    auto LibDeviceModule =
        parseIRFile(CUDALibDevice, Error, GPUModule->getContext());

    if (!LibDeviceModule) {
      BuildSuccessful = false;
      report_fatal_error("Could not find or load libdevice. Skipping GPU "
                         "kernel generation. Please set -polly-acc-libdevice "
                         "accordingly.\n");
      return;
    }

    Linker L(*GPUModule);

    // Set an nvptx64 target triple to avoid linker warnings. The original
    // triple of the libdevice files are nvptx-unknown-unknown.
    LibDeviceModule->setTargetTriple(Triple::normalize("nvptx64-nvidia-cuda"));
    L.linkInModule(std::move(LibDeviceModule), Linker::LinkOnlyNeeded);
  }
}

std::string GPUNodeBuilder::finalizeKernelFunction() {

  if (verifyModule(*GPUModule)) {
    LLVM_DEBUG(dbgs() << "verifyModule failed on module:\n";
               GPUModule->print(dbgs(), nullptr); dbgs() << "\n";);
    LLVM_DEBUG(dbgs() << "verifyModule Error:\n";
               verifyModule(*GPUModule, &dbgs()););

    if (FailOnVerifyModuleFailure)
      llvm_unreachable("VerifyModule failed.");

    BuildSuccessful = false;
    return "";
  }

  addCUDALibDevice();

  if (DumpKernelIR)
    outs() << *GPUModule << "\n";

  if (Arch != GPUArch::SPIR32 && Arch != GPUArch::SPIR64) {
    // Optimize module.
    llvm::legacy::PassManager OptPasses;
    PassManagerBuilder PassBuilder;
    PassBuilder.OptLevel = 3;
    PassBuilder.SizeLevel = 0;
    PassBuilder.populateModulePassManager(OptPasses);
    OptPasses.run(*GPUModule);
  }

  std::string Assembly = createKernelASM();

  if (DumpKernelASM)
    outs() << Assembly << "\n";

  GPUModule.release();
  KernelIDs.clear();

  return Assembly;
}
/// Construct an `isl_pw_aff_list` from a vector of `isl_pw_aff`
/// @param PwAffs The list of piecewise affine functions to create an
///               `isl_pw_aff_list` from. We expect an rvalue ref because
///               all the isl_pw_aff are used up by this function.
///
/// @returns  The `isl_pw_aff_list`.
__isl_give isl_pw_aff_list *
createPwAffList(isl_ctx *Context,
                const std::vector<__isl_take isl_pw_aff *> &&PwAffs) {
  isl_pw_aff_list *List = isl_pw_aff_list_alloc(Context, PwAffs.size());

  for (unsigned i = 0; i < PwAffs.size(); i++) {
    List = isl_pw_aff_list_insert(List, i, PwAffs[i]);
  }
  return List;
}

/// Align all the `PwAffs` such that they have the same parameter dimensions.
///
/// We loop over all `pw_aff` and align all of their spaces together to
/// create a common space for all the `pw_aff`. This common space is the
/// `AlignSpace`. We then align all the `pw_aff` to this space. We start
/// with the given `SeedSpace`.
/// @param PwAffs    The list of piecewise affine functions we want to align.
///                  This is an rvalue reference because the entire vector is
///                  used up by the end of the operation.
/// @param SeedSpace The space to start the alignment process with.
/// @returns         A std::pair, whose first element is the aligned space,
///                  whose second element is the vector of aligned piecewise
///                  affines.
static std::pair<__isl_give isl_space *, std::vector<__isl_give isl_pw_aff *>>
alignPwAffs(const std::vector<__isl_take isl_pw_aff *> &&PwAffs,
            __isl_take isl_space *SeedSpace) {
  assert(SeedSpace && "Invalid seed space given.");

  isl_space *AlignSpace = SeedSpace;
  for (isl_pw_aff *PwAff : PwAffs) {
    isl_space *PwAffSpace = isl_pw_aff_get_domain_space(PwAff);
    AlignSpace = isl_space_align_params(AlignSpace, PwAffSpace);
  }
  std::vector<isl_pw_aff *> AdjustedPwAffs;

  for (unsigned i = 0; i < PwAffs.size(); i++) {
    isl_pw_aff *Adjusted = PwAffs[i];
    assert(Adjusted && "Invalid pw_aff given.");
    Adjusted = isl_pw_aff_align_params(Adjusted, isl_space_copy(AlignSpace));
    AdjustedPwAffs.push_back(Adjusted);
  }
  return std::make_pair(AlignSpace, AdjustedPwAffs);
}

namespace {
class PPCGCodeGeneration : public ScopPass {
public:
  static char ID;

  GPURuntime Runtime = GPURuntime::CUDA;

  GPUArch Architecture = GPUArch::NVPTX64;

  /// The scop that is currently processed.
  Scop *S;

  LoopInfo *LI;
  DominatorTree *DT;
  ScalarEvolution *SE;
  const DataLayout *DL;
  RegionInfo *RI;

  PPCGCodeGeneration() : ScopPass(ID) {
    // Apply defaults.
    Runtime = GPURuntimeChoice;
    Architecture = GPUArchChoice;
  }

  /// Construct compilation options for PPCG.
  ///
  /// @returns The compilation options.
  ppcg_options *createPPCGOptions() {
    auto DebugOptions =
        (ppcg_debug_options *)malloc(sizeof(ppcg_debug_options));
    auto Options = (ppcg_options *)malloc(sizeof(ppcg_options));

    DebugOptions->dump_schedule_constraints = false;
    DebugOptions->dump_schedule = false;
    DebugOptions->dump_final_schedule = false;
    DebugOptions->dump_sizes = false;
    DebugOptions->verbose = false;

    Options->debug = DebugOptions;

    Options->group_chains = false;
    Options->reschedule = true;
    Options->scale_tile_loops = false;
    Options->wrap = false;

    Options->non_negative_parameters = false;
    Options->ctx = nullptr;
    Options->sizes = nullptr;

    Options->tile = true;
    Options->tile_size = 32;

    Options->isolate_full_tiles = false;

    Options->use_private_memory = PrivateMemory;
    Options->use_shared_memory = SharedMemory;
    Options->max_shared_memory = 48 * 1024;

    Options->target = PPCG_TARGET_CUDA;
    Options->openmp = false;
    Options->linearize_device_arrays = true;
    Options->allow_gnu_extensions = false;

    Options->unroll_copy_shared = false;
    Options->unroll_gpu_tile = false;
    Options->live_range_reordering = true;

    Options->live_range_reordering = true;
    Options->hybrid = false;
    Options->opencl_compiler_options = nullptr;
    Options->opencl_use_gpu = false;
    Options->opencl_n_include_file = 0;
    Options->opencl_include_files = nullptr;
    Options->opencl_print_kernel_types = false;
    Options->opencl_embed_kernel_code = false;

    Options->save_schedule_file = nullptr;
    Options->load_schedule_file = nullptr;

    return Options;
  }

  /// Get a tagged access relation containing all accesses of type @p AccessTy.
  ///
  /// Instead of a normal access of the form:
  ///
  ///   Stmt[i,j,k] -> Array[f_0(i,j,k), f_1(i,j,k)]
  ///
  /// a tagged access has the form
  ///
  ///   [Stmt[i,j,k] -> id[]] -> Array[f_0(i,j,k), f_1(i,j,k)]
  ///
  /// where 'id' is an additional space that references the memory access that
  /// triggered the access.
  ///
  /// @param AccessTy The type of the memory accesses to collect.
  ///
  /// @return The relation describing all tagged memory accesses.
  isl_union_map *getTaggedAccesses(enum MemoryAccess::AccessType AccessTy) {
    isl_union_map *Accesses = isl_union_map_empty(S->getParamSpace().release());

    for (auto &Stmt : *S)
      for (auto &Acc : Stmt)
        if (Acc->getType() == AccessTy) {
          isl_map *Relation = Acc->getAccessRelation().release();
          Relation =
              isl_map_intersect_domain(Relation, Stmt.getDomain().release());

          isl_space *Space = isl_map_get_space(Relation);
          Space = isl_space_range(Space);
          Space = isl_space_from_range(Space);
          Space =
              isl_space_set_tuple_id(Space, isl_dim_in, Acc->getId().release());
          isl_map *Universe = isl_map_universe(Space);
          Relation = isl_map_domain_product(Relation, Universe);
          Accesses = isl_union_map_add_map(Accesses, Relation);
        }

    return Accesses;
  }

  /// Get the set of all read accesses, tagged with the access id.
  ///
  /// @see getTaggedAccesses
  isl_union_map *getTaggedReads() {
    return getTaggedAccesses(MemoryAccess::READ);
  }

  /// Get the set of all may (and must) accesses, tagged with the access id.
  ///
  /// @see getTaggedAccesses
  isl_union_map *getTaggedMayWrites() {
    return isl_union_map_union(getTaggedAccesses(MemoryAccess::MAY_WRITE),
                               getTaggedAccesses(MemoryAccess::MUST_WRITE));
  }

  /// Get the set of all must accesses, tagged with the access id.
  ///
  /// @see getTaggedAccesses
  isl_union_map *getTaggedMustWrites() {
    return getTaggedAccesses(MemoryAccess::MUST_WRITE);
  }

  /// Collect parameter and array names as isl_ids.
  ///
  /// To reason about the different parameters and arrays used, ppcg requires
  /// a list of all isl_ids in use. As PPCG traditionally performs
  /// source-to-source compilation each of these isl_ids is mapped to the
  /// expression that represents it. As we do not have a corresponding
  /// expression in Polly, we just map each id to a 'zero' expression to match
  /// the data format that ppcg expects.
  ///
  /// @returns Retun a map from collected ids to 'zero' ast expressions.
  __isl_give isl_id_to_ast_expr *getNames() {
    auto *Names = isl_id_to_ast_expr_alloc(
        S->getIslCtx().get(),
        S->getNumParams() + std::distance(S->array_begin(), S->array_end()));
    auto *Zero = isl_ast_expr_from_val(isl_val_zero(S->getIslCtx().get()));

    for (const SCEV *P : S->parameters()) {
      isl_id *Id = S->getIdForParam(P).release();
      Names = isl_id_to_ast_expr_set(Names, Id, isl_ast_expr_copy(Zero));
    }

    for (auto &Array : S->arrays()) {
      auto Id = Array->getBasePtrId().release();
      Names = isl_id_to_ast_expr_set(Names, Id, isl_ast_expr_copy(Zero));
    }

    isl_ast_expr_free(Zero);

    return Names;
  }

  /// Create a new PPCG scop from the current scop.
  ///
  /// The PPCG scop is initialized with data from the current polly::Scop. From
  /// this initial data, the data-dependences in the PPCG scop are initialized.
  /// We do not use Polly's dependence analysis for now, to ensure we match
  /// the PPCG default behaviour more closely.
  ///
  /// @returns A new ppcg scop.
  ppcg_scop *createPPCGScop() {
    MustKillsInfo KillsInfo = computeMustKillsInfo(*S);

    auto PPCGScop = (ppcg_scop *)malloc(sizeof(ppcg_scop));

    PPCGScop->options = createPPCGOptions();
    // enable live range reordering
    PPCGScop->options->live_range_reordering = 1;

    PPCGScop->start = 0;
    PPCGScop->end = 0;

    PPCGScop->context = S->getContext().release();
    PPCGScop->domain = S->getDomains().release();
    // TODO: investigate this further. PPCG calls collect_call_domains.
    PPCGScop->call = isl_union_set_from_set(S->getContext().release());
    PPCGScop->tagged_reads = getTaggedReads();
    PPCGScop->reads = S->getReads().release();
    PPCGScop->live_in = nullptr;
    PPCGScop->tagged_may_writes = getTaggedMayWrites();
    PPCGScop->may_writes = S->getWrites().release();
    PPCGScop->tagged_must_writes = getTaggedMustWrites();
    PPCGScop->must_writes = S->getMustWrites().release();
    PPCGScop->live_out = nullptr;
    PPCGScop->tagged_must_kills = KillsInfo.TaggedMustKills.release();
    PPCGScop->must_kills = KillsInfo.MustKills.release();

    PPCGScop->tagger = nullptr;
    PPCGScop->independence =
        isl_union_map_empty(isl_set_get_space(PPCGScop->context));
    PPCGScop->dep_flow = nullptr;
    PPCGScop->tagged_dep_flow = nullptr;
    PPCGScop->dep_false = nullptr;
    PPCGScop->dep_forced = nullptr;
    PPCGScop->dep_order = nullptr;
    PPCGScop->tagged_dep_order = nullptr;

    PPCGScop->schedule = S->getScheduleTree().release();
    // If we have something non-trivial to kill, add it to the schedule
    if (KillsInfo.KillsSchedule.get())
      PPCGScop->schedule = isl_schedule_sequence(
          PPCGScop->schedule, KillsInfo.KillsSchedule.release());

    PPCGScop->names = getNames();
    PPCGScop->pet = nullptr;

    compute_tagger(PPCGScop);
    compute_dependences(PPCGScop);
    eliminate_dead_code(PPCGScop);

    return PPCGScop;
  }

  /// Collect the array accesses in a statement.
  ///
  /// @param Stmt The statement for which to collect the accesses.
  ///
  /// @returns A list of array accesses.
  gpu_stmt_access *getStmtAccesses(ScopStmt &Stmt) {
    gpu_stmt_access *Accesses = nullptr;

    for (MemoryAccess *Acc : Stmt) {
      auto Access =
          isl_alloc_type(S->getIslCtx().get(), struct gpu_stmt_access);
      Access->read = Acc->isRead();
      Access->write = Acc->isWrite();
      Access->access = Acc->getAccessRelation().release();
      isl_space *Space = isl_map_get_space(Access->access);
      Space = isl_space_range(Space);
      Space = isl_space_from_range(Space);
      Space = isl_space_set_tuple_id(Space, isl_dim_in, Acc->getId().release());
      isl_map *Universe = isl_map_universe(Space);
      Access->tagged_access =
          isl_map_domain_product(Acc->getAccessRelation().release(), Universe);
      Access->exact_write = !Acc->isMayWrite();
      Access->ref_id = Acc->getId().release();
      Access->next = Accesses;
      Access->n_index = Acc->getScopArrayInfo()->getNumberOfDimensions();
      // TODO: Also mark one-element accesses to arrays as fixed-element.
      Access->fixed_element =
          Acc->isLatestScalarKind() ? isl_bool_true : isl_bool_false;
      Accesses = Access;
    }

    return Accesses;
  }

  /// Collect the list of GPU statements.
  ///
  /// Each statement has an id, a pointer to the underlying data structure,
  /// as well as a list with all memory accesses.
  ///
  /// TODO: Initialize the list of memory accesses.
  ///
  /// @returns A linked-list of statements.
  gpu_stmt *getStatements() {
    gpu_stmt *Stmts = isl_calloc_array(S->getIslCtx().get(), struct gpu_stmt,
                                       std::distance(S->begin(), S->end()));

    int i = 0;
    for (auto &Stmt : *S) {
      gpu_stmt *GPUStmt = &Stmts[i];

      GPUStmt->id = Stmt.getDomainId().release();

      // We use the pet stmt pointer to keep track of the Polly statements.
      GPUStmt->stmt = (pet_stmt *)&Stmt;
      GPUStmt->accesses = getStmtAccesses(Stmt);
      i++;
    }

    return Stmts;
  }

  /// Derive the extent of an array.
  ///
  /// The extent of an array is the set of elements that are within the
  /// accessed array. For the inner dimensions, the extent constraints are
  /// 0 and the size of the corresponding array dimension. For the first
  /// (outermost) dimension, the extent constraints are the minimal and maximal
  /// subscript value for the first dimension.
  ///
  /// @param Array The array to derive the extent for.
  ///
  /// @returns An isl_set describing the extent of the array.
  isl::set getExtent(ScopArrayInfo *Array) {
    unsigned NumDims = Array->getNumberOfDimensions();

    if (Array->getNumberOfDimensions() == 0)
      return isl::set::universe(Array->getSpace());

    isl::union_map Accesses = S->getAccesses(Array);
    isl::union_set AccessUSet = Accesses.range();
    AccessUSet = AccessUSet.coalesce();
    AccessUSet = AccessUSet.detect_equalities();
    AccessUSet = AccessUSet.coalesce();

    if (AccessUSet.is_empty())
      return isl::set::empty(Array->getSpace());

    isl::set AccessSet = AccessUSet.extract_set(Array->getSpace());

    isl::local_space LS = isl::local_space(Array->getSpace());

    isl::pw_aff Val = isl::aff::var_on_domain(LS, isl::dim::set, 0);
    isl::pw_aff OuterMin = AccessSet.dim_min(0);
    isl::pw_aff OuterMax = AccessSet.dim_max(0);
    OuterMin = OuterMin.add_dims(isl::dim::in, Val.dim(isl::dim::in));
    OuterMax = OuterMax.add_dims(isl::dim::in, Val.dim(isl::dim::in));
    OuterMin = OuterMin.set_tuple_id(isl::dim::in, Array->getBasePtrId());
    OuterMax = OuterMax.set_tuple_id(isl::dim::in, Array->getBasePtrId());

    isl::set Extent = isl::set::universe(Array->getSpace());

    Extent = Extent.intersect(OuterMin.le_set(Val));
    Extent = Extent.intersect(OuterMax.ge_set(Val));

    for (unsigned i = 1; i < NumDims; ++i)
      Extent = Extent.lower_bound_si(isl::dim::set, i, 0);

    for (unsigned i = 0; i < NumDims; ++i) {
      isl::pw_aff PwAff = Array->getDimensionSizePw(i);

      // isl_pw_aff can be NULL for zero dimension. Only in the case of a
      // Fortran array will we have a legitimate dimension.
      if (PwAff.is_null()) {
        assert(i == 0 && "invalid dimension isl_pw_aff for nonzero dimension");
        continue;
      }

      isl::pw_aff Val = isl::aff::var_on_domain(
          isl::local_space(Array->getSpace()), isl::dim::set, i);
      PwAff = PwAff.add_dims(isl::dim::in, Val.dim(isl::dim::in));
      PwAff = PwAff.set_tuple_id(isl::dim::in, Val.get_tuple_id(isl::dim::in));
      isl::set Set = PwAff.gt_set(Val);
      Extent = Set.intersect(Extent);
    }

    return Extent;
  }

  /// Derive the bounds of an array.
  ///
  /// For the first dimension we derive the bound of the array from the extent
  /// of this dimension. For inner dimensions we obtain their size directly from
  /// ScopArrayInfo.
  ///
  /// @param PPCGArray The array to compute bounds for.
  /// @param Array The polly array from which to take the information.
  void setArrayBounds(gpu_array_info &PPCGArray, ScopArrayInfo *Array) {
    std::vector<isl_pw_aff *> Bounds;

    if (PPCGArray.n_index > 0) {
      if (isl_set_is_empty(PPCGArray.extent)) {
        isl_set *Dom = isl_set_copy(PPCGArray.extent);
        isl_local_space *LS = isl_local_space_from_space(
            isl_space_params(isl_set_get_space(Dom)));
        isl_set_free(Dom);
        isl_pw_aff *Zero = isl_pw_aff_from_aff(isl_aff_zero_on_domain(LS));
        Bounds.push_back(Zero);
      } else {
        isl_set *Dom = isl_set_copy(PPCGArray.extent);
        Dom = isl_set_project_out(Dom, isl_dim_set, 1, PPCGArray.n_index - 1);
        isl_pw_aff *Bound = isl_set_dim_max(isl_set_copy(Dom), 0);
        isl_set_free(Dom);
        Dom = isl_pw_aff_domain(isl_pw_aff_copy(Bound));
        isl_local_space *LS =
            isl_local_space_from_space(isl_set_get_space(Dom));
        isl_aff *One = isl_aff_zero_on_domain(LS);
        One = isl_aff_add_constant_si(One, 1);
        Bound = isl_pw_aff_add(Bound, isl_pw_aff_alloc(Dom, One));
        Bound = isl_pw_aff_gist(Bound, S->getContext().release());
        Bounds.push_back(Bound);
      }
    }

    for (unsigned i = 1; i < PPCGArray.n_index; ++i) {
      isl_pw_aff *Bound = Array->getDimensionSizePw(i).release();
      auto LS = isl_pw_aff_get_domain_space(Bound);
      auto Aff = isl_multi_aff_zero(LS);

      // We need types to work out, which is why we perform this weird dance
      // with `Aff` and `Bound`. Consider this example:

      // LS: [p] -> { [] }
      // Zero: [p] -> { [] } | Implicitly, is [p] -> { ~ -> [] }.
      // This `~` is used to denote a "null space" (which is different from
      // a *zero dimensional* space), which is something that ISL does not
      // show you when pretty printing.

      // Bound: [p] -> { [] -> [(10p)] } | Here, the [] is a *zero dimensional*
      // space, not a "null space" which does not exist at all.

      // When we pullback (precompose) `Bound` with `Zero`, we get:
      // Bound . Zero =
      //     ([p] -> { [] -> [(10p)] }) . ([p] -> {~ -> [] }) =
      //     [p] -> { ~ -> [(10p)] } =
      //     [p] -> [(10p)] (as ISL pretty prints it)
      // Bound Pullback: [p] -> { [(10p)] }

      // We want this kind of an expression for Bound, without a
      // zero dimensional input, but with a "null space" input for the types
      // to work out later on, as far as I (Siddharth Bhat) understand.
      // I was unable to find a reference to this in the ISL manual.
      // References: Tobias Grosser.

      Bound = isl_pw_aff_pullback_multi_aff(Bound, Aff);
      Bounds.push_back(Bound);
    }

    /// To construct a `isl_multi_pw_aff`, we need all the indivisual `pw_aff`
    /// to have the same parameter dimensions. So, we need to align them to an
    /// appropriate space.
    /// Scop::Context is _not_ an appropriate space, because when we have
    /// `-polly-ignore-parameter-bounds` enabled, the Scop::Context does not
    /// contain all parameter dimensions.
    /// So, use the helper `alignPwAffs` to align all the `isl_pw_aff` together.
    isl_space *SeedAlignSpace = S->getParamSpace().release();
    SeedAlignSpace = isl_space_add_dims(SeedAlignSpace, isl_dim_set, 1);

    isl_space *AlignSpace = nullptr;
    std::vector<isl_pw_aff *> AlignedBounds;
    std::tie(AlignSpace, AlignedBounds) =
        alignPwAffs(std::move(Bounds), SeedAlignSpace);

    assert(AlignSpace && "alignPwAffs did not initialise AlignSpace");

    isl_pw_aff_list *BoundsList =
        createPwAffList(S->getIslCtx().get(), std::move(AlignedBounds));

    isl_space *BoundsSpace = isl_set_get_space(PPCGArray.extent);
    BoundsSpace = isl_space_align_params(BoundsSpace, AlignSpace);

    assert(BoundsSpace && "Unable to access space of array.");
    assert(BoundsList && "Unable to access list of bounds.");

    PPCGArray.bound =
        isl_multi_pw_aff_from_pw_aff_list(BoundsSpace, BoundsList);
    assert(PPCGArray.bound && "PPCGArray.bound was not constructed correctly.");
  }

  /// Create the arrays for @p PPCGProg.
  ///
  /// @param PPCGProg The program to compute the arrays for.
  void createArrays(gpu_prog *PPCGProg,
                    const SmallVector<ScopArrayInfo *, 4> &ValidSAIs) {
    int i = 0;
    for (auto &Array : ValidSAIs) {
      std::string TypeName;
      raw_string_ostream OS(TypeName);

      OS << *Array->getElementType();
      TypeName = OS.str();

      gpu_array_info &PPCGArray = PPCGProg->array[i];

      PPCGArray.space = Array->getSpace().release();
      PPCGArray.type = strdup(TypeName.c_str());
      PPCGArray.size = DL->getTypeAllocSize(Array->getElementType());
      PPCGArray.name = strdup(Array->getName().c_str());
      PPCGArray.extent = nullptr;
      PPCGArray.n_index = Array->getNumberOfDimensions();
      PPCGArray.extent = getExtent(Array).release();
      PPCGArray.n_ref = 0;
      PPCGArray.refs = nullptr;
      PPCGArray.accessed = true;
      PPCGArray.read_only_scalar =
          Array->isReadOnly() && Array->getNumberOfDimensions() == 0;
      PPCGArray.has_compound_element = false;
      PPCGArray.local = false;
      PPCGArray.declare_local = false;
      PPCGArray.global = false;
      PPCGArray.linearize = false;
      PPCGArray.dep_order = nullptr;
      PPCGArray.user = Array;

      PPCGArray.bound = nullptr;
      setArrayBounds(PPCGArray, Array);
      i++;

      collect_references(PPCGProg, &PPCGArray);
      PPCGArray.only_fixed_element = only_fixed_element_accessed(&PPCGArray);
    }
  }

  /// Create an identity map between the arrays in the scop.
  ///
  /// @returns An identity map between the arrays in the scop.
  isl_union_map *getArrayIdentity() {
    isl_union_map *Maps = isl_union_map_empty(S->getParamSpace().release());

    for (auto &Array : S->arrays()) {
      isl_space *Space = Array->getSpace().release();
      Space = isl_space_map_from_set(Space);
      isl_map *Identity = isl_map_identity(Space);
      Maps = isl_union_map_add_map(Maps, Identity);
    }

    return Maps;
  }

  /// Create a default-initialized PPCG GPU program.
  ///
  /// @returns A new gpu program description.
  gpu_prog *createPPCGProg(ppcg_scop *PPCGScop) {

    if (!PPCGScop)
      return nullptr;

    auto PPCGProg = isl_calloc_type(S->getIslCtx().get(), struct gpu_prog);

    PPCGProg->ctx = S->getIslCtx().get();
    PPCGProg->scop = PPCGScop;
    PPCGProg->context = isl_set_copy(PPCGScop->context);
    PPCGProg->read = isl_union_map_copy(PPCGScop->reads);
    PPCGProg->may_write = isl_union_map_copy(PPCGScop->may_writes);
    PPCGProg->must_write = isl_union_map_copy(PPCGScop->must_writes);
    PPCGProg->tagged_must_kill =
        isl_union_map_copy(PPCGScop->tagged_must_kills);
    PPCGProg->to_inner = getArrayIdentity();
    PPCGProg->to_outer = getArrayIdentity();
    // TODO: verify that this assignment is correct.
    PPCGProg->any_to_outer = nullptr;
    PPCGProg->n_stmts = std::distance(S->begin(), S->end());
    PPCGProg->stmts = getStatements();

    // Only consider arrays that have a non-empty extent.
    // Otherwise, this will cause us to consider the following kinds of
    // empty arrays:
    //     1. Invariant loads that are represented by SAI objects.
    //     2. Arrays with statically known zero size.
    auto ValidSAIsRange =
        make_filter_range(S->arrays(), [this](ScopArrayInfo *SAI) -> bool {
          return !getExtent(SAI).is_empty();
        });
    SmallVector<ScopArrayInfo *, 4> ValidSAIs(ValidSAIsRange.begin(),
                                              ValidSAIsRange.end());

    PPCGProg->n_array =
        ValidSAIs.size(); // std::distance(S->array_begin(), S->array_end());
    PPCGProg->array = isl_calloc_array(
        S->getIslCtx().get(), struct gpu_array_info, PPCGProg->n_array);

    createArrays(PPCGProg, ValidSAIs);

    PPCGProg->array_order = nullptr;
    collect_order_dependences(PPCGProg);

    PPCGProg->may_persist = compute_may_persist(PPCGProg);
    return PPCGProg;
  }

  struct PrintGPUUserData {
    struct cuda_info *CudaInfo;
    struct gpu_prog *PPCGProg;
    std::vector<ppcg_kernel *> Kernels;
  };

  /// Print a user statement node in the host code.
  ///
  /// We use ppcg's printing facilities to print the actual statement and
  /// additionally build up a list of all kernels that are encountered in the
  /// host ast.
  ///
  /// @param P The printer to print to
  /// @param Options The printing options to use
  /// @param Node The node to print
  /// @param User A user pointer to carry additional data. This pointer is
  ///             expected to be of type PrintGPUUserData.
  ///
  /// @returns A printer to which the output has been printed.
  static __isl_give isl_printer *
  printHostUser(__isl_take isl_printer *P,
                __isl_take isl_ast_print_options *Options,
                __isl_take isl_ast_node *Node, void *User) {
    auto Data = (struct PrintGPUUserData *)User;
    auto Id = isl_ast_node_get_annotation(Node);

    if (Id) {
      bool IsUser = !strcmp(isl_id_get_name(Id), "user");

      // If this is a user statement, format it ourselves as ppcg would
      // otherwise try to call pet functionality that is not available in
      // Polly.
      if (IsUser) {
        P = isl_printer_start_line(P);
        P = isl_printer_print_ast_node(P, Node);
        P = isl_printer_end_line(P);
        isl_id_free(Id);
        isl_ast_print_options_free(Options);
        return P;
      }

      auto Kernel = (struct ppcg_kernel *)isl_id_get_user(Id);
      isl_id_free(Id);
      Data->Kernels.push_back(Kernel);
    }

    return print_host_user(P, Options, Node, User);
  }

  /// Print C code corresponding to the control flow in @p Kernel.
  ///
  /// @param Kernel The kernel to print
  void printKernel(ppcg_kernel *Kernel) {
    auto *P = isl_printer_to_str(S->getIslCtx().get());
    P = isl_printer_set_output_format(P, ISL_FORMAT_C);
    auto *Options = isl_ast_print_options_alloc(S->getIslCtx().get());
    P = isl_ast_node_print(Kernel->tree, P, Options);
    char *String = isl_printer_get_str(P);
    outs() << String << "\n";
    free(String);
    isl_printer_free(P);
  }

  /// Print C code corresponding to the GPU code described by @p Tree.
  ///
  /// @param Tree An AST describing GPU code
  /// @param PPCGProg The PPCG program from which @Tree has been constructed.
  void printGPUTree(isl_ast_node *Tree, gpu_prog *PPCGProg) {
    auto *P = isl_printer_to_str(S->getIslCtx().get());
    P = isl_printer_set_output_format(P, ISL_FORMAT_C);

    PrintGPUUserData Data;
    Data.PPCGProg = PPCGProg;

    auto *Options = isl_ast_print_options_alloc(S->getIslCtx().get());
    Options =
        isl_ast_print_options_set_print_user(Options, printHostUser, &Data);
    P = isl_ast_node_print(Tree, P, Options);
    char *String = isl_printer_get_str(P);
    outs() << "# host\n";
    outs() << String << "\n";
    free(String);
    isl_printer_free(P);

    for (auto Kernel : Data.Kernels) {
      outs() << "# kernel" << Kernel->id << "\n";
      printKernel(Kernel);
    }
  }

  // Generate a GPU program using PPCG.
  //
  // GPU mapping consists of multiple steps:
  //
  //  1) Compute new schedule for the program.
  //  2) Map schedule to GPU (TODO)
  //  3) Generate code for new schedule (TODO)
  //
  // We do not use here the Polly ScheduleOptimizer, as the schedule optimizer
  // is mostly CPU specific. Instead, we use PPCG's GPU code generation
  // strategy directly from this pass.
  gpu_gen *generateGPU(ppcg_scop *PPCGScop, gpu_prog *PPCGProg) {

    auto PPCGGen = isl_calloc_type(S->getIslCtx().get(), struct gpu_gen);

    PPCGGen->ctx = S->getIslCtx().get();
    PPCGGen->options = PPCGScop->options;
    PPCGGen->print = nullptr;
    PPCGGen->print_user = nullptr;
    PPCGGen->build_ast_expr = &pollyBuildAstExprForStmt;
    PPCGGen->prog = PPCGProg;
    PPCGGen->tree = nullptr;
    PPCGGen->types.n = 0;
    PPCGGen->types.name = nullptr;
    PPCGGen->sizes = nullptr;
    PPCGGen->used_sizes = nullptr;
    PPCGGen->kernel_id = 0;

    // Set scheduling strategy to same strategy PPCG is using.
    isl_options_set_schedule_outer_coincidence(PPCGGen->ctx, true);
    isl_options_set_schedule_maximize_band_depth(PPCGGen->ctx, true);
    isl_options_set_schedule_whole_component(PPCGGen->ctx, false);

    isl_schedule *Schedule = get_schedule(PPCGGen);

    int has_permutable = has_any_permutable_node(Schedule);

    Schedule =
        isl_schedule_align_params(Schedule, S->getFullParamSpace().release());

    if (!has_permutable || has_permutable < 0) {
      Schedule = isl_schedule_free(Schedule);
      LLVM_DEBUG(dbgs() << getUniqueScopName(S)
                        << " does not have permutable bands. Bailing out\n";);
    } else {
      const bool CreateTransferToFromDevice = !PollyManagedMemory;
      Schedule = map_to_device(PPCGGen, Schedule, CreateTransferToFromDevice);
      PPCGGen->tree = generate_code(PPCGGen, isl_schedule_copy(Schedule));
    }

    if (DumpSchedule) {
      isl_printer *P = isl_printer_to_str(S->getIslCtx().get());
      P = isl_printer_set_yaml_style(P, ISL_YAML_STYLE_BLOCK);
      P = isl_printer_print_str(P, "Schedule\n");
      P = isl_printer_print_str(P, "========\n");
      if (Schedule)
        P = isl_printer_print_schedule(P, Schedule);
      else
        P = isl_printer_print_str(P, "No schedule found\n");

      outs() << isl_printer_get_str(P) << "\n";
      isl_printer_free(P);
    }

    if (DumpCode) {
      outs() << "Code\n";
      outs() << "====\n";
      if (PPCGGen->tree)
        printGPUTree(PPCGGen->tree, PPCGProg);
      else
        outs() << "No code generated\n";
    }

    isl_schedule_free(Schedule);

    return PPCGGen;
  }

  /// Free gpu_gen structure.
  ///
  /// @param PPCGGen The ppcg_gen object to free.
  void freePPCGGen(gpu_gen *PPCGGen) {
    isl_ast_node_free(PPCGGen->tree);
    isl_union_map_free(PPCGGen->sizes);
    isl_union_map_free(PPCGGen->used_sizes);
    free(PPCGGen);
  }

  /// Free the options in the ppcg scop structure.
  ///
  /// ppcg is not freeing these options for us. To avoid leaks we do this
  /// ourselves.
  ///
  /// @param PPCGScop The scop referencing the options to free.
  void freeOptions(ppcg_scop *PPCGScop) {
    free(PPCGScop->options->debug);
    PPCGScop->options->debug = nullptr;
    free(PPCGScop->options);
    PPCGScop->options = nullptr;
  }

  /// Approximate the number of points in the set.
  ///
  /// This function returns an ast expression that overapproximates the number
  /// of points in an isl set through the rectangular hull surrounding this set.
  ///
  /// @param Set   The set to count.
  /// @param Build The isl ast build object to use for creating the ast
  ///              expression.
  ///
  /// @returns An approximation of the number of points in the set.
  __isl_give isl_ast_expr *approxPointsInSet(__isl_take isl_set *Set,
                                             __isl_keep isl_ast_build *Build) {

    isl_val *One = isl_val_int_from_si(isl_set_get_ctx(Set), 1);
    auto *Expr = isl_ast_expr_from_val(isl_val_copy(One));

    isl_space *Space = isl_set_get_space(Set);
    Space = isl_space_params(Space);
    auto *Univ = isl_set_universe(Space);
    isl_pw_aff *OneAff = isl_pw_aff_val_on_domain(Univ, One);

    for (long i = 0, n = isl_set_dim(Set, isl_dim_set); i < n; i++) {
      isl_pw_aff *Max = isl_set_dim_max(isl_set_copy(Set), i);
      isl_pw_aff *Min = isl_set_dim_min(isl_set_copy(Set), i);
      isl_pw_aff *DimSize = isl_pw_aff_sub(Max, Min);
      DimSize = isl_pw_aff_add(DimSize, isl_pw_aff_copy(OneAff));
      auto DimSizeExpr = isl_ast_build_expr_from_pw_aff(Build, DimSize);
      Expr = isl_ast_expr_mul(Expr, DimSizeExpr);
    }

    isl_set_free(Set);
    isl_pw_aff_free(OneAff);

    return Expr;
  }

  /// Approximate a number of dynamic instructions executed by a given
  /// statement.
  ///
  /// @param Stmt  The statement for which to compute the number of dynamic
  ///              instructions.
  /// @param Build The isl ast build object to use for creating the ast
  ///              expression.
  /// @returns An approximation of the number of dynamic instructions executed
  ///          by @p Stmt.
  __isl_give isl_ast_expr *approxDynamicInst(ScopStmt &Stmt,
                                             __isl_keep isl_ast_build *Build) {
    auto Iterations = approxPointsInSet(Stmt.getDomain().release(), Build);

    long InstCount = 0;

    if (Stmt.isBlockStmt()) {
      auto *BB = Stmt.getBasicBlock();
      InstCount = std::distance(BB->begin(), BB->end());
    } else {
      auto *R = Stmt.getRegion();

      for (auto *BB : R->blocks()) {
        InstCount += std::distance(BB->begin(), BB->end());
      }
    }

    isl_val *InstVal = isl_val_int_from_si(S->getIslCtx().get(), InstCount);
    auto *InstExpr = isl_ast_expr_from_val(InstVal);
    return isl_ast_expr_mul(InstExpr, Iterations);
  }

  /// Approximate dynamic instructions executed in scop.
  ///
  /// @param S     The scop for which to approximate dynamic instructions.
  /// @param Build The isl ast build object to use for creating the ast
  ///              expression.
  /// @returns An approximation of the number of dynamic instructions executed
  ///          in @p S.
  __isl_give isl_ast_expr *
  getNumberOfIterations(Scop &S, __isl_keep isl_ast_build *Build) {
    isl_ast_expr *Instructions;

    isl_val *Zero = isl_val_int_from_si(S.getIslCtx().get(), 0);
    Instructions = isl_ast_expr_from_val(Zero);

    for (ScopStmt &Stmt : S) {
      isl_ast_expr *StmtInstructions = approxDynamicInst(Stmt, Build);
      Instructions = isl_ast_expr_add(Instructions, StmtInstructions);
    }
    return Instructions;
  }

  /// Create a check that ensures sufficient compute in scop.
  ///
  /// @param S     The scop for which to ensure sufficient compute.
  /// @param Build The isl ast build object to use for creating the ast
  ///              expression.
  /// @returns An expression that evaluates to TRUE in case of sufficient
  ///          compute and to FALSE, otherwise.
  __isl_give isl_ast_expr *
  createSufficientComputeCheck(Scop &S, __isl_keep isl_ast_build *Build) {
    auto Iterations = getNumberOfIterations(S, Build);
    auto *MinComputeVal = isl_val_int_from_si(S.getIslCtx().get(), MinCompute);
    auto *MinComputeExpr = isl_ast_expr_from_val(MinComputeVal);
    return isl_ast_expr_ge(Iterations, MinComputeExpr);
  }

  /// Check if the basic block contains a function we cannot codegen for GPU
  /// kernels.
  ///
  /// If this basic block does something with a `Function` other than calling
  /// a function that we support in a kernel, return true.
  bool containsInvalidKernelFunctionInBlock(const BasicBlock *BB,
                                            bool AllowCUDALibDevice) {
    for (const Instruction &Inst : *BB) {
      const CallInst *Call = dyn_cast<CallInst>(&Inst);
      if (Call && isValidFunctionInKernel(Call->getCalledFunction(),
                                          AllowCUDALibDevice))
        continue;

      for (Value *Op : Inst.operands())
        // Look for (<func-type>*) among operands of Inst
        if (auto PtrTy = dyn_cast<PointerType>(Op->getType())) {
          if (isa<FunctionType>(PtrTy->getElementType())) {
            LLVM_DEBUG(dbgs()
                       << Inst << " has illegal use of function in kernel.\n");
            return true;
          }
        }
    }
    return false;
  }

  /// Return whether the Scop S uses functions in a way that we do not support.
  bool containsInvalidKernelFunction(const Scop &S, bool AllowCUDALibDevice) {
    for (auto &Stmt : S) {
      if (Stmt.isBlockStmt()) {
        if (containsInvalidKernelFunctionInBlock(Stmt.getBasicBlock(),
                                                 AllowCUDALibDevice))
          return true;
      } else {
        assert(Stmt.isRegionStmt() &&
               "Stmt was neither block nor region statement");
        for (const BasicBlock *BB : Stmt.getRegion()->blocks())
          if (containsInvalidKernelFunctionInBlock(BB, AllowCUDALibDevice))
            return true;
      }
    }
    return false;
  }

  /// Generate code for a given GPU AST described by @p Root.
  ///
  /// @param Root An isl_ast_node pointing to the root of the GPU AST.
  /// @param Prog The GPU Program to generate code for.
  void generateCode(__isl_take isl_ast_node *Root, gpu_prog *Prog) {
    ScopAnnotator Annotator;
    Annotator.buildAliasScopes(*S);

    Region *R = &S->getRegion();

    simplifyRegion(R, DT, LI, RI);

    BasicBlock *EnteringBB = R->getEnteringBlock();

    PollyIRBuilder Builder(EnteringBB->getContext(), ConstantFolder(),
                           IRInserter(Annotator));
    Builder.SetInsertPoint(EnteringBB->getTerminator());

    // Only build the run-time condition and parameters _after_ having
    // introduced the conditional branch. This is important as the conditional
    // branch will guard the original scop from new induction variables that
    // the SCEVExpander may introduce while code generating the parameters and
    // which may introduce scalar dependences that prevent us from correctly
    // code generating this scop.
    BBPair StartExitBlocks;
    BranchInst *CondBr = nullptr;
    std::tie(StartExitBlocks, CondBr) =
        executeScopConditionally(*S, Builder.getTrue(), *DT, *RI, *LI);
    BasicBlock *StartBlock = std::get<0>(StartExitBlocks);

    assert(CondBr && "CondBr not initialized by executeScopConditionally");

    GPUNodeBuilder NodeBuilder(Builder, Annotator, *DL, *LI, *SE, *DT, *S,
                               StartBlock, Prog, Runtime, Architecture);

    // TODO: Handle LICM
    auto SplitBlock = StartBlock->getSinglePredecessor();
    Builder.SetInsertPoint(SplitBlock->getTerminator());

    isl_ast_build *Build = isl_ast_build_alloc(S->getIslCtx().get());
    isl::ast_expr Condition =
        IslAst::buildRunCondition(*S, isl::manage_copy(Build));
    isl_ast_expr *SufficientCompute = createSufficientComputeCheck(*S, Build);
    Condition =
        isl::manage(isl_ast_expr_and(Condition.release(), SufficientCompute));
    isl_ast_build_free(Build);

    // preload invariant loads. Note: This should happen before the RTC
    // because the RTC may depend on values that are invariant load hoisted.
    if (!NodeBuilder.preloadInvariantLoads()) {
      // Patch the introduced branch condition to ensure that we always execute
      // the original SCoP.
      auto *FalseI1 = Builder.getFalse();
      auto *SplitBBTerm = Builder.GetInsertBlock()->getTerminator();
      SplitBBTerm->setOperand(0, FalseI1);

      LLVM_DEBUG(dbgs() << "preloading invariant loads failed in function: " +
                               S->getFunction().getName() +
                               " | Scop Region: " + S->getNameStr());
      // adjust the dominator tree accordingly.
      auto *ExitingBlock = StartBlock->getUniqueSuccessor();
      assert(ExitingBlock);
      auto *MergeBlock = ExitingBlock->getUniqueSuccessor();
      assert(MergeBlock);
      polly::markBlockUnreachable(*StartBlock, Builder);
      polly::markBlockUnreachable(*ExitingBlock, Builder);
      auto *ExitingBB = S->getExitingBlock();
      assert(ExitingBB);

      DT->changeImmediateDominator(MergeBlock, ExitingBB);
      DT->eraseNode(ExitingBlock);
      isl_ast_node_free(Root);
    } else {

      if (polly::PerfMonitoring) {
        PerfMonitor P(*S, EnteringBB->getParent()->getParent());
        P.initialize();
        P.insertRegionStart(SplitBlock->getTerminator());

        // TODO: actually think if this is the correct exiting block to place
        // the `end` performance marker. Invariant load hoisting changes
        // the CFG in a way that I do not precisely understand, so I
        // (Siddharth<siddu.druid@gmail.com>) should come back to this and
        // think about which exiting block to use.
        auto *ExitingBlock = StartBlock->getUniqueSuccessor();
        assert(ExitingBlock);
        BasicBlock *MergeBlock = ExitingBlock->getUniqueSuccessor();
        P.insertRegionEnd(MergeBlock->getTerminator());
      }

      NodeBuilder.addParameters(S->getContext().release());
      Value *RTC = NodeBuilder.createRTC(Condition.release());
      Builder.GetInsertBlock()->getTerminator()->setOperand(0, RTC);

      Builder.SetInsertPoint(&*StartBlock->begin());

      NodeBuilder.create(Root);
    }

    /// In case a sequential kernel has more surrounding loops as any parallel
    /// kernel, the SCoP is probably mostly sequential. Hence, there is no
    /// point in running it on a GPU.
    if (NodeBuilder.DeepestSequential > NodeBuilder.DeepestParallel)
      CondBr->setOperand(0, Builder.getFalse());

    if (!NodeBuilder.BuildSuccessful)
      CondBr->setOperand(0, Builder.getFalse());
  }

  bool runOnScop(Scop &CurrentScop) override {
    S = &CurrentScop;
    LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
    DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
    SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
    DL = &S->getRegion().getEntry()->getModule()->getDataLayout();
    RI = &getAnalysis<RegionInfoPass>().getRegionInfo();

    LLVM_DEBUG(dbgs() << "PPCGCodeGen running on : " << getUniqueScopName(S)
                      << " | loop depth: " << S->getMaxLoopDepth() << "\n");

    // We currently do not support functions other than intrinsics inside
    // kernels, as code generation will need to offload function calls to the
    // kernel. This may lead to a kernel trying to call a function on the host.
    // This also allows us to prevent codegen from trying to take the
    // address of an intrinsic function to send to the kernel.
    if (containsInvalidKernelFunction(CurrentScop,
                                      Architecture == GPUArch::NVPTX64)) {
      LLVM_DEBUG(
          dbgs() << getUniqueScopName(S)
                 << " contains function which cannot be materialised in a GPU "
                    "kernel. Bailing out.\n";);
      return false;
    }

    auto PPCGScop = createPPCGScop();
    auto PPCGProg = createPPCGProg(PPCGScop);
    auto PPCGGen = generateGPU(PPCGScop, PPCGProg);

    if (PPCGGen->tree) {
      generateCode(isl_ast_node_copy(PPCGGen->tree), PPCGProg);
      CurrentScop.markAsToBeSkipped();
    } else {
      LLVM_DEBUG(dbgs() << getUniqueScopName(S)
                        << " has empty PPCGGen->tree. Bailing out.\n");
    }

    freeOptions(PPCGScop);
    freePPCGGen(PPCGGen);
    gpu_prog_free(PPCGProg);
    ppcg_scop_free(PPCGScop);

    return true;
  }

  void printScop(raw_ostream &, Scop &) const override {}

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    ScopPass::getAnalysisUsage(AU);

    AU.addRequired<DominatorTreeWrapperPass>();
    AU.addRequired<RegionInfoPass>();
    AU.addRequired<ScalarEvolutionWrapperPass>();
    AU.addRequired<ScopDetectionWrapperPass>();
    AU.addRequired<ScopInfoRegionPass>();
    AU.addRequired<LoopInfoWrapperPass>();

    // FIXME: We do not yet add regions for the newly generated code to the
    //        region tree.
  }
};
} // namespace

char PPCGCodeGeneration::ID = 1;

Pass *polly::createPPCGCodeGenerationPass(GPUArch Arch, GPURuntime Runtime) {
  PPCGCodeGeneration *generator = new PPCGCodeGeneration();
  generator->Runtime = Runtime;
  generator->Architecture = Arch;
  return generator;
}

INITIALIZE_PASS_BEGIN(PPCGCodeGeneration, "polly-codegen-ppcg",
                      "Polly - Apply PPCG translation to SCOP", false, false)
INITIALIZE_PASS_DEPENDENCY(DependenceInfo);
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass);
INITIALIZE_PASS_END(PPCGCodeGeneration, "polly-codegen-ppcg",
                    "Polly - Apply PPCG translation to SCOP", false, false)
