1 //===- GmpConv.cpp - Recreate LLVM IR from the Scop. ---------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Functions for converting between gmp objects and apint. 11 // 12 //===----------------------------------------------------------------------===// 13 #include "polly/Support/GICHelper.h" 14 #include "llvm/IR/Value.h" 15 #include "isl/aff.h" 16 #include "isl/map.h" 17 #include "isl/schedule.h" 18 #include "isl/set.h" 19 #include "isl/space.h" 20 #include "isl/union_map.h" 21 #include "isl/union_set.h" 22 #include "isl/val.h" 23 24 #include <climits> 25 26 using namespace llvm; 27 28 __isl_give isl_val *polly::isl_valFromAPInt(isl_ctx *Ctx, const APInt Int, 29 bool IsSigned) { 30 APInt Abs; 31 isl_val *v; 32 33 // As isl is interpreting the input always as unsigned value, we need some 34 // additional pre and post processing to import signed values. The approach 35 // we take is to first obtain the absolute value of Int and then negate the 36 // value after it has been imported to isl. 37 // 38 // It should be noted that the smallest integer value represented in two's 39 // complement with a certain amount of bits does not have a corresponding 40 // positive representation in two's complement representation with the same 41 // number of bits. E.g. 110 (-2) does not have a corresponding value for (2). 42 // To ensure that there is always a corresponding value available we first 43 // sign-extend the input by one bit and only then take the absolute value. 44 if (IsSigned) 45 Abs = Int.sext(Int.getBitWidth() + 1).abs(); 46 else 47 Abs = Int; 48 49 const uint64_t *Data = Abs.getRawData(); 50 unsigned Words = Abs.getNumWords(); 51 52 v = isl_val_int_from_chunks(Ctx, Words, sizeof(uint64_t), Data); 53 54 if (IsSigned && Int.isNegative()) 55 v = isl_val_neg(v); 56 57 return v; 58 } 59 60 APInt polly::APIntFromVal(__isl_take isl_val *Val) { 61 uint64_t *Data; 62 int NumChunks; 63 const static int ChunkSize = sizeof(uint64_t); 64 65 assert(isl_val_is_int(Val) && "Only integers can be converted to APInt"); 66 67 NumChunks = isl_val_n_abs_num_chunks(Val, ChunkSize); 68 Data = (uint64_t *)malloc(NumChunks * ChunkSize); 69 isl_val_get_abs_num_chunks(Val, ChunkSize, Data); 70 int NumBits = CHAR_BIT * ChunkSize * NumChunks; 71 APInt A(NumBits, NumChunks, Data); 72 73 // As isl provides only an interface to obtain data that describes the 74 // absolute value of an isl_val, A at this point always contains a positive 75 // number. In case Val was originally negative, we expand the size of A by 76 // one and negate the value (in two's complement representation). As a result, 77 // the new value in A corresponds now with Val. 78 if (isl_val_is_neg(Val)) { 79 A = A.zext(A.getBitWidth() + 1); 80 A = -A; 81 } 82 83 // isl may represent small numbers with more than the minimal number of bits. 84 // We truncate the APInt to the minimal number of bits needed to represent the 85 // signed value it contains, to ensure that the bitwidth is always minimal. 86 if (A.getMinSignedBits() < A.getBitWidth()) 87 A = A.trunc(A.getMinSignedBits()); 88 89 free(Data); 90 isl_val_free(Val); 91 return A; 92 } 93 94 template <typename ISLTy, typename ISL_CTX_GETTER, typename ISL_PRINTER> 95 static inline std::string stringFromIslObjInternal(__isl_keep ISLTy *isl_obj, 96 ISL_CTX_GETTER ctx_getter_fn, 97 ISL_PRINTER printer_fn) { 98 if (!isl_obj) 99 return "null"; 100 isl_ctx *ctx = ctx_getter_fn(isl_obj); 101 isl_printer *p = isl_printer_to_str(ctx); 102 p = printer_fn(p, isl_obj); 103 char *char_str = isl_printer_get_str(p); 104 std::string string; 105 if (char_str) 106 string = char_str; 107 else 108 string = "null"; 109 free(char_str); 110 isl_printer_free(p); 111 return string; 112 } 113 114 std::string polly::stringFromIslObj(__isl_keep isl_map *map) { 115 return stringFromIslObjInternal(map, isl_map_get_ctx, isl_printer_print_map); 116 } 117 118 std::string polly::stringFromIslObj(__isl_keep isl_set *set) { 119 return stringFromIslObjInternal(set, isl_set_get_ctx, isl_printer_print_set); 120 } 121 122 std::string polly::stringFromIslObj(__isl_keep isl_union_map *umap) { 123 return stringFromIslObjInternal(umap, isl_union_map_get_ctx, 124 isl_printer_print_union_map); 125 } 126 127 std::string polly::stringFromIslObj(__isl_keep isl_union_set *uset) { 128 return stringFromIslObjInternal(uset, isl_union_set_get_ctx, 129 isl_printer_print_union_set); 130 } 131 132 std::string polly::stringFromIslObj(__isl_keep isl_schedule *schedule) { 133 return stringFromIslObjInternal(schedule, isl_schedule_get_ctx, 134 isl_printer_print_schedule); 135 } 136 137 std::string polly::stringFromIslObj(__isl_keep isl_multi_aff *maff) { 138 return stringFromIslObjInternal(maff, isl_multi_aff_get_ctx, 139 isl_printer_print_multi_aff); 140 } 141 142 std::string polly::stringFromIslObj(__isl_keep isl_pw_multi_aff *pma) { 143 return stringFromIslObjInternal(pma, isl_pw_multi_aff_get_ctx, 144 isl_printer_print_pw_multi_aff); 145 } 146 147 std::string polly::stringFromIslObj(__isl_keep isl_union_pw_multi_aff *upma) { 148 return stringFromIslObjInternal(upma, isl_union_pw_multi_aff_get_ctx, 149 isl_printer_print_union_pw_multi_aff); 150 } 151 152 std::string polly::stringFromIslObj(__isl_keep isl_aff *aff) { 153 return stringFromIslObjInternal(aff, isl_aff_get_ctx, isl_printer_print_aff); 154 } 155 156 std::string polly::stringFromIslObj(__isl_keep isl_pw_aff *pwaff) { 157 return stringFromIslObjInternal(pwaff, isl_pw_aff_get_ctx, 158 isl_printer_print_pw_aff); 159 } 160 161 std::string polly::stringFromIslObj(__isl_keep isl_space *space) { 162 return stringFromIslObjInternal(space, isl_space_get_ctx, 163 isl_printer_print_space); 164 } 165 166 static void replace(std::string &str, const std::string &find, 167 const std::string &replace) { 168 size_t pos = 0; 169 while ((pos = str.find(find, pos)) != std::string::npos) { 170 str.replace(pos, find.length(), replace); 171 pos += replace.length(); 172 } 173 } 174 175 static void makeIslCompatible(std::string &str) { 176 replace(str, ".", "_"); 177 replace(str, "\"", "_"); 178 replace(str, " ", "__"); 179 replace(str, "=>", "TO"); 180 } 181 182 std::string polly::getIslCompatibleName(const std::string &Prefix, 183 const std::string &Middle, 184 const std::string &Suffix) { 185 std::string S = Prefix + Middle + Suffix; 186 makeIslCompatible(S); 187 return S; 188 } 189 190 std::string polly::getIslCompatibleName(const std::string &Prefix, 191 const Value *Val, 192 const std::string &Suffix) { 193 std::string ValStr; 194 raw_string_ostream OS(ValStr); 195 Val->printAsOperand(OS, false); 196 ValStr = OS.str(); 197 // Remove the leading % 198 ValStr.erase(0, 1); 199 return getIslCompatibleName(Prefix, ValStr, Suffix); 200 } 201 202 #define DEFINE_ISLPTR(TYPE) \ 203 template <> void IslPtr<isl_##TYPE>::dump() const { \ 204 isl_##TYPE##_dump(Obj); \ 205 } \ 206 template <> void NonowningIslPtr<isl_##TYPE>::dump() const { \ 207 isl_##TYPE##_dump(Obj); \ 208 } 209 210 namespace polly { 211 DEFINE_ISLPTR(id) 212 DEFINE_ISLPTR(val) 213 DEFINE_ISLPTR(space) 214 DEFINE_ISLPTR(basic_map) 215 DEFINE_ISLPTR(map) 216 DEFINE_ISLPTR(union_map) 217 DEFINE_ISLPTR(basic_set) 218 DEFINE_ISLPTR(set) 219 DEFINE_ISLPTR(union_set) 220 DEFINE_ISLPTR(aff) 221 DEFINE_ISLPTR(multi_aff) 222 DEFINE_ISLPTR(pw_aff) 223 DEFINE_ISLPTR(union_pw_aff) 224 DEFINE_ISLPTR(multi_union_pw_aff) 225 DEFINE_ISLPTR(union_pw_multi_aff) 226 } 227 228 void polly::foreachElt(NonowningIslPtr<isl_map> Map, 229 const std::function<void(IslPtr<isl_basic_map>)> &F) { 230 isl_map_foreach_basic_map( 231 Map.keep(), 232 [](__isl_take isl_basic_map *BMap, void *User) -> isl_stat { 233 auto &F = 234 *static_cast<const std::function<void(IslPtr<isl_basic_map>)> *>( 235 User); 236 F(give(BMap)); 237 return isl_stat_ok; 238 }, 239 const_cast<void *>(static_cast<const void *>(&F))); 240 } 241 242 void polly::foreachElt(NonowningIslPtr<isl_set> Set, 243 const std::function<void(IslPtr<isl_basic_set>)> &F) { 244 isl_set_foreach_basic_set( 245 Set.keep(), 246 [](__isl_take isl_basic_set *BSet, void *User) -> isl_stat { 247 auto &F = 248 *static_cast<const std::function<void(IslPtr<isl_basic_set>)> *>( 249 User); 250 F(give(BSet)); 251 return isl_stat_ok; 252 }, 253 const_cast<void *>(static_cast<const void *>(&F))); 254 } 255 256 void polly::foreachElt(NonowningIslPtr<isl_union_map> UMap, 257 const std::function<void(IslPtr<isl_map> Map)> &F) { 258 isl_union_map_foreach_map( 259 UMap.keep(), 260 [](__isl_take isl_map *Map, void *User) -> isl_stat { 261 auto &F = 262 *static_cast<const std::function<void(IslPtr<isl_map>)> *>(User); 263 F(give(Map)); 264 return isl_stat_ok; 265 }, 266 const_cast<void *>(static_cast<const void *>(&F))); 267 } 268 269 void polly::foreachElt(NonowningIslPtr<isl_union_set> USet, 270 const std::function<void(IslPtr<isl_set> Set)> &F) { 271 isl_union_set_foreach_set( 272 USet.keep(), 273 [](__isl_take isl_set *Set, void *User) -> isl_stat { 274 auto &F = 275 *static_cast<const std::function<void(IslPtr<isl_set>)> *>(User); 276 F(give(Set)); 277 return isl_stat_ok; 278 }, 279 const_cast<void *>(static_cast<const void *>(&F))); 280 } 281 282 void polly::foreachElt(NonowningIslPtr<isl_union_pw_aff> UPwAff, 283 const std::function<void(IslPtr<isl_pw_aff>)> &F) { 284 isl_union_pw_aff_foreach_pw_aff( 285 UPwAff.keep(), 286 [](__isl_take isl_pw_aff *PwAff, void *User) -> isl_stat { 287 auto &F = 288 *static_cast<const std::function<void(IslPtr<isl_pw_aff>)> *>(User); 289 F(give(PwAff)); 290 return isl_stat_ok; 291 }, 292 const_cast<void *>(static_cast<const void *>(&F))); 293 } 294 295 isl_stat polly::foreachEltWithBreak( 296 NonowningIslPtr<isl_map> Map, 297 const std::function<isl_stat(IslPtr<isl_basic_map>)> &F) { 298 return isl_map_foreach_basic_map( 299 Map.keep(), 300 [](__isl_take isl_basic_map *BMap, void *User) -> isl_stat { 301 auto &F = *static_cast< 302 const std::function<isl_stat(IslPtr<isl_basic_map>)> *>(User); 303 return F(give(BMap)); 304 }, 305 const_cast<void *>(static_cast<const void *>(&F))); 306 } 307 308 isl_stat polly::foreachEltWithBreak( 309 NonowningIslPtr<isl_union_map> UMap, 310 const std::function<isl_stat(IslPtr<isl_map> Map)> &F) { 311 return isl_union_map_foreach_map( 312 UMap.keep(), 313 [](__isl_take isl_map *Map, void *User) -> isl_stat { 314 auto &F = 315 *static_cast<const std::function<isl_stat(IslPtr<isl_map> Map)> *>( 316 User); 317 return F(give(Map)); 318 }, 319 const_cast<void *>(static_cast<const void *>(&F))); 320 } 321 322 isl_stat polly::foreachPieceWithBreak( 323 NonowningIslPtr<isl_pw_aff> PwAff, 324 const std::function<isl_stat(IslPtr<isl_set>, IslPtr<isl_aff>)> &F) { 325 return isl_pw_aff_foreach_piece( 326 PwAff.keep(), 327 [](__isl_take isl_set *Domain, __isl_take isl_aff *Aff, 328 void *User) -> isl_stat { 329 auto &F = *static_cast< 330 const std::function<isl_stat(IslPtr<isl_set>, IslPtr<isl_aff>)> *>( 331 User); 332 return F(give(Domain), give(Aff)); 333 }, 334 const_cast<void *>(static_cast<const void *>(&F))); 335 } 336