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_multi_pw_aff *mpa) { 148 return stringFromIslObjInternal(mpa, isl_multi_pw_aff_get_ctx, 149 isl_printer_print_multi_pw_aff); 150 } 151 152 std::string polly::stringFromIslObj(__isl_keep isl_union_pw_multi_aff *upma) { 153 return stringFromIslObjInternal(upma, isl_union_pw_multi_aff_get_ctx, 154 isl_printer_print_union_pw_multi_aff); 155 } 156 157 std::string polly::stringFromIslObj(__isl_keep isl_aff *aff) { 158 return stringFromIslObjInternal(aff, isl_aff_get_ctx, isl_printer_print_aff); 159 } 160 161 std::string polly::stringFromIslObj(__isl_keep isl_pw_aff *pwaff) { 162 return stringFromIslObjInternal(pwaff, isl_pw_aff_get_ctx, 163 isl_printer_print_pw_aff); 164 } 165 166 std::string polly::stringFromIslObj(__isl_keep isl_space *space) { 167 return stringFromIslObjInternal(space, isl_space_get_ctx, 168 isl_printer_print_space); 169 } 170 171 static void replace(std::string &str, const std::string &find, 172 const std::string &replace) { 173 size_t pos = 0; 174 while ((pos = str.find(find, pos)) != std::string::npos) { 175 str.replace(pos, find.length(), replace); 176 pos += replace.length(); 177 } 178 } 179 180 static void makeIslCompatible(std::string &str) { 181 replace(str, ".", "_"); 182 replace(str, "\"", "_"); 183 replace(str, " ", "__"); 184 replace(str, "=>", "TO"); 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 Value *Val, 197 const std::string &Suffix) { 198 std::string ValStr; 199 raw_string_ostream OS(ValStr); 200 Val->printAsOperand(OS, false); 201 ValStr = OS.str(); 202 // Remove the leading % 203 ValStr.erase(0, 1); 204 return getIslCompatibleName(Prefix, ValStr, Suffix); 205 } 206