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