Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- Support/GICHelper.h -- Helper functions for ISL --------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Helper functions for isl objects.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. //
  13. #ifndef POLLY_SUPPORT_GIC_HELPER_H
  14. #define POLLY_SUPPORT_GIC_HELPER_H
  15.  
  16. #include "llvm/ADT/APInt.h"
  17. #include "llvm/IR/DiagnosticInfo.h"
  18. #include "llvm/Support/raw_ostream.h"
  19. #include "isl/ctx.h"
  20. #include "isl/isl-noexceptions.h"
  21. #include "isl/options.h"
  22.  
  23. namespace polly {
  24.  
  25. /// Translate an llvm::APInt to an isl_val.
  26. ///
  27. /// Translate the bitsequence without sign information as provided by APInt into
  28. /// a signed isl_val type. Depending on the value of @p IsSigned @p Int is
  29. /// interpreted as unsigned value or as signed value in two's complement
  30. /// representation.
  31. ///
  32. /// Input IsSigned                 Output
  33. ///
  34. ///     0        0           ->    0
  35. ///     1        0           ->    1
  36. ///    00        0           ->    0
  37. ///    01        0           ->    1
  38. ///    10        0           ->    2
  39. ///    11        0           ->    3
  40. ///
  41. ///     0        1           ->    0
  42. ///     1        1           ->   -1
  43. ///    00        1           ->    0
  44. ///    01        1           ->    1
  45. ///    10        1           ->   -2
  46. ///    11        1           ->   -1
  47. ///
  48. /// @param Ctx      The isl_ctx to create the isl_val in.
  49. /// @param Int      The integer value to translate.
  50. /// @param IsSigned If the APInt should be interpreted as signed or unsigned
  51. ///                 value.
  52. ///
  53. /// @return The isl_val corresponding to @p Int.
  54. __isl_give isl_val *isl_valFromAPInt(isl_ctx *Ctx, const llvm::APInt Int,
  55.                                      bool IsSigned);
  56.  
  57. /// Translate an llvm::APInt to an isl::val.
  58. ///
  59. /// Translate the bitsequence without sign information as provided by APInt into
  60. /// a signed isl::val type. Depending on the value of @p IsSigned @p Int is
  61. /// interpreted as unsigned value or as signed value in two's complement
  62. /// representation.
  63. ///
  64. /// Input IsSigned                 Output
  65. ///
  66. ///     0        0           ->    0
  67. ///     1        0           ->    1
  68. ///    00        0           ->    0
  69. ///    01        0           ->    1
  70. ///    10        0           ->    2
  71. ///    11        0           ->    3
  72. ///
  73. ///     0        1           ->    0
  74. ///     1        1           ->   -1
  75. ///    00        1           ->    0
  76. ///    01        1           ->    1
  77. ///    10        1           ->   -2
  78. ///    11        1           ->   -1
  79. ///
  80. /// @param Ctx      The isl_ctx to create the isl::val in.
  81. /// @param Int      The integer value to translate.
  82. /// @param IsSigned If the APInt should be interpreted as signed or unsigned
  83. ///                 value.
  84. ///
  85. /// @return The isl::val corresponding to @p Int.
  86. inline isl::val valFromAPInt(isl_ctx *Ctx, const llvm::APInt Int,
  87.                              bool IsSigned) {
  88.   return isl::manage(isl_valFromAPInt(Ctx, Int, IsSigned));
  89. }
  90.  
  91. /// Translate isl_val to llvm::APInt.
  92. ///
  93. /// This function can only be called on isl_val values which are integers.
  94. /// Calling this function with a non-integral rational, NaN or infinity value
  95. /// is not allowed.
  96. ///
  97. /// As the input isl_val may be negative, the APInt that this function returns
  98. /// must always be interpreted as signed two's complement value. The bitwidth of
  99. /// the generated APInt is always the minimal bitwidth necessary to model the
  100. /// provided integer when interpreting the bit pattern as signed value.
  101. ///
  102. /// Some example conversions are:
  103. ///
  104. ///   Input      Bits    Signed  Bitwidth
  105. ///       0 ->      0         0         1
  106. ///      -1 ->      1        -1         1
  107. ///       1 ->     01         1         2
  108. ///      -2 ->     10        -2         2
  109. ///       2 ->    010         2         3
  110. ///      -3 ->    101        -3         3
  111. ///       3 ->    011         3         3
  112. ///      -4 ->    100        -4         3
  113. ///       4 ->   0100         4         4
  114. ///
  115. /// @param Val The isl val to translate.
  116. ///
  117. /// @return The APInt value corresponding to @p Val.
  118. llvm::APInt APIntFromVal(__isl_take isl_val *Val);
  119.  
  120. /// Translate isl::val to llvm::APInt.
  121. ///
  122. /// This function can only be called on isl::val values which are integers.
  123. /// Calling this function with a non-integral rational, NaN or infinity value
  124. /// is not allowed.
  125. ///
  126. /// As the input isl::val may be negative, the APInt that this function returns
  127. /// must always be interpreted as signed two's complement value. The bitwidth of
  128. /// the generated APInt is always the minimal bitwidth necessary to model the
  129. /// provided integer when interpreting the bit pattern as signed value.
  130. ///
  131. /// Some example conversions are:
  132. ///
  133. ///   Input      Bits    Signed  Bitwidth
  134. ///       0 ->      0         0         1
  135. ///      -1 ->      1        -1         1
  136. ///       1 ->     01         1         2
  137. ///      -2 ->     10        -2         2
  138. ///       2 ->    010         2         3
  139. ///      -3 ->    101        -3         3
  140. ///       3 ->    011         3         3
  141. ///      -4 ->    100        -4         3
  142. ///       4 ->   0100         4         4
  143. ///
  144. /// @param Val The isl val to translate.
  145. ///
  146. /// @return The APInt value corresponding to @p Val.
  147. inline llvm::APInt APIntFromVal(isl::val V) {
  148.   return APIntFromVal(V.release());
  149. }
  150.  
  151. /// Get c++ string from Isl objects.
  152. //@{
  153. #define ISL_CPP_OBJECT_TO_STRING(name)                                         \
  154.   inline std::string stringFromIslObj(const name &Obj,                         \
  155.                                       std::string DefaultValue = "") {         \
  156.     return stringFromIslObj(Obj.get(), DefaultValue);                          \
  157.   }
  158.  
  159. #define ISL_OBJECT_TO_STRING(name)                                             \
  160.   std::string stringFromIslObj(__isl_keep isl_##name *Obj,                     \
  161.                                std::string DefaultValue = "");                 \
  162.   ISL_CPP_OBJECT_TO_STRING(isl::name)
  163.  
  164. ISL_OBJECT_TO_STRING(aff)
  165. ISL_OBJECT_TO_STRING(ast_expr)
  166. ISL_OBJECT_TO_STRING(ast_node)
  167. ISL_OBJECT_TO_STRING(basic_map)
  168. ISL_OBJECT_TO_STRING(basic_set)
  169. ISL_OBJECT_TO_STRING(map)
  170. ISL_OBJECT_TO_STRING(set)
  171. ISL_OBJECT_TO_STRING(id)
  172. ISL_OBJECT_TO_STRING(multi_aff)
  173. ISL_OBJECT_TO_STRING(multi_pw_aff)
  174. ISL_OBJECT_TO_STRING(multi_union_pw_aff)
  175. ISL_OBJECT_TO_STRING(point)
  176. ISL_OBJECT_TO_STRING(pw_aff)
  177. ISL_OBJECT_TO_STRING(pw_multi_aff)
  178. ISL_OBJECT_TO_STRING(schedule)
  179. ISL_OBJECT_TO_STRING(schedule_node)
  180. ISL_OBJECT_TO_STRING(space)
  181. ISL_OBJECT_TO_STRING(union_access_info)
  182. ISL_OBJECT_TO_STRING(union_flow)
  183. ISL_OBJECT_TO_STRING(union_set)
  184. ISL_OBJECT_TO_STRING(union_map)
  185. ISL_OBJECT_TO_STRING(union_pw_aff)
  186. ISL_OBJECT_TO_STRING(union_pw_multi_aff)
  187. //@}
  188.  
  189. #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  190. /// C++ wrapper for isl_*_dump() functions.
  191. //@{
  192.  
  193. #define ISL_DUMP_OBJECT(name)                                                  \
  194.   void dumpIslObj(const isl::name &Obj);                                       \
  195.   void dumpIslObj(isl_##name *Obj);
  196.  
  197. ISL_DUMP_OBJECT(aff)
  198. ISL_DUMP_OBJECT(aff_list)
  199. ISL_DUMP_OBJECT(ast_expr)
  200. ISL_DUMP_OBJECT(ast_node)
  201. ISL_DUMP_OBJECT(ast_node_list)
  202. ISL_DUMP_OBJECT(basic_map)
  203. ISL_DUMP_OBJECT(basic_map_list)
  204. ISL_DUMP_OBJECT(basic_set)
  205. ISL_DUMP_OBJECT(basic_set_list)
  206. ISL_DUMP_OBJECT(constraint)
  207. ISL_DUMP_OBJECT(id)
  208. ISL_DUMP_OBJECT(id_list)
  209. ISL_DUMP_OBJECT(id_to_ast_expr)
  210. ISL_DUMP_OBJECT(local_space)
  211. ISL_DUMP_OBJECT(map)
  212. ISL_DUMP_OBJECT(map_list)
  213. ISL_DUMP_OBJECT(multi_aff)
  214. ISL_DUMP_OBJECT(multi_pw_aff)
  215. ISL_DUMP_OBJECT(multi_union_pw_aff)
  216. ISL_DUMP_OBJECT(multi_val)
  217. ISL_DUMP_OBJECT(point)
  218. ISL_DUMP_OBJECT(pw_aff)
  219. ISL_DUMP_OBJECT(pw_aff_list)
  220. ISL_DUMP_OBJECT(pw_multi_aff)
  221. ISL_DUMP_OBJECT(schedule)
  222. ISL_DUMP_OBJECT(schedule_constraints)
  223. ISL_DUMP_OBJECT(schedule_node)
  224. ISL_DUMP_OBJECT(set)
  225. ISL_DUMP_OBJECT(set_list)
  226. ISL_DUMP_OBJECT(space)
  227. ISL_DUMP_OBJECT(union_map)
  228. ISL_DUMP_OBJECT(union_pw_aff)
  229. ISL_DUMP_OBJECT(union_pw_aff_list)
  230. ISL_DUMP_OBJECT(union_pw_multi_aff)
  231. ISL_DUMP_OBJECT(union_set)
  232. ISL_DUMP_OBJECT(union_set_list)
  233. ISL_DUMP_OBJECT(val)
  234. ISL_DUMP_OBJECT(val_list)
  235. //@}
  236.  
  237. /// Emit the equivaltent of the isl_*_dump output into a raw_ostream.
  238. /// @{
  239. void dumpIslObj(const isl::schedule_node &Node, llvm::raw_ostream &OS);
  240. void dumpIslObj(__isl_keep isl_schedule_node *node, llvm::raw_ostream &OS);
  241. /// @}
  242. #endif
  243.  
  244. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  245.                                      __isl_keep isl_union_map *Map) {
  246.   OS << polly::stringFromIslObj(Map, "null");
  247.   return OS;
  248. }
  249.  
  250. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  251.                                      __isl_keep isl_map *Map) {
  252.   OS << polly::stringFromIslObj(Map, "null");
  253.   return OS;
  254. }
  255.  
  256. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  257.                                      __isl_keep isl_set *Set) {
  258.   OS << polly::stringFromIslObj(Set, "null");
  259.   return OS;
  260. }
  261.  
  262. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  263.                                      __isl_keep isl_pw_aff *Map) {
  264.   OS << polly::stringFromIslObj(Map, "null");
  265.   return OS;
  266. }
  267.  
  268. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  269.                                      __isl_keep isl_pw_multi_aff *PMA) {
  270.   OS << polly::stringFromIslObj(PMA, "null");
  271.   return OS;
  272. }
  273.  
  274. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  275.                                      __isl_keep isl_multi_aff *MA) {
  276.   OS << polly::stringFromIslObj(MA, "null");
  277.   return OS;
  278. }
  279.  
  280. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  281.                                      __isl_keep isl_union_pw_multi_aff *UPMA) {
  282.   OS << polly::stringFromIslObj(UPMA, "null");
  283.   return OS;
  284. }
  285.  
  286. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  287.                                      __isl_keep isl_schedule *Schedule) {
  288.   OS << polly::stringFromIslObj(Schedule, "null");
  289.   return OS;
  290. }
  291.  
  292. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
  293.                                      __isl_keep isl_space *Space) {
  294.   OS << polly::stringFromIslObj(Space, "null");
  295.   return OS;
  296. }
  297.  
  298. /// Combine Prefix, Val (or Number) and Suffix to an isl-compatible name.
  299. ///
  300. /// In case @p UseInstructionNames is set, this function returns:
  301. ///
  302. /// @p Prefix + "_" + @p Val->getName() + @p Suffix
  303. ///
  304. /// otherwise
  305. ///
  306. /// @p Prefix + to_string(Number) + @p Suffix
  307. ///
  308. /// We ignore the value names by default, as they may change between release
  309. /// and debug mode and can consequently not be used when aiming for reproducible
  310. /// builds. However, for debugging named statements are often helpful, hence
  311. /// we allow their optional use.
  312. std::string getIslCompatibleName(const std::string &Prefix,
  313.                                  const llvm::Value *Val, long Number,
  314.                                  const std::string &Suffix,
  315.                                  bool UseInstructionNames);
  316.  
  317. /// Combine Prefix, Name (or Number) and Suffix to an isl-compatible name.
  318. ///
  319. /// In case @p UseInstructionNames is set, this function returns:
  320. ///
  321. /// @p Prefix + "_" + Name + @p Suffix
  322. ///
  323. /// otherwise
  324. ///
  325. /// @p Prefix + to_string(Number) + @p Suffix
  326. ///
  327. /// We ignore @p Name by default, as they may change between release
  328. /// and debug mode and can consequently not be used when aiming for reproducible
  329. /// builds. However, for debugging named statements are often helpful, hence
  330. /// we allow their optional use.
  331. std::string getIslCompatibleName(const std::string &Prefix,
  332.                                  const std::string &Middle, long Number,
  333.                                  const std::string &Suffix,
  334.                                  bool UseInstructionNames);
  335.  
  336. std::string getIslCompatibleName(const std::string &Prefix,
  337.                                  const std::string &Middle,
  338.                                  const std::string &Suffix);
  339.  
  340. inline llvm::DiagnosticInfoOptimizationBase &
  341. operator<<(llvm::DiagnosticInfoOptimizationBase &OS,
  342.            const isl::union_map &Obj) {
  343.   OS << stringFromIslObj(Obj);
  344.   return OS;
  345. }
  346.  
  347. /// Scope guard for code that allows arbitrary isl function to return an error
  348. /// if the max-operations quota exceeds.
  349. ///
  350. /// This allows to opt-in code sections that have known long executions times.
  351. /// code not in a hot path can continue to assume that no unexpected error
  352. /// occurs.
  353. ///
  354. /// This is typically used inside a nested IslMaxOperationsGuard scope. The
  355. /// IslMaxOperationsGuard defines the number of allowed base operations for some
  356. /// code, IslQuotaScope defines where it is allowed to return an error result.
  357. class IslQuotaScope final {
  358.   isl_ctx *IslCtx;
  359.   int OldOnError;
  360.  
  361. public:
  362.   IslQuotaScope() : IslCtx(nullptr) {}
  363.   IslQuotaScope(const IslQuotaScope &) = delete;
  364.   IslQuotaScope(IslQuotaScope &&Other)
  365.       : IslCtx(Other.IslCtx), OldOnError(Other.OldOnError) {
  366.     Other.IslCtx = nullptr;
  367.   }
  368.   const IslQuotaScope &operator=(IslQuotaScope &&Other) {
  369.     std::swap(this->IslCtx, Other.IslCtx);
  370.     std::swap(this->OldOnError, Other.OldOnError);
  371.     return *this;
  372.   }
  373.  
  374.   /// Enter a quota-aware scope.
  375.   ///
  376.   /// Should not be used directly. Use IslMaxOperationsGuard::enter() instead.
  377.   explicit IslQuotaScope(isl_ctx *IslCtx, unsigned long LocalMaxOps)
  378.       : IslCtx(IslCtx) {
  379.     assert(IslCtx);
  380.     assert(isl_ctx_get_max_operations(IslCtx) == 0 && "Incorrect nesting");
  381.     if (LocalMaxOps == 0) {
  382.       this->IslCtx = nullptr;
  383.       return;
  384.     }
  385.  
  386.     OldOnError = isl_options_get_on_error(IslCtx);
  387.     isl_options_set_on_error(IslCtx, ISL_ON_ERROR_CONTINUE);
  388.     isl_ctx_reset_error(IslCtx);
  389.     isl_ctx_set_max_operations(IslCtx, LocalMaxOps);
  390.   }
  391.  
  392.   ~IslQuotaScope() {
  393.     if (!IslCtx)
  394.       return;
  395.  
  396.     assert(isl_ctx_get_max_operations(IslCtx) > 0 && "Incorrect nesting");
  397.     assert(isl_options_get_on_error(IslCtx) == ISL_ON_ERROR_CONTINUE &&
  398.            "Incorrect nesting");
  399.     isl_ctx_set_max_operations(IslCtx, 0);
  400.     isl_options_set_on_error(IslCtx, OldOnError);
  401.   }
  402.  
  403.   /// Return whether the current quota has exceeded.
  404.   bool hasQuotaExceeded() const {
  405.     if (!IslCtx)
  406.       return false;
  407.  
  408.     return isl_ctx_last_error(IslCtx) == isl_error_quota;
  409.   }
  410. };
  411.  
  412. /// Scoped limit of ISL operations.
  413. ///
  414. /// Limits the number of ISL operations during the lifetime of this object. The
  415. /// idea is to use this as an RAII guard for the scope where the code is aware
  416. /// that ISL can return errors even when all input is valid. After leaving the
  417. /// scope, it will return to the error setting as it was before. That also means
  418. /// that the error setting should not be changed while in that scope.
  419. ///
  420. /// Such scopes are not allowed to be nested because the previous operations
  421. /// counter cannot be reset to the previous state, or one that adds the
  422. /// operations while being in the nested scope. Use therefore is only allowed
  423. /// while currently a no operations-limit is active.
  424. class IslMaxOperationsGuard final {
  425. private:
  426.   /// The ISL context to set the operations limit.
  427.   ///
  428.   /// If set to nullptr, there is no need for any action at the end of the
  429.   /// scope.
  430.   isl_ctx *IslCtx;
  431.  
  432.   /// Maximum number of operations for the scope.
  433.   unsigned long LocalMaxOps;
  434.  
  435.   /// When AutoEnter is enabled, holds the IslQuotaScope object.
  436.   IslQuotaScope TopLevelScope;
  437.  
  438. public:
  439.   /// Enter a max operations scope.
  440.   ///
  441.   /// @param IslCtx      The ISL context to set the operations limit for.
  442.   /// @param LocalMaxOps Maximum number of operations allowed in the
  443.   ///                    scope. If set to zero, no operations limit is enforced.
  444.   /// @param AutoEnter   If true, automatically enters an IslQuotaScope such
  445.   ///                    that isl operations may return quota errors
  446.   ///                    immediately. If false, only starts the operations
  447.   ///                    counter, but isl does not return quota errors before
  448.   ///                    calling enter().
  449.   IslMaxOperationsGuard(isl_ctx *IslCtx, unsigned long LocalMaxOps,
  450.                         bool AutoEnter = true)
  451.       : IslCtx(IslCtx), LocalMaxOps(LocalMaxOps) {
  452.     assert(IslCtx);
  453.     assert(isl_ctx_get_max_operations(IslCtx) == 0 &&
  454.            "Nested max operations not supported");
  455.  
  456.     // Users of this guard may check whether the last error was isl_error_quota.
  457.     // Reset the last error such that a previous out-of-quota error is not
  458.     // mistaken to have occurred in the in this quota, even if the max number of
  459.     // operations is set to infinite (LocalMaxOps == 0).
  460.     isl_ctx_reset_error(IslCtx);
  461.  
  462.     if (LocalMaxOps == 0) {
  463.       // No limit on operations; also disable restoring on_error/max_operations.
  464.       this->IslCtx = nullptr;
  465.       return;
  466.     }
  467.  
  468.     isl_ctx_reset_operations(IslCtx);
  469.     TopLevelScope = enter(AutoEnter);
  470.   }
  471.  
  472.   /// Enter a scope that can handle out-of-quota errors.
  473.   ///
  474.   /// @param AllowReturnNull Whether the scoped code can handle out-of-quota
  475.   ///                        errors. If false, returns a dummy scope object that
  476.   ///                        does nothing.
  477.   IslQuotaScope enter(bool AllowReturnNull = true) {
  478.     return AllowReturnNull && IslCtx ? IslQuotaScope(IslCtx, LocalMaxOps)
  479.                                      : IslQuotaScope();
  480.   }
  481.  
  482.   /// Return whether the current quota has exceeded.
  483.   bool hasQuotaExceeded() const {
  484.     if (!IslCtx)
  485.       return false;
  486.  
  487.     return isl_ctx_last_error(IslCtx) == isl_error_quota;
  488.   }
  489. };
  490. } // end namespace polly
  491.  
  492. #endif
  493.