reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
//===--- RuntimeDebugBuilder.h --- Helper to insert prints into LLVM-IR ---===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//

#ifndef RUNTIME_DEBUG_BUILDER_H
#define RUNTIME_DEBUG_BUILDER_H

#include "polly/CodeGen/IRBuilder.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include <vector>

namespace llvm {
class Value;
class Function;
} // namespace llvm

namespace polly {

/// Insert function calls that print certain LLVM values at run time.
///
/// This class inserts libc function calls to print certain LLVM values at
/// run time.
struct RuntimeDebugBuilder {

  /// Generate a constant string into the builder's llvm::Module which can be
  /// passed to createGPUPrinter() or createGPUPrinter().
  ///
  /// @param Builder The builder used to emit the printer calls.
  /// @param Str     The string to be printed.

  /// @return        A global containing @p Str.
  static llvm::Value *getPrintableString(PollyIRBuilder &Builder,
                                         llvm::StringRef Str) {
    // TODO: Get rid of magic number 4. It it NVPTX's constant address space and
    // works on X86 (CPU) only because its backend ignores the address space.
    return Builder.CreateGlobalStringPtr(Str, "", 4);
  }

  /// Return whether an llvm::Value of the type @p Ty is printable for
  /// debugging.
  ///
  /// That is, whether such a value can be passed to createGPUPrinter() or
  /// createGPUPrinter() to be dumped as runtime.  If false is returned, those
  /// functions will fail.
  static bool isPrintable(llvm::Type *Ty);

  /// Print a set of LLVM-IR Values or StringRefs via printf
  ///
  ///  This function emits a call to printf that will print the given arguments.
  ///  It is useful for debugging CPU programs. All arguments given in this list
  ///  will be automatically concatenated and the resulting string will be
  ///  printed atomically. We also support ArrayRef arguments, which can be used
  ///  to provide of id values.
  ///
  ///  @param Builder The builder used to emit the printer calls.
  ///  @param Args    The list of values to print.
  template <typename... Args>
  static void createCPUPrinter(PollyIRBuilder &Builder, Args... args) {
    std::vector<llvm::Value *> Vector;
    createPrinter(Builder, /* CPU */ false, Vector, args...);
  }

  /// Print a set of LLVM-IR Values or StringRefs on an NVIDIA GPU.
  ///
  ///  This function emits a call to vprintf that will print the given
  ///  arguments from within a kernel thread. It is useful for debugging
  ///  CUDA program kernels. All arguments given in this list will be
  ///  automatically concatenated and the resulting string will be printed
  ///  atomically. We also support ArrayRef arguments, which can be used to
  ///  provide for example a list of thread-id values.
  ///
  ///  @param Builder The builder used to emit the printer calls.
  ///  @param Args    The list of values to print.
  template <typename... Args>
  static void createGPUPrinter(PollyIRBuilder &Builder, Args... args) {
    std::vector<llvm::Value *> Vector;
    createPrinter(Builder, /* GPU */ true, Vector, args...);
  }

private:
  /// Handle Values.
  template <typename... Args>
  static void createPrinter(PollyIRBuilder &Builder, bool UseGPU,
                            std::vector<llvm::Value *> &Values,
                            llvm::Value *Value, Args... args) {
    Values.push_back(Value);
    createPrinter(Builder, UseGPU, Values, args...);
  }

  /// Handle StringRefs.
  template <typename... Args>
  static void createPrinter(PollyIRBuilder &Builder, bool UseGPU,
                            std::vector<llvm::Value *> &Values,
                            llvm::StringRef String, Args... args) {
    Values.push_back(getPrintableString(Builder, String));
    createPrinter(Builder, UseGPU, Values, args...);
  }

  /// Handle ArrayRefs.
  template <typename... Args>
  static void createPrinter(PollyIRBuilder &Builder, bool UseGPU,
                            std::vector<llvm::Value *> &Values,
                            llvm::ArrayRef<llvm::Value *> Array, Args... args) {
    Values.insert(Values.end(), Array.begin(), Array.end());
    createPrinter(Builder, UseGPU, Values, args...);
  }

  /// Print a list of Values.
  static void createPrinter(PollyIRBuilder &Builder, bool UseGPU,
                            llvm::ArrayRef<llvm::Value *> Values);

  /// Print a list of Values on a GPU.
  static void createGPUPrinterT(PollyIRBuilder &Builder,
                                llvm::ArrayRef<llvm::Value *> Values);

  /// Print a list of Values on a CPU.
  static void createCPUPrinterT(PollyIRBuilder &Builder,
                                llvm::ArrayRef<llvm::Value *> Values);

  /// Get a reference to the 'printf' function.
  ///
  /// If the current module does not yet contain a reference to printf, we
  /// insert a reference to it. Otherwise the existing reference is returned.
  static llvm::Function *getPrintF(PollyIRBuilder &Builder);

  /// Call printf
  ///
  /// @param Builder The builder used to insert the code.
  /// @param Format  The format string.
  /// @param Values  The set of values to print.
  static void createPrintF(PollyIRBuilder &Builder, std::string Format,
                           llvm::ArrayRef<llvm::Value *> Values);

  /// Get (and possibly insert) a vprintf declaration into the module.
  static llvm::Function *getVPrintF(PollyIRBuilder &Builder);

  /// Call fflush
  ///
  /// @parma Builder The builder used to insert the code.
  static void createFlush(PollyIRBuilder &Builder);

  /// Get (and possibly insert) a NVIDIA address space cast call.
  static llvm::Function *getAddressSpaceCast(PollyIRBuilder &Builder,
                                             unsigned Src, unsigned Dst,
                                             unsigned SrcBits = 8,
                                             unsigned DstBits = 8);

  /// Get identifiers that describe the currently executed GPU thread.
  ///
  /// The result will be a vector that if passed to the GPU printer will result
  /// into a string (initialized to values corresponding to the printing
  /// thread):
  ///
  ///   "> block-id: bidx bid1y bidz | thread-id: tidx tidy tidz "
  static std::vector<llvm::Value *>
  getGPUThreadIdentifiers(PollyIRBuilder &Builder);
};
} // namespace polly

extern bool PollyDebugPrinting;

#endif