175805378STobias Grosser //===- GmpConv.cpp - Recreate LLVM IR from the Scop. ---------------------===//
275805378STobias Grosser //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
675805378STobias Grosser //
775805378STobias Grosser //===----------------------------------------------------------------------===//
875805378STobias Grosser //
9a6d48f59SMichael Kruse // Functions for converting between gmp objects and llvm::APInt.
1075805378STobias Grosser //
1175805378STobias Grosser //===----------------------------------------------------------------------===//
12edab1359STobias Grosser
13031bb165SMichael Kruse #include "polly/Support/GICHelper.h"
14031bb165SMichael Kruse #include "llvm/ADT/APInt.h"
15031bb165SMichael Kruse #include "isl/val.h"
1676f8279eSTobias Grosser
1775805378STobias Grosser using namespace llvm;
1875805378STobias Grosser
isl_valFromAPInt(isl_ctx * Ctx,const APInt Int,bool IsSigned)19edab1359STobias Grosser __isl_give isl_val *polly::isl_valFromAPInt(isl_ctx *Ctx, const APInt Int,
20edab1359STobias Grosser bool IsSigned) {
21edab1359STobias Grosser APInt Abs;
22edab1359STobias Grosser isl_val *v;
23edab1359STobias Grosser
2443720008STobias Grosser // As isl is interpreting the input always as unsigned value, we need some
2543720008STobias Grosser // additional pre and post processing to import signed values. The approach
2643720008STobias Grosser // we take is to first obtain the absolute value of Int and then negate the
2743720008STobias Grosser // value after it has been imported to isl.
2843720008STobias Grosser //
2943720008STobias Grosser // It should be noted that the smallest integer value represented in two's
3043720008STobias Grosser // complement with a certain amount of bits does not have a corresponding
3143720008STobias Grosser // positive representation in two's complement representation with the same
3243720008STobias Grosser // number of bits. E.g. 110 (-2) does not have a corresponding value for (2).
3343720008STobias Grosser // To ensure that there is always a corresponding value available we first
3443720008STobias Grosser // sign-extend the input by one bit and only then take the absolute value.
35edab1359STobias Grosser if (IsSigned)
3643720008STobias Grosser Abs = Int.sext(Int.getBitWidth() + 1).abs();
37edab1359STobias Grosser else
38edab1359STobias Grosser Abs = Int;
39edab1359STobias Grosser
40edab1359STobias Grosser const uint64_t *Data = Abs.getRawData();
41edab1359STobias Grosser unsigned Words = Abs.getNumWords();
42edab1359STobias Grosser
43edab1359STobias Grosser v = isl_val_int_from_chunks(Ctx, Words, sizeof(uint64_t), Data);
44edab1359STobias Grosser
45edab1359STobias Grosser if (IsSigned && Int.isNegative())
46edab1359STobias Grosser v = isl_val_neg(v);
47edab1359STobias Grosser
48edab1359STobias Grosser return v;
49edab1359STobias Grosser }
50edab1359STobias Grosser
APIntFromVal(__isl_take isl_val * Val)51edab1359STobias Grosser APInt polly::APIntFromVal(__isl_take isl_val *Val) {
52edab1359STobias Grosser uint64_t *Data;
53edab1359STobias Grosser int NumChunks;
5476f8279eSTobias Grosser const static int ChunkSize = sizeof(uint64_t);
55edab1359STobias Grosser
5676f8279eSTobias Grosser assert(isl_val_is_int(Val) && "Only integers can be converted to APInt");
57edab1359STobias Grosser
5876f8279eSTobias Grosser NumChunks = isl_val_n_abs_num_chunks(Val, ChunkSize);
5976f8279eSTobias Grosser Data = (uint64_t *)malloc(NumChunks * ChunkSize);
6076f8279eSTobias Grosser isl_val_get_abs_num_chunks(Val, ChunkSize, Data);
6176f8279eSTobias Grosser int NumBits = CHAR_BIT * ChunkSize * NumChunks;
6276f8279eSTobias Grosser APInt A(NumBits, NumChunks, Data);
63edab1359STobias Grosser
6476f8279eSTobias Grosser // As isl provides only an interface to obtain data that describes the
6576f8279eSTobias Grosser // absolute value of an isl_val, A at this point always contains a positive
6676f8279eSTobias Grosser // number. In case Val was originally negative, we expand the size of A by
6776f8279eSTobias Grosser // one and negate the value (in two's complement representation). As a result,
6876f8279eSTobias Grosser // the new value in A corresponds now with Val.
69edab1359STobias Grosser if (isl_val_is_neg(Val)) {
70edab1359STobias Grosser A = A.zext(A.getBitWidth() + 1);
71edab1359STobias Grosser A = -A;
72edab1359STobias Grosser }
73edab1359STobias Grosser
7476f8279eSTobias Grosser // isl may represent small numbers with more than the minimal number of bits.
7576f8279eSTobias Grosser // We truncate the APInt to the minimal number of bits needed to represent the
7676f8279eSTobias Grosser // signed value it contains, to ensure that the bitwidth is always minimal.
77edab1359STobias Grosser if (A.getMinSignedBits() < A.getBitWidth())
78edab1359STobias Grosser A = A.trunc(A.getMinSignedBits());
79edab1359STobias Grosser
80edab1359STobias Grosser free(Data);
81edab1359STobias Grosser isl_val_free(Val);
82edab1359STobias Grosser return A;
83edab1359STobias Grosser }
84edab1359STobias Grosser
855205e0c4SHongbin Zheng template <typename ISLTy, typename ISL_CTX_GETTER, typename ISL_PRINTER>
stringFromIslObjInternal(__isl_keep ISLTy * isl_obj,ISL_CTX_GETTER ctx_getter_fn,ISL_PRINTER printer_fn,std::string DefaultValue)86e602a076STobias Grosser static inline std::string stringFromIslObjInternal(__isl_keep ISLTy *isl_obj,
87e602a076STobias Grosser ISL_CTX_GETTER ctx_getter_fn,
88cfe117deSpatacca ISL_PRINTER printer_fn,
89cfe117deSpatacca std::string DefaultValue) {
90b8d26447SMichael Kruse if (!isl_obj)
91cfe117deSpatacca return DefaultValue;
925205e0c4SHongbin Zheng isl_ctx *ctx = ctx_getter_fn(isl_obj);
935205e0c4SHongbin Zheng isl_printer *p = isl_printer_to_str(ctx);
94a2d80ba5STobias Grosser p = printer_fn(p, isl_obj);
9515f5efffSTobias Grosser char *char_str = isl_printer_get_str(p);
96b43cc62fSTobias Grosser std::string string;
97b43cc62fSTobias Grosser if (char_str)
98b43cc62fSTobias Grosser string = char_str;
99b43cc62fSTobias Grosser else
100cfe117deSpatacca string = DefaultValue;
10115f5efffSTobias Grosser free(char_str);
10275805378STobias Grosser isl_printer_free(p);
10375805378STobias Grosser return string;
10475805378STobias Grosser }
10575805378STobias Grosser
106cfe117deSpatacca #define ISL_C_OBJECT_TO_STRING(name) \
107cfe117deSpatacca std::string polly::stringFromIslObj(__isl_keep isl_##name *Obj, \
108cfe117deSpatacca std::string DefaultValue) { \
109cfe117deSpatacca return stringFromIslObjInternal(Obj, isl_##name##_get_ctx, \
110cfe117deSpatacca isl_printer_print_##name, DefaultValue); \
1115205e0c4SHongbin Zheng }
1125205e0c4SHongbin Zheng
113cfe117deSpatacca ISL_C_OBJECT_TO_STRING(aff)
ISL_C_OBJECT_TO_STRING(ast_expr)114cfe117deSpatacca ISL_C_OBJECT_TO_STRING(ast_expr)
115cfe117deSpatacca ISL_C_OBJECT_TO_STRING(ast_node)
116cfe117deSpatacca ISL_C_OBJECT_TO_STRING(basic_map)
117cfe117deSpatacca ISL_C_OBJECT_TO_STRING(basic_set)
118cfe117deSpatacca ISL_C_OBJECT_TO_STRING(map)
119cfe117deSpatacca ISL_C_OBJECT_TO_STRING(set)
120cfe117deSpatacca ISL_C_OBJECT_TO_STRING(id)
121cfe117deSpatacca ISL_C_OBJECT_TO_STRING(multi_aff)
122cfe117deSpatacca ISL_C_OBJECT_TO_STRING(multi_pw_aff)
123cfe117deSpatacca ISL_C_OBJECT_TO_STRING(multi_union_pw_aff)
124cfe117deSpatacca ISL_C_OBJECT_TO_STRING(point)
125cfe117deSpatacca ISL_C_OBJECT_TO_STRING(pw_aff)
126cfe117deSpatacca ISL_C_OBJECT_TO_STRING(pw_multi_aff)
127cfe117deSpatacca ISL_C_OBJECT_TO_STRING(schedule)
128cfe117deSpatacca ISL_C_OBJECT_TO_STRING(schedule_node)
129cfe117deSpatacca ISL_C_OBJECT_TO_STRING(space)
130cfe117deSpatacca ISL_C_OBJECT_TO_STRING(union_access_info)
131cfe117deSpatacca ISL_C_OBJECT_TO_STRING(union_flow)
132cfe117deSpatacca ISL_C_OBJECT_TO_STRING(union_set)
133cfe117deSpatacca ISL_C_OBJECT_TO_STRING(union_map)
134cfe117deSpatacca ISL_C_OBJECT_TO_STRING(union_pw_aff)
135cfe117deSpatacca ISL_C_OBJECT_TO_STRING(union_pw_multi_aff)
136a7bdd29cSHongbin Zheng
13779fc23f2SJohannes Doerfert static void replace(std::string &str, const std::string &find,
13879fc23f2SJohannes Doerfert const std::string &replace) {
13979fc23f2SJohannes Doerfert size_t pos = 0;
14079fc23f2SJohannes Doerfert while ((pos = str.find(find, pos)) != std::string::npos) {
14179fc23f2SJohannes Doerfert str.replace(pos, find.length(), replace);
14279fc23f2SJohannes Doerfert pos += replace.length();
14379fc23f2SJohannes Doerfert }
14479fc23f2SJohannes Doerfert }
14579fc23f2SJohannes Doerfert
makeIslCompatible(std::string & str)14679fc23f2SJohannes Doerfert static void makeIslCompatible(std::string &str) {
14779fc23f2SJohannes Doerfert replace(str, ".", "_");
14879fc23f2SJohannes Doerfert replace(str, "\"", "_");
14916c4403aSTobias Grosser replace(str, " ", "__");
15016c4403aSTobias Grosser replace(str, "=>", "TO");
1515ae08c0eSMichael Kruse replace(str, "+", "_");
15279fc23f2SJohannes Doerfert }
15379fc23f2SJohannes Doerfert
getIslCompatibleName(const std::string & Prefix,const std::string & Middle,const std::string & Suffix)1543a7e812cSJohannes Doerfert std::string polly::getIslCompatibleName(const std::string &Prefix,
1553a7e812cSJohannes Doerfert const std::string &Middle,
1563a7e812cSJohannes Doerfert const std::string &Suffix) {
1573a7e812cSJohannes Doerfert std::string S = Prefix + Middle + Suffix;
1583a7e812cSJohannes Doerfert makeIslCompatible(S);
1593a7e812cSJohannes Doerfert return S;
1603a7e812cSJohannes Doerfert }
1613a7e812cSJohannes Doerfert
getIslCompatibleName(const std::string & Prefix,const std::string & Name,long Number,const std::string & Suffix,bool UseInstructionNames)162f567e1aaSTobias Grosser std::string polly::getIslCompatibleName(const std::string &Prefix,
163e2ccc3fbSTobias Grosser const std::string &Name, long Number,
164e2ccc3fbSTobias Grosser const std::string &Suffix,
165e2ccc3fbSTobias Grosser bool UseInstructionNames) {
166e2ccc3fbSTobias Grosser std::string S = Prefix;
167e2ccc3fbSTobias Grosser
168e2ccc3fbSTobias Grosser if (UseInstructionNames)
169e2ccc3fbSTobias Grosser S += std::string("_") + Name;
170e2ccc3fbSTobias Grosser else
171e2ccc3fbSTobias Grosser S += std::to_string(Number);
172e2ccc3fbSTobias Grosser
173e2ccc3fbSTobias Grosser S += Suffix;
174e2ccc3fbSTobias Grosser
175e2ccc3fbSTobias Grosser makeIslCompatible(S);
176e2ccc3fbSTobias Grosser return S;
177e2ccc3fbSTobias Grosser }
178e2ccc3fbSTobias Grosser
getIslCompatibleName(const std::string & Prefix,const Value * Val,long Number,const std::string & Suffix,bool UseInstructionNames)179e2ccc3fbSTobias Grosser std::string polly::getIslCompatibleName(const std::string &Prefix,
180e2ccc3fbSTobias Grosser const Value *Val, long Number,
181e2ccc3fbSTobias Grosser const std::string &Suffix,
182e2ccc3fbSTobias Grosser bool UseInstructionNames) {
18379fc23f2SJohannes Doerfert std::string ValStr;
184e2ccc3fbSTobias Grosser
185e2ccc3fbSTobias Grosser if (UseInstructionNames && Val->hasName())
186e2ccc3fbSTobias Grosser ValStr = std::string("_") + std::string(Val->getName());
187e2ccc3fbSTobias Grosser else
188e2ccc3fbSTobias Grosser ValStr = std::to_string(Number);
189e2ccc3fbSTobias Grosser
1903a7e812cSJohannes Doerfert return getIslCompatibleName(Prefix, ValStr, Suffix);
19179fc23f2SJohannes Doerfert }
19289d2be07SMichael Kruse
19389d2be07SMichael Kruse #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
194*ec2029f9SMichael Kruse #define ISL_DUMP_OBJECT_IMPL(NAME) \
195*ec2029f9SMichael Kruse void polly::dumpIslObj(const isl::NAME &Obj) { \
196*ec2029f9SMichael Kruse isl_##NAME##_dump(Obj.get()); \
197*ec2029f9SMichael Kruse } \
198*ec2029f9SMichael Kruse void polly::dumpIslObj(isl_##NAME *Obj) { isl_##NAME##_dump(Obj); }
199*ec2029f9SMichael Kruse
200*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(aff)
ISL_DUMP_OBJECT_IMPL(aff_list)201*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(aff_list)
202*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(ast_expr)
203*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(ast_node)
204*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(ast_node_list)
205*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(basic_map)
206*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(basic_map_list)
207*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(basic_set)
208*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(basic_set_list)
209*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(constraint)
210*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(id)
211*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(id_list)
212*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(id_to_ast_expr)
213*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(local_space)
214*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(map)
215*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(map_list)
216*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(multi_aff)
217*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(multi_pw_aff)
218*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(multi_union_pw_aff)
219*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(multi_val)
220*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(point)
221*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(pw_aff)
222*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(pw_aff_list)
223*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(pw_multi_aff)
224*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(schedule)
225*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(schedule_constraints)
226*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(schedule_node)
227*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(set)
228*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(set_list)
229*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(space)
230*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(union_map)
231*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(union_pw_aff)
232*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(union_pw_aff_list)
233*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(union_pw_multi_aff)
234*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(union_set)
235*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(union_set_list)
236*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(val)
237*ec2029f9SMichael Kruse ISL_DUMP_OBJECT_IMPL(val_list)
23864489255SMichael Kruse
23964489255SMichael Kruse void polly::dumpIslObj(__isl_keep isl_schedule_node *node, raw_ostream &OS) {
24064489255SMichael Kruse if (!node)
24164489255SMichael Kruse return;
24264489255SMichael Kruse
24364489255SMichael Kruse isl_ctx *ctx = isl_schedule_node_get_ctx(node);
24464489255SMichael Kruse isl_printer *p = isl_printer_to_str(ctx);
24564489255SMichael Kruse p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_BLOCK);
24664489255SMichael Kruse p = isl_printer_print_schedule_node(p, node);
24764489255SMichael Kruse
24864489255SMichael Kruse char *char_str = isl_printer_get_str(p);
24964489255SMichael Kruse OS << char_str;
25064489255SMichael Kruse
25164489255SMichael Kruse free(char_str);
25264489255SMichael Kruse isl_printer_free(p);
25364489255SMichael Kruse }
25464489255SMichael Kruse
dumpIslObj(const isl::schedule_node & Node,raw_ostream & OS)25564489255SMichael Kruse void polly::dumpIslObj(const isl::schedule_node &Node, raw_ostream &OS) {
25664489255SMichael Kruse dumpIslObj(Node.get(), OS);
25764489255SMichael Kruse }
25864489255SMichael Kruse
25989d2be07SMichael Kruse #endif
260