1 //===- GmpConv.cpp - Recreate LLVM IR from the Scop. ---------------------===// 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 // Functions for converting between gmp objects and llvm::APInt. 10 // 11 //===----------------------------------------------------------------------===// 12 #include "polly/Support/GICHelper.h" 13 #include "llvm/IR/Value.h" 14 #include "isl/aff.h" 15 #include "isl/map.h" 16 #include "isl/schedule.h" 17 #include "isl/set.h" 18 #include "isl/space.h" 19 #include "isl/union_map.h" 20 #include "isl/union_set.h" 21 #include "isl/val.h" 22 23 #include <climits> 24 25 using namespace llvm; 26 27 __isl_give isl_val *polly::isl_valFromAPInt(isl_ctx *Ctx, const APInt Int, 28 bool IsSigned) { 29 APInt Abs; 30 isl_val *v; 31 32 // As isl is interpreting the input always as unsigned value, we need some 33 // additional pre and post processing to import signed values. The approach 34 // we take is to first obtain the absolute value of Int and then negate the 35 // value after it has been imported to isl. 36 // 37 // It should be noted that the smallest integer value represented in two's 38 // complement with a certain amount of bits does not have a corresponding 39 // positive representation in two's complement representation with the same 40 // number of bits. E.g. 110 (-2) does not have a corresponding value for (2). 41 // To ensure that there is always a corresponding value available we first 42 // sign-extend the input by one bit and only then take the absolute value. 43 if (IsSigned) 44 Abs = Int.sext(Int.getBitWidth() + 1).abs(); 45 else 46 Abs = Int; 47 48 const uint64_t *Data = Abs.getRawData(); 49 unsigned Words = Abs.getNumWords(); 50 51 v = isl_val_int_from_chunks(Ctx, Words, sizeof(uint64_t), Data); 52 53 if (IsSigned && Int.isNegative()) 54 v = isl_val_neg(v); 55 56 return v; 57 } 58 59 APInt polly::APIntFromVal(__isl_take isl_val *Val) { 60 uint64_t *Data; 61 int NumChunks; 62 const static int ChunkSize = sizeof(uint64_t); 63 64 assert(isl_val_is_int(Val) && "Only integers can be converted to APInt"); 65 66 NumChunks = isl_val_n_abs_num_chunks(Val, ChunkSize); 67 Data = (uint64_t *)malloc(NumChunks * ChunkSize); 68 isl_val_get_abs_num_chunks(Val, ChunkSize, Data); 69 int NumBits = CHAR_BIT * ChunkSize * NumChunks; 70 APInt A(NumBits, NumChunks, Data); 71 72 // As isl provides only an interface to obtain data that describes the 73 // absolute value of an isl_val, A at this point always contains a positive 74 // number. In case Val was originally negative, we expand the size of A by 75 // one and negate the value (in two's complement representation). As a result, 76 // the new value in A corresponds now with Val. 77 if (isl_val_is_neg(Val)) { 78 A = A.zext(A.getBitWidth() + 1); 79 A = -A; 80 } 81 82 // isl may represent small numbers with more than the minimal number of bits. 83 // We truncate the APInt to the minimal number of bits needed to represent the 84 // signed value it contains, to ensure that the bitwidth is always minimal. 85 if (A.getMinSignedBits() < A.getBitWidth()) 86 A = A.trunc(A.getMinSignedBits()); 87 88 free(Data); 89 isl_val_free(Val); 90 return A; 91 } 92 93 template <typename ISLTy, typename ISL_CTX_GETTER, typename ISL_PRINTER> 94 static inline std::string stringFromIslObjInternal(__isl_keep ISLTy *isl_obj, 95 ISL_CTX_GETTER ctx_getter_fn, 96 ISL_PRINTER printer_fn) { 97 if (!isl_obj) 98 return "null"; 99 isl_ctx *ctx = ctx_getter_fn(isl_obj); 100 isl_printer *p = isl_printer_to_str(ctx); 101 p = printer_fn(p, isl_obj); 102 char *char_str = isl_printer_get_str(p); 103 std::string string; 104 if (char_str) 105 string = char_str; 106 else 107 string = "null"; 108 free(char_str); 109 isl_printer_free(p); 110 return string; 111 } 112 113 std::string polly::stringFromIslObj(__isl_keep isl_map *map) { 114 return stringFromIslObjInternal(map, isl_map_get_ctx, isl_printer_print_map); 115 } 116 117 std::string polly::stringFromIslObj(__isl_keep isl_set *set) { 118 return stringFromIslObjInternal(set, isl_set_get_ctx, isl_printer_print_set); 119 } 120 121 std::string polly::stringFromIslObj(__isl_keep isl_union_map *umap) { 122 return stringFromIslObjInternal(umap, isl_union_map_get_ctx, 123 isl_printer_print_union_map); 124 } 125 126 std::string polly::stringFromIslObj(__isl_keep isl_union_set *uset) { 127 return stringFromIslObjInternal(uset, isl_union_set_get_ctx, 128 isl_printer_print_union_set); 129 } 130 131 std::string polly::stringFromIslObj(__isl_keep isl_schedule *schedule) { 132 return stringFromIslObjInternal(schedule, isl_schedule_get_ctx, 133 isl_printer_print_schedule); 134 } 135 136 std::string polly::stringFromIslObj(__isl_keep isl_multi_aff *maff) { 137 return stringFromIslObjInternal(maff, isl_multi_aff_get_ctx, 138 isl_printer_print_multi_aff); 139 } 140 141 std::string polly::stringFromIslObj(__isl_keep isl_pw_multi_aff *pma) { 142 return stringFromIslObjInternal(pma, isl_pw_multi_aff_get_ctx, 143 isl_printer_print_pw_multi_aff); 144 } 145 146 std::string polly::stringFromIslObj(__isl_keep isl_multi_pw_aff *mpa) { 147 return stringFromIslObjInternal(mpa, isl_multi_pw_aff_get_ctx, 148 isl_printer_print_multi_pw_aff); 149 } 150 151 std::string polly::stringFromIslObj(__isl_keep isl_union_pw_multi_aff *upma) { 152 return stringFromIslObjInternal(upma, isl_union_pw_multi_aff_get_ctx, 153 isl_printer_print_union_pw_multi_aff); 154 } 155 156 std::string polly::stringFromIslObj(__isl_keep isl_aff *aff) { 157 return stringFromIslObjInternal(aff, isl_aff_get_ctx, isl_printer_print_aff); 158 } 159 160 std::string polly::stringFromIslObj(__isl_keep isl_pw_aff *pwaff) { 161 return stringFromIslObjInternal(pwaff, isl_pw_aff_get_ctx, 162 isl_printer_print_pw_aff); 163 } 164 165 std::string polly::stringFromIslObj(__isl_keep isl_space *space) { 166 return stringFromIslObjInternal(space, isl_space_get_ctx, 167 isl_printer_print_space); 168 } 169 170 static void replace(std::string &str, const std::string &find, 171 const std::string &replace) { 172 size_t pos = 0; 173 while ((pos = str.find(find, pos)) != std::string::npos) { 174 str.replace(pos, find.length(), replace); 175 pos += replace.length(); 176 } 177 } 178 179 static void makeIslCompatible(std::string &str) { 180 replace(str, ".", "_"); 181 replace(str, "\"", "_"); 182 replace(str, " ", "__"); 183 replace(str, "=>", "TO"); 184 replace(str, "+", "_"); 185 } 186 187 std::string polly::getIslCompatibleName(const std::string &Prefix, 188 const std::string &Middle, 189 const std::string &Suffix) { 190 std::string S = Prefix + Middle + Suffix; 191 makeIslCompatible(S); 192 return S; 193 } 194 195 std::string polly::getIslCompatibleName(const std::string &Prefix, 196 const std::string &Name, long Number, 197 const std::string &Suffix, 198 bool UseInstructionNames) { 199 std::string S = Prefix; 200 201 if (UseInstructionNames) 202 S += std::string("_") + Name; 203 else 204 S += std::to_string(Number); 205 206 S += Suffix; 207 208 makeIslCompatible(S); 209 return S; 210 } 211 212 std::string polly::getIslCompatibleName(const std::string &Prefix, 213 const Value *Val, long Number, 214 const std::string &Suffix, 215 bool UseInstructionNames) { 216 std::string ValStr; 217 218 if (UseInstructionNames && Val->hasName()) 219 ValStr = std::string("_") + std::string(Val->getName()); 220 else 221 ValStr = std::to_string(Number); 222 223 return getIslCompatibleName(Prefix, ValStr, Suffix); 224 } 225 226 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 227 /// To call a inline dump() method in a debugger, at it must have been 228 /// instantiated in at least one translation unit. Because isl's dump() method 229 /// are meant to be called from a debugger only, but not from code, no such 230 /// instantiation would exist. We use this method to force an instantiation in 231 /// this translation unit. Because it has non-static linking, the compiler does 232 /// not know that it is never called, and therefore must ensure the existence of 233 /// the dump functions. 234 void neverCalled() { 235 isl::aff().dump(); 236 isl::aff_list().dump(); 237 isl::ast_expr().dump(); 238 isl::ast_expr_list().dump(); 239 isl::ast_node().dump(); 240 isl::ast_node_list().dump(); 241 isl::basic_map().dump(); 242 isl::basic_map_list().dump(); 243 isl::basic_set().dump(); 244 isl::basic_set_list().dump(); 245 isl::constraint().dump(); 246 isl::constraint_list().dump(); 247 isl::id().dump(); 248 isl::id_list().dump(); 249 isl::id_to_ast_expr().dump(); 250 isl::local_space().dump(); 251 isl::map().dump(); 252 isl::map_list().dump(); 253 isl::multi_aff().dump(); 254 isl::multi_pw_aff().dump(); 255 isl::multi_union_pw_aff().dump(); 256 isl::multi_val().dump(); 257 isl::point().dump(); 258 isl::pw_aff().dump(); 259 isl::pw_aff_list().dump(); 260 isl::pw_multi_aff().dump(); 261 isl::pw_qpolynomial().dump(); 262 isl::qpolynomial().dump(); 263 isl::schedule().dump(); 264 isl::schedule_constraints().dump(); 265 isl::schedule_node().dump(); 266 isl::set().dump(); 267 isl::set_list().dump(); 268 isl::space().dump(); 269 isl::union_map().dump(); 270 isl::union_map_list().dump(); 271 isl::union_pw_aff().dump(); 272 isl::union_pw_aff_list().dump(); 273 isl::union_pw_multi_aff().dump(); 274 isl::union_pw_multi_aff_list().dump(); 275 isl::union_set().dump(); 276 isl::union_set_list().dump(); 277 isl::val().dump(); 278 isl::val_list().dump(); 279 } 280 #endif 281