Branch data Line data Source code
1 : : // This file is a part of Julia. License is MIT: https://julialang.org/license
2 : :
3 : : namespace JL_I {
4 : : #include "intrinsics.h"
5 : : }
6 : :
7 : : #include "ccall.cpp"
8 : :
9 : : //Mark our stats as being from intrinsics irgen
10 : : #undef DEBUG_TYPE
11 : : #define DEBUG_TYPE "julia_irgen_intrinsics"
12 : :
13 : : STATISTIC(EmittedConstants, "Number of constants emitted");
14 : : STATISTIC(EmittedCoercedUnboxes, "Number of unbox coercions emitted");
15 : : STATISTIC(EmittedUnboxes, "Number of unboxes emitted");
16 : : STATISTIC(EmittedRuntimeCalls, "Number of runtime intrinsic calls emitted");
17 : : STATISTIC(EmittedIntrinsics, "Number of intrinsic calls emitted");
18 : : STATISTIC(Emitted_arraylen, "Number of arraylen calls emitted");
19 : : STATISTIC(Emitted_pointerref, "Number of pointerref calls emitted");
20 : : STATISTIC(Emitted_pointerset, "Number of pointerset calls emitted");
21 : : STATISTIC(Emitted_atomic_fence, "Number of atomic_fence calls emitted");
22 : : STATISTIC(Emitted_atomic_pointerref, "Number of atomic_pointerref calls emitted");
23 : : STATISTIC(Emitted_atomic_pointerop, "Number of atomic_pointerop calls emitted");
24 : : STATISTIC(Emitted_bitcast, "Number of bitcast calls emitted");
25 : : STATISTIC(Emitted_trunc_int, "Number of trunc_int calls emitted");
26 : : STATISTIC(Emitted_sext_int, "Number of sext_int calls emitted");
27 : : STATISTIC(Emitted_zext_int, "Number of zext_int calls emitted");
28 : : STATISTIC(Emitted_uitofp, "Number of uitofp calls emitted");
29 : : STATISTIC(Emitted_sitofp, "Number of sitofp calls emitted");
30 : : STATISTIC(Emitted_fptoui, "Number of fptoui calls emitted");
31 : : STATISTIC(Emitted_fptosi, "Number of fptosi calls emitted");
32 : : STATISTIC(Emitted_fptrunc, "Number of fptrunc calls emitted");
33 : : STATISTIC(Emitted_fpext, "Number of fpext calls emitted");
34 : : STATISTIC(Emitted_not_int, "Number of not_int calls emitted");
35 : : STATISTIC(Emitted_have_fma, "Number of have_fma calls emitted");
36 : : STATISTIC(EmittedUntypedIntrinsics, "Number of untyped intrinsics emitted");
37 : :
38 : : using namespace JL_I;
39 : :
40 : 41 : FunctionType *get_intr_args1(LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), {JuliaType::get_prjlvalue_ty(C)}, false); }
41 : 104 : FunctionType *get_intr_args2(LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), {JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C)}, false); }
42 : 2 : FunctionType *get_intr_args3(LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), {JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C)}, false); }
43 : 0 : FunctionType *get_intr_args4(LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), {JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C)}, false); }
44 : 0 : FunctionType *get_intr_args5(LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), {JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C)}, false); }
45 : :
46 : 206 : const auto &runtime_func() {
47 : : static struct runtime_funcs_t {
48 : : std::array<JuliaFunction *, num_intrinsics> runtime_func;
49 : 13 : runtime_funcs_t() :
50 : : runtime_func{
51 : : #define ADD_I(name, nargs) new JuliaFunction{XSTR(jl_##name), get_intr_args##nargs, nullptr},
52 : : #define ADD_HIDDEN ADD_I
53 : : #define ALIAS(alias, base) nullptr,
54 : 13 : INTRINSICS
55 : : #undef ADD_I
56 : : #undef ADD_HIDDEN
57 : : #undef ALIAS
58 : 13 : }
59 : : {
60 : : #define ADD_I(name, nargs)
61 : : #define ADD_HIDDEN(name, nargs)
62 : : #define ALIAS(alias, base) runtime_func[alias] = runtime_func[base];
63 : 13 : INTRINSICS
64 : : #undef ADD_I
65 : : #undef ADD_HIDDEN
66 : : #undef ALIAS
67 : 13 : }
68 [ + + + - ]: 206 : } runtime_funcs;
69 : 206 : return runtime_funcs.runtime_func;
70 : : }
71 : :
72 : 1078900 : const auto &float_func() {
73 : : static struct float_funcs_t {
74 : : std::bitset<num_intrinsics> float_func;
75 : 15 : float_funcs_t() {
76 : 15 : float_func[neg_float] = true;
77 : 15 : float_func[neg_float_fast] = true;
78 : 15 : float_func[add_float] = true;
79 : 15 : float_func[sub_float] = true;
80 : 15 : float_func[mul_float] = true;
81 : 15 : float_func[div_float] = true;
82 : 15 : float_func[rem_float] = true;
83 : 15 : float_func[add_float_fast] = true;
84 : 15 : float_func[sub_float_fast] = true;
85 : 15 : float_func[mul_float_fast] = true;
86 : 15 : float_func[div_float_fast] = true;
87 : 15 : float_func[rem_float_fast] = true;
88 : 15 : float_func[fma_float] = true;
89 : 15 : float_func[muladd_float] = true;
90 : 15 : float_func[eq_float] = true;
91 : 15 : float_func[ne_float] = true;
92 : 15 : float_func[lt_float] = true;
93 : 15 : float_func[le_float] = true;
94 : 15 : float_func[eq_float_fast] = true;
95 : 15 : float_func[ne_float_fast] = true;
96 : 15 : float_func[lt_float_fast] = true;
97 : 15 : float_func[le_float_fast] = true;
98 : 15 : float_func[fpiseq] = true;
99 : 15 : float_func[abs_float] = true;
100 : 15 : float_func[copysign_float] = true;
101 : 15 : float_func[ceil_llvm] = true;
102 : 15 : float_func[floor_llvm] = true;
103 : 15 : float_func[trunc_llvm] = true;
104 : 15 : float_func[rint_llvm] = true;
105 : 15 : float_func[sqrt_llvm] = true;
106 : 15 : float_func[sqrt_llvm_fast] = true;
107 : 15 : }
108 [ + + + - ]: 1078900 : } float_funcs;
109 : :
110 : 1078900 : return float_funcs.float_func;
111 : : }
112 : :
113 : : extern "C"
114 : 2 : JL_DLLEXPORT uint32_t jl_get_LLVM_VERSION_impl(void)
115 : : {
116 : : return 10000 * LLVM_VERSION_MAJOR + 100 * LLVM_VERSION_MINOR
117 : : #ifdef LLVM_VERSION_PATCH
118 : 2 : + LLVM_VERSION_PATCH
119 : : #endif
120 : : ;
121 : : }
122 : :
123 : : /*
124 : : low-level intrinsics design:
125 : : intrinsics only operate on bitstype values
126 : : any composite type is expected to be handled via its constructor,
127 : : so it is not permitted here
128 : : functions like add_int expect unboxed values of matching types
129 : : every operation that can return an unboxed value does so.
130 : : this maximizes opportunities for composing functions without
131 : : unnecessary boxing.
132 : : the bitcast function does nothing except change the type tag
133 : : of a value. At the user-level, it is perhaps better known as reinterpret.
134 : : boxing is delayed until absolutely necessary, and handled at the point
135 : : where the box is needed.
136 : : all intrinsics have a non-compiled implementation, this file contains
137 : : the optimizations for handling them unboxed
138 : : */
139 : :
140 : : // convert an llvm type to same-size float type
141 : 11050 : static Type *FLOATT(Type *t)
142 : : {
143 [ + - ]: 11050 : if (t->isFloatingPointTy())
144 : 11050 : return t;
145 [ # # ]: 0 : unsigned nb = (t->isPointerTy() ? sizeof(void*) * 8 : t->getPrimitiveSizeInBits());
146 : 0 : auto &ctxt = t->getContext();
147 [ # # ]: 0 : if (nb == 64)
148 : 0 : return getDoubleTy(ctxt);
149 [ # # ]: 0 : if (nb == 32)
150 : 0 : return getFloatTy(ctxt);
151 [ # # ]: 0 : if (nb == 16)
152 : 0 : return getHalfTy(ctxt);
153 [ # # ]: 0 : if (nb == 128)
154 : 0 : return getFP128Ty(ctxt);
155 : 0 : return NULL;
156 : : }
157 : :
158 : : // convert an llvm type to same-size int type
159 : 1763190 : static Type *INTT(Type *t)
160 : : {
161 : 1763190 : auto &ctxt = t->getContext();
162 [ + + ]: 1763190 : if (t->isIntegerTy())
163 : 1747220 : return t;
164 [ + + ]: 15964 : if (t->isPointerTy())
165 : 15638 : return getSizeTy(ctxt);
166 [ + + ]: 326 : if (t == getDoubleTy(ctxt))
167 : 294 : return getInt64Ty(ctxt);
168 [ + - ]: 32 : if (t == getFloatTy(ctxt))
169 : 32 : return getInt32Ty(ctxt);
170 [ # # ]: 0 : if (t == getHalfTy(ctxt))
171 : 0 : return getInt16Ty(ctxt);
172 : 0 : unsigned nb = t->getPrimitiveSizeInBits();
173 [ # # # # ]: 0 : assert(t != getVoidTy(ctxt) && nb > 0);
174 : 0 : return IntegerType::get(ctxt, nb);
175 : : }
176 : :
177 : 158100 : static Value *uint_cnvt(jl_codectx_t &ctx, Type *to, Value *x)
178 : : {
179 : 158100 : Type *t = x->getType();
180 [ + + ]: 158100 : if (t == to)
181 : 80153 : return x;
182 [ + + ]: 77947 : if (to->getPrimitiveSizeInBits() < x->getType()->getPrimitiveSizeInBits())
183 : 73118 : return ctx.builder.CreateTrunc(x, to);
184 : 4829 : return ctx.builder.CreateZExt(x, to);
185 : : }
186 : :
187 : 1241150 : static Constant *julia_const_to_llvm(jl_codectx_t &ctx, const void *ptr, jl_datatype_t *bt)
188 : : {
189 : : // assumes `jl_is_pointerfree(bt)`.
190 : : // `ptr` can point to a inline field, do not read the tag from it.
191 : : // make sure to return exactly the type specified by
192 : : // julia_type_to_llvm as this will be assumed by the callee.
193 [ + + ]: 1241150 : if (bt == jl_bool_type)
194 [ + + ]: 2950 : return ConstantInt::get(getInt8Ty(ctx.builder.getContext()), (*(const uint8_t*)ptr) ? 1 : 0);
195 : :
196 : 1238200 : Type *lt = julia_struct_to_llvm(ctx, (jl_value_t*)bt, NULL);
197 : :
198 [ + + + - : 1238200 : if (jl_is_vecelement_type((jl_value_t*)bt) && !jl_is_uniontype(jl_tparam0(bt)))
+ + ]
199 : 56 : bt = (jl_datatype_t*)jl_tparam0(bt);
200 : :
201 [ - + ]: 1238200 : if (type_is_ghost(lt))
202 : 0 : return UndefValue::get(lt);
203 : :
204 [ + + ]: 1238200 : if (lt->isFloatTy()) {
205 : 28 : uint32_t data32 = *(const uint32_t*)ptr;
206 : 28 : return ConstantFP::get(ctx.builder.getContext(),
207 : 56 : APFloat(lt->getFltSemantics(), APInt(32, data32)));
208 : : }
209 [ + + ]: 1238170 : if (lt->isDoubleTy()) {
210 : 12012 : uint64_t data64 = *(const uint64_t*)ptr;
211 : 12012 : return ConstantFP::get(ctx.builder.getContext(),
212 : 24024 : APFloat(lt->getFltSemantics(), APInt(64, data64)));
213 : : }
214 [ + - + + : 1226160 : if (lt->isFloatingPointTy() || lt->isIntegerTy() || lt->isPointerTy()) {
- + + + ]
215 : 1193860 : int nb = jl_datatype_size(bt);
216 : 2387730 : APInt val(8 * nb, 0);
217 : 1193860 : void *bits = const_cast<uint64_t*>(val.getRawData());
218 : : assert(sys::IsLittleEndianHost);
219 : 1193860 : memcpy(bits, ptr, nb);
220 [ - + ]: 1193860 : if (lt->isFloatingPointTy()) {
221 : 0 : return ConstantFP::get(ctx.builder.getContext(),
222 : 0 : APFloat(lt->getFltSemantics(), val));
223 : : }
224 [ - + ]: 1193860 : if (lt->isPointerTy()) {
225 : 0 : Type *Ty = IntegerType::get(ctx.builder.getContext(), 8 * nb);
226 : 0 : Constant *addr = ConstantInt::get(Ty, val);
227 : 0 : return ConstantExpr::getIntToPtr(addr, lt);
228 : : }
229 [ - + ]: 1193860 : assert(cast<IntegerType>(lt)->getBitWidth() == 8u * nb);
230 : 1193860 : return ConstantInt::get(lt, val);
231 : : }
232 : :
233 : 32291 : size_t nf = jl_datatype_nfields(bt);
234 : 64582 : std::vector<Constant*> fields(0);
235 [ + + ]: 111070 : for (size_t i = 0; i < nf; i++) {
236 : 78779 : size_t offs = jl_field_offset(bt, i);
237 : 78779 : jl_value_t *ft = jl_field_type(bt, i);
238 : 78779 : Type *lft = julia_type_to_llvm(ctx, ft);
239 [ + + ]: 78779 : if (type_is_ghost(lft))
240 : 1286 : continue;
241 [ - + ]: 77493 : assert(!jl_field_isptr(bt, i));
242 [ + + ]: 77493 : unsigned llvm_idx = isa<StructType>(lt) ? convert_struct_offset(jl_Module->getDataLayout(), lt, offs) : i;
243 [ - + ]: 77493 : while (fields.size() < llvm_idx)
244 : 0 : fields.push_back(
245 : 0 : UndefValue::get(GetElementPtrInst::getTypeAtIndex(lt, fields.size())));
246 : 77493 : const uint8_t *ov = (const uint8_t*)ptr + offs;
247 [ - + ]: 77493 : if (jl_is_uniontype(ft)) {
248 : : // compute the same type layout as julia_struct_to_llvm
249 : 0 : size_t fsz = 0, al = 0;
250 : 0 : (void)jl_islayout_inline(ft, &fsz, &al);
251 : 0 : fsz = jl_field_size(bt, i);
252 : 0 : uint8_t sel = ((const uint8_t*)ptr)[offs + fsz - 1];
253 : 0 : jl_value_t *active_ty = jl_nth_union_component(ft, sel);
254 : 0 : size_t active_sz = jl_datatype_size(active_ty);
255 : 0 : Type *AlignmentType = IntegerType::get(ctx.builder.getContext(), 8 * al);
256 : 0 : unsigned NumATy = (fsz - 1) / al;
257 : 0 : unsigned remainder = (fsz - 1) % al;
258 [ # # ]: 0 : while (NumATy--) {
259 : : Constant *fld;
260 [ # # ]: 0 : if (active_sz > 0) {
261 : 0 : APInt Elem(8 * al, 0);
262 : 0 : void *bits = const_cast<uint64_t*>(Elem.getRawData());
263 [ # # ]: 0 : if (active_sz > al) {
264 : 0 : memcpy(bits, ov, al);
265 : 0 : active_sz -= al;
266 : : }
267 : : else {
268 : 0 : memcpy(bits, ov, active_sz);
269 : 0 : active_sz = 0;
270 : : }
271 : 0 : fld = ConstantInt::get(AlignmentType, Elem);
272 : : }
273 : : else {
274 : 0 : fld = UndefValue::get(AlignmentType);
275 : : }
276 : 0 : ov += al;
277 : 0 : fields.push_back(fld);
278 : : }
279 [ # # ]: 0 : while (remainder--) {
280 : : Constant *fld;
281 [ # # ]: 0 : if (active_sz > 0) {
282 : 0 : uint8_t byte = *ov;
283 : 0 : APInt Elem(8, byte);
284 : 0 : active_sz -= 1;
285 : 0 : fld = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), Elem);
286 : : }
287 : : else {
288 : 0 : fld = UndefValue::get(getInt8Ty(ctx.builder.getContext()));
289 : : }
290 : 0 : ov += 1;
291 : 0 : fields.push_back(fld);
292 : : }
293 : 0 : fields.push_back(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), sel));
294 : : }
295 : : else {
296 : 77493 : Constant *val = julia_const_to_llvm(ctx, ov, (jl_datatype_t*)ft);
297 : 77493 : fields.push_back(val);
298 : : }
299 : : }
300 : :
301 [ + + ]: 32291 : if (lt->isVectorTy())
302 : 4 : return ConstantVector::get(fields);
303 [ + + ]: 32287 : if (StructType *st = dyn_cast<StructType>(lt))
304 : 4943 : return ConstantStruct::get(st, fields);
305 [ + - ]: 27344 : if (ArrayType *at = dyn_cast<ArrayType>(lt))
306 : 27344 : return ConstantArray::get(at, fields);
307 : 0 : assert(false && "Unknown LLVM type");
308 : : jl_unreachable();
309 : : }
310 : :
311 : 1686950 : static Constant *julia_const_to_llvm(jl_codectx_t &ctx, jl_value_t *e)
312 : : {
313 [ + + ]: 1686950 : if (e == jl_true)
314 : 270099 : return ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 1);
315 [ + + ]: 1416860 : if (e == jl_false)
316 : 238638 : return ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0);
317 : 1178220 : jl_value_t *bt = jl_typeof(e);
318 [ + + ]: 1178220 : if (!jl_is_pointerfree(bt))
319 : 14564 : return NULL;
320 : 1163650 : return julia_const_to_llvm(ctx, e, (jl_datatype_t*)bt);
321 : : }
322 : :
323 : 5399490 : static Value *emit_unboxed_coercion(jl_codectx_t &ctx, Type *to, Value *unboxed)
324 : : {
325 : 5399490 : Type *ty = unboxed->getType();
326 [ + + ]: 5399490 : if (ty == to)
327 : 4694500 : return unboxed;
328 : 704999 : bool frompointer = ty->isPointerTy();
329 : 704999 : bool topointer = to->isPointerTy();
330 : 704999 : const DataLayout &DL = jl_Module->getDataLayout();
331 [ + + + - : 704999 : if (ty->isIntegerTy(1) && to->isIntegerTy(8)) {
+ + ]
332 : : // bools may be stored internally as int8
333 : 494348 : unboxed = ctx.builder.CreateZExt(unboxed, to);
334 : : }
335 [ + + + - : 210651 : else if (ty->isIntegerTy(8) && to->isIntegerTy(1)) {
+ + ]
336 : : // bools may be stored internally as int8
337 : 194515 : unboxed = ctx.builder.CreateTrunc(unboxed, to);
338 : : }
339 [ + - - + : 16136 : else if (ty->isVoidTy() || DL.getTypeSizeInBits(ty) != DL.getTypeSizeInBits(to)) {
- + ]
340 : : // this can happen in dead code
341 : : //emit_unreachable(ctx);
342 : 0 : return UndefValue::get(to);
343 : : }
344 [ + + - + ]: 704999 : if (frompointer && topointer) {
345 : 0 : unboxed = emit_bitcast(ctx, unboxed, to);
346 : : }
347 [ + + - + : 704999 : else if (!ty->isIntOrPtrTy() && !ty->isFloatingPointTy()) {
- + ]
348 : : #ifndef JL_NDEBUG
349 : 0 : const DataLayout &DL = jl_Module->getDataLayout();
350 : : #endif
351 [ # # ]: 0 : assert(DL.getTypeSizeInBits(ty) == DL.getTypeSizeInBits(to));
352 : 0 : AllocaInst *cast = ctx.builder.CreateAlloca(ty);
353 : 0 : ctx.builder.CreateStore(unboxed, cast);
354 : 0 : unboxed = ctx.builder.CreateLoad(to, ctx.builder.CreateBitCast(cast, to->getPointerTo()));
355 : : }
356 [ + + ]: 704999 : else if (frompointer) {
357 : 50 : Type *INTT_to = INTT(to);
358 : 50 : unboxed = ctx.builder.CreatePtrToInt(unboxed, INTT_to);
359 [ - + ]: 50 : if (INTT_to != to)
360 : 0 : unboxed = ctx.builder.CreateBitCast(unboxed, to);
361 : : }
362 [ + + ]: 704949 : else if (topointer) {
363 : 15638 : Type *INTT_to = INTT(to);
364 [ + - ]: 15638 : if (to != INTT_to)
365 : 15638 : unboxed = ctx.builder.CreateBitCast(unboxed, INTT_to);
366 : 15638 : unboxed = emit_inttoptr(ctx, unboxed, to);
367 : : }
368 : : else {
369 : 689311 : unboxed = ctx.builder.CreateBitCast(unboxed, to);
370 : : }
371 : 704999 : return unboxed;
372 : : }
373 : :
374 : : // emit code to unpack a raw value from a box into registers
375 : 5595330 : static Value *emit_unbox(jl_codectx_t &ctx, Type *to, const jl_cgval_t &x, jl_value_t *jt)
376 : : {
377 [ - + ]: 5595330 : assert(to != getVoidTy(ctx.builder.getContext()));
378 : : // TODO: fully validate that x.typ == jt?
379 [ - + ]: 5595330 : if (x.isghost) {
380 : : // this can happen when a branch yielding a different type ends
381 : : // up being dead code, and type inference knows that the other
382 : : // branch's type is the only one that matters.
383 [ # # ]: 0 : if (type_is_ghost(to)) {
384 : 0 : return NULL;
385 : : }
386 : : //emit_unreachable(ctx);
387 : 0 : return UndefValue::get(to); // type mismatch error
388 : : }
389 : :
390 [ + + ]: 5595330 : Constant *c = x.constant ? julia_const_to_llvm(ctx, x.constant) : NULL;
391 [ + + + + : 5595330 : if (!x.ispointer() || c) { // already unboxed, but sometimes need conversion
+ + ]
392 [ + + ]: 5399490 : Value *unboxed = c ? c : x.V;
393 : 5399490 : return emit_unboxed_coercion(ctx, to, unboxed);
394 : : }
395 : :
396 : : // bools stored as int8, so an extra Trunc is needed to get an int1
397 [ + + ]: 195840 : Value *p = x.constant ? literal_pointer_val(ctx, x.constant) : x.V;
398 : :
399 [ + + - + : 195840 : if (jt == (jl_value_t*)jl_bool_type || to->isIntegerTy(1)) {
+ + ]
400 : 32442 : Instruction *unbox_load = tbaa_decorate(x.tbaa, ctx.builder.CreateLoad(getInt8Ty(ctx.builder.getContext()), maybe_bitcast(ctx, p, getInt8PtrTy(ctx.builder.getContext()))));
401 [ + - ]: 32442 : if (jt == (jl_value_t*)jl_bool_type)
402 : 32442 : unbox_load->setMetadata(LLVMContext::MD_range, MDNode::get(ctx.builder.getContext(), {
403 : 32442 : ConstantAsMetadata::get(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0)),
404 : 32442 : ConstantAsMetadata::get(ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 2)) }));
405 : : Value *unboxed;
406 [ + + ]: 32442 : if (to->isIntegerTy(1))
407 : 3408 : unboxed = ctx.builder.CreateTrunc(unbox_load, to);
408 : : else
409 : 29034 : unboxed = unbox_load; // `to` must be Int8Ty
410 : 32442 : return unboxed;
411 : : }
412 : :
413 : 163398 : unsigned alignment = julia_alignment(jt);
414 : 163398 : Type *ptype = to->getPointerTo();
415 [ + + + + : 163398 : if (p->getType() != ptype && isa<AllocaInst>(p)) {
+ + ]
416 : : // LLVM's mem2reg can't handle coercion if the load/store type does
417 : : // not match the type of the alloca. As such, it is better to
418 : : // perform the load using the alloca's type and then perform the
419 : : // appropriate coercion manually.
420 : 924 : AllocaInst *AI = cast<AllocaInst>(p);
421 : 924 : Type *AllocType = AI->getAllocatedType();
422 : 924 : const DataLayout &DL = jl_Module->getDataLayout();
423 [ + - ]: 1848 : if (!AI->isArrayAllocation() &&
424 [ + + - + : 1936 : (AllocType->isFloatingPointTy() || AllocType->isIntegerTy() || AllocType->isPointerTy()) &&
+ - ]
425 [ + - + - : 1936 : (to->isFloatingPointTy() || to->isIntegerTy() || to->isPointerTy()) &&
- + - - ]
426 [ - + ]: 924 : DL.getTypeSizeInBits(AllocType) == DL.getTypeSizeInBits(to)) {
427 : 0 : Instruction *load = ctx.builder.CreateAlignedLoad(AllocType, p, Align(alignment));
428 : 0 : return emit_unboxed_coercion(ctx, to, tbaa_decorate(x.tbaa, load));
429 : : }
430 : : }
431 : 163398 : p = maybe_bitcast(ctx, p, ptype);
432 : 163398 : Instruction *load = ctx.builder.CreateAlignedLoad(to, p, Align(alignment));
433 : 163398 : return tbaa_decorate(x.tbaa, load);
434 : : }
435 : :
436 : : // emit code to store a raw value into a destination
437 : 190152 : static void emit_unbox_store(jl_codectx_t &ctx, const jl_cgval_t &x, Value *dest, MDNode *tbaa_dest, unsigned alignment, bool isVolatile)
438 : : {
439 [ + + ]: 190152 : if (x.isghost) {
440 : : // this can happen when a branch yielding a different type ends
441 : : // up being dead code, and type inference knows that the other
442 : : // branch's type is the only one that matters.
443 : 4471 : return;
444 : : }
445 : :
446 : 185681 : Value *unboxed = nullptr;
447 [ + + ]: 185681 : if (!x.ispointer()) { // already unboxed, but sometimes need conversion
448 : 88269 : unboxed = x.V;
449 [ - + ]: 88269 : assert(unboxed);
450 : : }
451 : :
452 : : // bools stored as int8, but can be narrowed to int1 often
453 [ + + ]: 185681 : if (x.typ == (jl_value_t*)jl_bool_type)
454 : 14379 : unboxed = emit_unbox(ctx, getInt8Ty(ctx.builder.getContext()), x, (jl_value_t*)jl_bool_type);
455 : :
456 [ + + ]: 185681 : if (unboxed) {
457 : 97823 : Type *dest_ty = unboxed->getType()->getPointerTo();
458 [ + + ]: 97823 : if (dest->getType() != dest_ty)
459 : 47057 : dest = emit_bitcast(ctx, dest, dest_ty);
460 : 97823 : StoreInst *store = ctx.builder.CreateAlignedStore(unboxed, dest, Align(alignment));
461 : 97823 : store->setVolatile(isVolatile);
462 : 97823 : tbaa_decorate(tbaa_dest, store);
463 : 97823 : return;
464 : : }
465 : :
466 : 87858 : Value *src = data_pointer(ctx, x);
467 : 87858 : emit_memcpy(ctx, dest, tbaa_dest, src, x.tbaa, jl_datatype_size(x.typ), alignment, isVolatile);
468 : : }
469 : :
470 : 349358 : static jl_value_t *staticeval_bitstype(const jl_cgval_t &targ)
471 : : {
472 : : // evaluate an argument at compile time to determine what type it is
473 [ + + ]: 349358 : if (jl_is_type_type(targ.typ)) {
474 : 349351 : jl_value_t *bt = jl_tparam0(targ.typ);
475 [ + - ]: 349351 : if (jl_is_primitivetype(bt))
476 : 349351 : return bt;
477 : : }
478 : 7 : return NULL;
479 : : }
480 : :
481 : 206 : static jl_cgval_t emit_runtime_call(jl_codectx_t &ctx, JL_I::intrinsic f, const jl_cgval_t *argv, size_t nargs)
482 : : {
483 : 206 : Function *func = prepare_call(runtime_func()[f]);
484 : 206 : Value **argvalues = (Value**)alloca(sizeof(Value*) * nargs);
485 [ + + ]: 579 : for (size_t i = 0; i < nargs; ++i) {
486 : 373 : argvalues[i] = boxed(ctx, argv[i]);
487 : : }
488 : 206 : Value *r = ctx.builder.CreateCall(func, makeArrayRef(argvalues, nargs));
489 : 206 : return mark_julia_type(ctx, r, true, (jl_value_t*)jl_any_type);
490 : : }
491 : :
492 : : // put a bits type tag on some value (despite the name, this doesn't necessarily actually change anything about the value however)
493 : 258375 : static jl_cgval_t generic_bitcast(jl_codectx_t &ctx, const jl_cgval_t *argv)
494 : : {
495 : : // Give the arguments names //
496 : 258375 : const jl_cgval_t &bt_value = argv[0];
497 : 258375 : const jl_cgval_t &v = argv[1];
498 : 258375 : jl_value_t *bt = staticeval_bitstype(bt_value);
499 : :
500 : : // it's easier to throw a good error from C than llvm
501 [ + + ]: 258375 : if (!bt)
502 : 3 : return emit_runtime_call(ctx, bitcast, argv, 2);
503 : :
504 : 258372 : Type *llvmt = bitstype_to_llvm(bt, ctx.builder.getContext(), true);
505 : 258372 : int nb = jl_datatype_size(bt);
506 : :
507 : : // Examine the second argument //
508 : : bool isboxed;
509 : 258372 : Type *vxt = julia_type_to_llvm(ctx, v.typ, &isboxed);
510 : :
511 [ + + - + : 258372 : if (!jl_is_primitivetype(v.typ) || jl_datatype_size(v.typ) != nb) {
+ + ]
512 : 7 : Value *typ = emit_typeof_boxed(ctx, v);
513 [ + - ]: 7 : if (!jl_is_primitivetype(v.typ)) {
514 [ + - ]: 7 : if (isboxed) {
515 : 7 : Value *isprimitive = emit_datatype_isprimitivetype(ctx, typ);
516 : 7 : error_unless(ctx, isprimitive, "bitcast: expected primitive type value for second argument");
517 : : }
518 : : else {
519 : 0 : emit_error(ctx, "bitcast: expected primitive type value for second argument");
520 : 0 : return jl_cgval_t();
521 : : }
522 : : }
523 [ + + + - ]: 7 : if (!jl_is_datatype(v.typ) || jl_datatype_size(v.typ) != nb) {
524 [ + - ]: 7 : if (isboxed) {
525 : 7 : Value *size = emit_datatype_size(ctx, typ);
526 : 14 : error_unless(ctx,
527 : 7 : ctx.builder.CreateICmpEQ(size, ConstantInt::get(getInt32Ty(ctx.builder.getContext()), nb)),
528 : : "bitcast: argument size does not match size of target type");
529 : : }
530 : : else {
531 : 0 : emit_error(ctx, "bitcast: argument size does not match size of target type");
532 : 0 : return jl_cgval_t();
533 : : }
534 : : }
535 : : }
536 : :
537 [ - + ]: 258372 : assert(!v.isghost);
538 : 258372 : Value *vx = NULL;
539 [ + + ]: 258372 : if (!v.ispointer())
540 : 218003 : vx = v.V;
541 [ + + ]: 40369 : else if (v.constant)
542 : 32460 : vx = julia_const_to_llvm(ctx, v.constant);
543 : :
544 [ + + + + : 258372 : if (v.ispointer() && vx == NULL) {
+ + ]
545 : : // try to load as original Type, to preserve llvm optimizations
546 : : // but if the v.typ is not well known, use llvmt
547 [ + + ]: 7909 : if (isboxed)
548 : 7 : vxt = llvmt;
549 [ - + ]: 7909 : auto storage_type = vxt->isIntegerTy(1) ? getInt8Ty(ctx.builder.getContext()) : vxt;
550 : 15818 : vx = tbaa_decorate(v.tbaa, ctx.builder.CreateLoad(
551 : : storage_type,
552 : : emit_bitcast(ctx, data_pointer(ctx, v),
553 : 7909 : storage_type->getPointerTo())));
554 : : }
555 : :
556 : 258372 : vxt = vx->getType();
557 [ + + ]: 258372 : if (vxt != llvmt) {
558 [ - + ]: 5429 : if (llvmt->isIntegerTy(1))
559 : 0 : vx = ctx.builder.CreateTrunc(vx, llvmt);
560 [ + + + - : 5429 : else if (vxt->isIntegerTy(1) && llvmt->isIntegerTy(8))
+ + ]
561 : 44 : vx = ctx.builder.CreateZExt(vx, llvmt);
562 [ + + + - : 5385 : else if (vxt->isPointerTy() && !llvmt->isPointerTy())
+ + ]
563 : 2745 : vx = ctx.builder.CreatePtrToInt(vx, llvmt);
564 [ + - - + : 2640 : else if (!vxt->isPointerTy() && llvmt->isPointerTy())
- + ]
565 : 0 : vx = emit_inttoptr(ctx, vx, llvmt);
566 : : else
567 : 2640 : vx = emit_bitcast(ctx, vx, llvmt);
568 : : }
569 : :
570 [ + - ]: 258372 : if (jl_is_concrete_type(bt)) {
571 : 258372 : return mark_julia_type(ctx, vx, false, bt);
572 : : }
573 : : else {
574 : 0 : Value *box = emit_allocobj(ctx, nb, boxed(ctx, bt_value));
575 : 0 : init_bits_value(ctx, box, vx, ctx.tbaa().tbaa_immut);
576 : 0 : return mark_julia_type(ctx, box, true, bt);
577 : : }
578 : : }
579 : :
580 : 90983 : static jl_cgval_t generic_cast(
581 : : jl_codectx_t &ctx,
582 : : intrinsic f, Instruction::CastOps Op,
583 : : const jl_cgval_t *argv, bool toint, bool fromint)
584 : : {
585 : 90983 : const jl_cgval_t &targ = argv[0];
586 : 90983 : const jl_cgval_t &v = argv[1];
587 : 90983 : jl_value_t *jlto = staticeval_bitstype(targ);
588 [ + + + + : 90983 : if (!jlto || !jl_is_primitivetype(v.typ))
+ + ]
589 : 6 : return emit_runtime_call(ctx, f, argv, 2);
590 : 90977 : Type *to = bitstype_to_llvm(jlto, ctx.builder.getContext(), true);
591 : 90977 : Type *vt = bitstype_to_llvm(v.typ, ctx.builder.getContext(), true);
592 [ + + ]: 90977 : if (toint)
593 : 89875 : to = INTT(to);
594 : : else
595 : 1102 : to = FLOATT(to);
596 [ + + ]: 90977 : if (fromint)
597 : 90581 : vt = INTT(vt);
598 : : else
599 : 396 : vt = FLOATT(vt);
600 [ + - - + ]: 90977 : if (!to || !vt)
601 : 0 : return emit_runtime_call(ctx, f, argv, 2);
602 : 90977 : Value *from = emit_unbox(ctx, vt, v, v.typ);
603 [ - + ]: 90977 : if (!CastInst::castIsValid(Op, from, to))
604 : 0 : return emit_runtime_call(ctx, f, argv, 2);
605 : : if (Op == Instruction::FPExt) {
606 : : #ifdef JL_NEED_FLOATTEMP_VAR
607 : : // Target platform might carry extra precision.
608 : : // Force rounding to single precision first. The reason is that it's
609 : : // fine to keep working in extended precision as long as it's
610 : : // understood that everything is implicitly rounded to 23 bits,
611 : : // but if we start looking at more bits we need to actually do the
612 : : // rounding first instead of carrying around incorrect low bits.
613 : : Value *jlfloattemp_var = emit_static_alloca(ctx, from->getType());
614 : : ctx.builder.CreateStore(from, jlfloattemp_var);
615 : : from = ctx.builder.CreateLoad(from->getType(), jlfloattemp_var, /*force this to load from the stack*/true);
616 : : #endif
617 : : }
618 : 90977 : Value *ans = ctx.builder.CreateCast(Op, from, to);
619 [ + + + + ]: 90977 : if (f == fptosi || f == fptoui)
620 : 362 : ans = ctx.builder.CreateFreeze(ans);
621 : 90977 : return mark_julia_type(ctx, ans, false, jlto);
622 : : }
623 : :
624 : 2 : static jl_cgval_t emit_runtime_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv)
625 : : {
626 : 2 : return emit_runtime_call(ctx, pointerref, argv, 3);
627 : : }
628 : :
629 : 10756 : static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv)
630 : : {
631 : 10756 : const jl_cgval_t &e = argv[0];
632 : 10756 : const jl_cgval_t &i = argv[1];
633 : 10756 : const jl_cgval_t &align = argv[2];
634 : :
635 [ + + - + ]: 10756 : if (align.constant == NULL || !jl_is_long(align.constant))
636 : 1 : return emit_runtime_pointerref(ctx, argv);
637 : 10755 : unsigned align_nb = jl_unbox_long(align.constant);
638 : :
639 [ + + ]: 10755 : if (i.typ != (jl_value_t*)jl_long_type)
640 : 1 : return emit_runtime_pointerref(ctx, argv);
641 : 10754 : jl_value_t *aty = e.typ;
642 [ - + ]: 10754 : if (!jl_is_cpointer_type(aty))
643 : 0 : return emit_runtime_pointerref(ctx, argv);
644 : 10754 : jl_value_t *ety = jl_tparam0(aty);
645 [ - + ]: 10754 : if (jl_is_typevar(ety))
646 : 0 : return emit_runtime_pointerref(ctx, argv);
647 [ - + ]: 10754 : if (!is_valid_intrinsic_elptr(ety)) {
648 : 0 : emit_error(ctx, "pointerref: invalid pointer type");
649 : 0 : return jl_cgval_t();
650 : : }
651 : :
652 : 10754 : Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), i, (jl_value_t*)jl_long_type);
653 : 10754 : Value *im1 = ctx.builder.CreateSub(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
654 : :
655 [ - + ]: 10754 : if (ety == (jl_value_t*)jl_any_type) {
656 : 0 : Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ);
657 : 0 : LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, thePtr, im1), Align(align_nb));
658 : 0 : tbaa_decorate(ctx.tbaa().tbaa_data, load);
659 : 0 : return mark_julia_type(ctx, load, true, ety);
660 : : }
661 [ + + ]: 10754 : else if (!jl_isbits(ety)) {
662 [ - + ]: 26 : assert(jl_is_datatype(ety));
663 : 26 : uint64_t size = jl_datatype_size(ety);
664 : 26 : Value *strct = emit_allocobj(ctx, size,
665 : : literal_pointer_val(ctx, ety));
666 : 52 : im1 = ctx.builder.CreateMul(im1, ConstantInt::get(getSizeTy(ctx.builder.getContext()),
667 : 26 : LLT_ALIGN(size, jl_datatype_align(ety))));
668 : 26 : Value *thePtr = emit_unbox(ctx, getInt8PtrTy(ctx.builder.getContext()), e, e.typ);
669 : 26 : thePtr = ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, thePtr, getInt8PtrTy(ctx.builder.getContext())), im1);
670 : 26 : MDNode *tbaa = best_tbaa(ctx.tbaa(), ety);
671 : 26 : emit_memcpy(ctx, strct, tbaa, thePtr, nullptr, size, 1);
672 : 26 : return mark_julia_type(ctx, strct, true, ety);
673 : : }
674 : : else {
675 : : bool isboxed;
676 : 10728 : Type *ptrty = julia_type_to_llvm(ctx, ety, &isboxed);
677 [ - + ]: 10728 : assert(!isboxed);
678 [ + - ]: 10728 : if (!type_is_ghost(ptrty)) {
679 : 10728 : Value *thePtr = emit_unbox(ctx, ptrty->getPointerTo(), e, e.typ);
680 : 10728 : return typed_load(ctx, thePtr, im1, ety, ctx.tbaa().tbaa_data, nullptr, isboxed, AtomicOrdering::NotAtomic, true, align_nb);
681 : : }
682 : : else {
683 : 0 : return ghostValue(ctx, ety);
684 : : }
685 : : }
686 : : }
687 : :
688 : 0 : static jl_cgval_t emit_runtime_pointerset(jl_codectx_t &ctx, jl_cgval_t *argv)
689 : : {
690 : 0 : return emit_runtime_call(ctx, pointerset, argv, 4);
691 : : }
692 : :
693 : : // e[i] = x
694 : 2366 : static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, jl_cgval_t *argv)
695 : : {
696 : 2366 : const jl_cgval_t &e = argv[0];
697 : 2366 : const jl_cgval_t &x = argv[1];
698 : 2366 : const jl_cgval_t &i = argv[2];
699 : 2366 : const jl_cgval_t &align = argv[3];
700 : :
701 [ + - - + ]: 2366 : if (align.constant == NULL || !jl_is_long(align.constant))
702 : 0 : return emit_runtime_pointerset(ctx, argv);
703 : 2366 : unsigned align_nb = jl_unbox_long(align.constant);
704 : :
705 [ - + ]: 2366 : if (i.typ != (jl_value_t*)jl_long_type)
706 : 0 : return emit_runtime_pointerset(ctx, argv);
707 : 2366 : jl_value_t *aty = e.typ;
708 [ - + ]: 2366 : if (!jl_is_cpointer_type(aty))
709 : 0 : return emit_runtime_pointerset(ctx, argv);
710 : 2366 : jl_value_t *ety = jl_tparam0(aty);
711 [ - + ]: 2366 : if (jl_is_typevar(ety))
712 : 0 : return emit_runtime_pointerset(ctx, argv);
713 [ + - - + ]: 2366 : if (align.constant == NULL || !jl_is_long(align.constant))
714 : 0 : return emit_runtime_pointerset(ctx, argv);
715 [ - + ]: 2366 : if (!is_valid_intrinsic_elptr(ety)) {
716 : 0 : emit_error(ctx, "pointerset: invalid pointer type");
717 : 0 : return jl_cgval_t();
718 : : }
719 : 2366 : emit_typecheck(ctx, x, ety, "pointerset");
720 : :
721 : 2366 : Value *idx = emit_unbox(ctx, getSizeTy(ctx.builder.getContext()), i, (jl_value_t*)jl_long_type);
722 : 2366 : Value *im1 = ctx.builder.CreateSub(idx, ConstantInt::get(getSizeTy(ctx.builder.getContext()), 1));
723 : :
724 : : Value *thePtr;
725 [ - + ]: 2366 : if (ety == (jl_value_t*)jl_any_type) {
726 : : // unsafe_store to Ptr{Any} is allowed to implicitly drop GC roots.
727 : 0 : thePtr = emit_unbox(ctx, getSizePtrTy(ctx.builder.getContext()), e, e.typ);
728 : 0 : Instruction *store = ctx.builder.CreateAlignedStore(
729 : 0 : ctx.builder.CreatePtrToInt(emit_pointer_from_objref(ctx, boxed(ctx, x)), getSizeTy(ctx.builder.getContext())),
730 : 0 : ctx.builder.CreateInBoundsGEP(getSizeTy(ctx.builder.getContext()), thePtr, im1), Align(align_nb));
731 : 0 : tbaa_decorate(ctx.tbaa().tbaa_data, store);
732 : : }
733 [ - + ]: 2366 : else if (!jl_isbits(ety)) {
734 : 0 : thePtr = emit_unbox(ctx, getInt8PtrTy(ctx.builder.getContext()), e, e.typ);
735 : 0 : uint64_t size = jl_datatype_size(ety);
736 : 0 : im1 = ctx.builder.CreateMul(im1, ConstantInt::get(getSizeTy(ctx.builder.getContext()),
737 : 0 : LLT_ALIGN(size, jl_datatype_align(ety))));
738 : 0 : emit_memcpy(ctx, ctx.builder.CreateInBoundsGEP(getInt8Ty(ctx.builder.getContext()), thePtr, im1), nullptr, x, size, align_nb);
739 : : }
740 : : else {
741 : : bool isboxed;
742 : 2366 : Type *ptrty = julia_type_to_llvm(ctx, ety, &isboxed);
743 [ - + ]: 2366 : assert(!isboxed);
744 [ + - ]: 2366 : if (!type_is_ghost(ptrty)) {
745 : 2366 : thePtr = emit_unbox(ctx, ptrty->getPointerTo(), e, e.typ);
746 : 4732 : typed_store(ctx, thePtr, im1, x, jl_cgval_t(), ety, ctx.tbaa().tbaa_data, nullptr, nullptr, isboxed,
747 : 2366 : AtomicOrdering::NotAtomic, AtomicOrdering::NotAtomic, align_nb, false, true, false, false, false, false, nullptr, "");
748 : : }
749 : : }
750 : 2366 : return e;
751 : : }
752 : :
753 : 10 : static jl_cgval_t emit_atomicfence(jl_codectx_t &ctx, jl_cgval_t *argv)
754 : : {
755 : 10 : const jl_cgval_t &ord = argv[0];
756 [ + - + - ]: 10 : if (ord.constant && jl_is_symbol(ord.constant)) {
757 : 10 : enum jl_memory_order order = jl_get_atomic_order((jl_sym_t*)ord.constant, true, true);
758 [ - + ]: 10 : if (order == jl_memory_order_invalid) {
759 : 0 : emit_atomic_error(ctx, "invalid atomic ordering");
760 : 0 : return jl_cgval_t(); // unreachable
761 : : }
762 [ + - ]: 10 : if (order > jl_memory_order_monotonic)
763 : 10 : ctx.builder.CreateFence(get_llvm_atomic_order(order));
764 : 10 : return ghostValue(ctx, jl_nothing_type);
765 : : }
766 : 0 : return emit_runtime_call(ctx, atomic_fence, argv, 1);
767 : : }
768 : :
769 : 1878 : static jl_cgval_t emit_atomic_pointerref(jl_codectx_t &ctx, jl_cgval_t *argv)
770 : : {
771 : 1878 : const jl_cgval_t &e = argv[0];
772 : 1878 : const jl_cgval_t &ord = argv[1];
773 : 1878 : jl_value_t *aty = e.typ;
774 [ + - + - : 1878 : if (!jl_is_cpointer_type(aty) || !ord.constant || !jl_is_symbol(ord.constant))
- + - + ]
775 : 0 : return emit_runtime_call(ctx, atomic_pointerref, argv, 2);
776 : 1878 : jl_value_t *ety = jl_tparam0(aty);
777 [ - + ]: 1878 : if (jl_is_typevar(ety))
778 : 0 : return emit_runtime_call(ctx, atomic_pointerref, argv, 2);
779 : 1878 : enum jl_memory_order order = jl_get_atomic_order((jl_sym_t*)ord.constant, true, false);
780 [ - + ]: 1878 : if (order == jl_memory_order_invalid) {
781 : 0 : emit_atomic_error(ctx, "invalid atomic ordering");
782 : 0 : return jl_cgval_t(); // unreachable
783 : : }
784 : 1878 : AtomicOrdering llvm_order = get_llvm_atomic_order(order);
785 : :
786 [ - + ]: 1878 : if (ety == (jl_value_t*)jl_any_type) {
787 : 0 : Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ);
788 : 0 : LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, thePtr, Align(sizeof(jl_value_t*)));
789 : 0 : tbaa_decorate(ctx.tbaa().tbaa_data, load);
790 : 0 : load->setOrdering(llvm_order);
791 : 0 : return mark_julia_type(ctx, load, true, ety);
792 : : }
793 : :
794 [ - + ]: 1878 : if (!is_valid_intrinsic_elptr(ety)) {
795 : 0 : emit_error(ctx, "atomic_pointerref: invalid pointer type");
796 : 0 : return jl_cgval_t();
797 : : }
798 : :
799 : 1878 : size_t nb = jl_datatype_size(ety);
800 [ + - - + ]: 1878 : if ((nb & (nb - 1)) != 0 || nb > MAX_POINTERATOMIC_SIZE) {
801 : 0 : emit_error(ctx, "atomic_pointerref: invalid pointer for atomic operation");
802 : 0 : return jl_cgval_t();
803 : : }
804 : :
805 [ - + ]: 1878 : if (!jl_isbits(ety)) {
806 [ # # ]: 0 : assert(jl_is_datatype(ety));
807 : 0 : uint64_t size = jl_datatype_size(ety);
808 : 0 : Value *strct = emit_allocobj(ctx, size,
809 : : literal_pointer_val(ctx, ety));
810 : 0 : Value *thePtr = emit_unbox(ctx, getInt8PtrTy(ctx.builder.getContext()), e, e.typ);
811 : 0 : Type *loadT = Type::getIntNTy(ctx.builder.getContext(), nb * 8);
812 : 0 : thePtr = emit_bitcast(ctx, thePtr, loadT->getPointerTo());
813 : 0 : MDNode *tbaa = best_tbaa(ctx.tbaa(), ety);
814 : 0 : LoadInst *load = ctx.builder.CreateAlignedLoad(loadT, thePtr, Align(nb));
815 : 0 : tbaa_decorate(tbaa, load);
816 : 0 : load->setOrdering(llvm_order);
817 : 0 : thePtr = emit_bitcast(ctx, strct, thePtr->getType());
818 : 0 : StoreInst *store = ctx.builder.CreateAlignedStore(load, thePtr, Align(julia_alignment(ety)));
819 : 0 : tbaa_decorate(tbaa, store);
820 : 0 : return mark_julia_type(ctx, strct, true, ety);
821 : : }
822 : : else {
823 : : bool isboxed;
824 : 1878 : Type *ptrty = julia_type_to_llvm(ctx, ety, &isboxed);
825 [ - + ]: 1878 : assert(!isboxed);
826 [ + - ]: 1878 : if (!type_is_ghost(ptrty)) {
827 : 1878 : Value *thePtr = emit_unbox(ctx, ptrty->getPointerTo(), e, e.typ);
828 : 1878 : return typed_load(ctx, thePtr, nullptr, ety, ctx.tbaa().tbaa_data, nullptr, isboxed, llvm_order, true, nb);
829 : : }
830 : : else {
831 [ # # ]: 0 : if (order > jl_memory_order_monotonic)
832 : 0 : ctx.builder.CreateFence(llvm_order);
833 : 0 : return ghostValue(ctx, ety);
834 : : }
835 : : }
836 : : }
837 : :
838 : : // e[i] = x (set)
839 : : // e[i] <= x (swap)
840 : : // e[i] y => x (replace)
841 : : // x(e[i], y) (modify)
842 : 0 : static jl_cgval_t emit_atomic_pointerop(jl_codectx_t &ctx, intrinsic f, const jl_cgval_t *argv, int nargs, const jl_cgval_t *modifyop)
843 : : {
844 : 0 : bool issetfield = f == atomic_pointerset;
845 : 0 : bool isreplacefield = f == atomic_pointerreplace;
846 : 0 : bool isswapfield = f == atomic_pointerswap;
847 : 0 : bool ismodifyfield = f == atomic_pointermodify;
848 : 0 : const jl_cgval_t undefval;
849 : 0 : const jl_cgval_t &e = argv[0];
850 [ # # # # ]: 0 : const jl_cgval_t &x = isreplacefield || ismodifyfield ? argv[2] : argv[1];
851 [ # # # # ]: 0 : const jl_cgval_t &y = isreplacefield || ismodifyfield ? argv[1] : undefval;
852 [ # # # # ]: 0 : const jl_cgval_t &ord = isreplacefield || ismodifyfield ? argv[3] : argv[2];
853 [ # # ]: 0 : const jl_cgval_t &failord = isreplacefield ? argv[4] : undefval;
854 : :
855 : 0 : jl_value_t *aty = e.typ;
856 [ # # # # : 0 : if (!jl_is_cpointer_type(aty) || !ord.constant || !jl_is_symbol(ord.constant))
# # # # ]
857 : 0 : return emit_runtime_call(ctx, f, argv, nargs);
858 [ # # ]: 0 : if (isreplacefield) {
859 [ # # # # ]: 0 : if (!failord.constant || !jl_is_symbol(failord.constant))
860 : 0 : return emit_runtime_call(ctx, f, argv, nargs);
861 : : }
862 : 0 : jl_value_t *ety = jl_tparam0(aty);
863 [ # # ]: 0 : if (jl_is_typevar(ety))
864 : 0 : return emit_runtime_call(ctx, f, argv, nargs);
865 : 0 : enum jl_memory_order order = jl_get_atomic_order((jl_sym_t*)ord.constant, !issetfield, true);
866 [ # # ]: 0 : enum jl_memory_order failorder = isreplacefield ? jl_get_atomic_order((jl_sym_t*)failord.constant, true, false) : order;
867 [ # # # # : 0 : if (order == jl_memory_order_invalid || failorder == jl_memory_order_invalid || failorder > order) {
# # ]
868 : 0 : emit_atomic_error(ctx, "invalid atomic ordering");
869 : 0 : return jl_cgval_t(); // unreachable
870 : : }
871 : 0 : AtomicOrdering llvm_order = get_llvm_atomic_order(order);
872 : 0 : AtomicOrdering llvm_failorder = get_llvm_atomic_order(failorder);
873 : :
874 [ # # ]: 0 : if (ety == (jl_value_t*)jl_any_type) {
875 : : // unsafe_store to Ptr{Any} is allowed to implicitly drop GC roots.
876 : : // n.b.: the expected value (y) must be rooted, but not the others
877 : 0 : Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ);
878 : 0 : bool isboxed = true;
879 : 0 : jl_cgval_t ret = typed_store(ctx, thePtr, nullptr, x, y, ety, ctx.tbaa().tbaa_data, nullptr, nullptr, isboxed,
880 : 0 : llvm_order, llvm_failorder, sizeof(jl_value_t*), false, issetfield, isreplacefield, isswapfield, ismodifyfield, false, modifyop, "atomic_pointermodify");
881 [ # # ]: 0 : if (issetfield)
882 : 0 : ret = e;
883 : 0 : return ret;
884 : : }
885 : :
886 [ # # ]: 0 : if (!is_valid_intrinsic_elptr(ety)) {
887 : 0 : std::string msg(StringRef(jl_intrinsic_name((int)f)));
888 : 0 : msg += ": invalid pointer type";
889 : 0 : emit_error(ctx, msg);
890 : 0 : return jl_cgval_t();
891 : : }
892 [ # # ]: 0 : if (!ismodifyfield)
893 : 0 : emit_typecheck(ctx, x, ety, std::string(jl_intrinsic_name((int)f)));
894 : :
895 : 0 : size_t nb = jl_datatype_size(ety);
896 [ # # # # ]: 0 : if ((nb & (nb - 1)) != 0 || nb > MAX_POINTERATOMIC_SIZE) {
897 : 0 : std::string msg(StringRef(jl_intrinsic_name((int)f)));
898 : 0 : msg += ": invalid pointer for atomic operation";
899 : 0 : emit_error(ctx, msg);
900 : 0 : return jl_cgval_t();
901 : : }
902 : :
903 [ # # ]: 0 : if (!jl_isbits(ety)) {
904 : : //Value *thePtr = emit_unbox(ctx, getInt8PtrTy(ctx.builder.getContext()), e, e.typ);
905 : : //uint64_t size = jl_datatype_size(ety);
906 : 0 : return emit_runtime_call(ctx, f, argv, nargs); // TODO: optimizations
907 : : }
908 : : else {
909 : : bool isboxed;
910 : 0 : Type *ptrty = julia_type_to_llvm(ctx, ety, &isboxed);
911 [ # # ]: 0 : assert(!isboxed);
912 : 0 : Value *thePtr = emit_unbox(ctx, ptrty->getPointerTo(), e, e.typ);
913 : 0 : jl_cgval_t ret = typed_store(ctx, thePtr, nullptr, x, y, ety, ctx.tbaa().tbaa_data, nullptr, nullptr, isboxed,
914 : 0 : llvm_order, llvm_failorder, nb, false, issetfield, isreplacefield, isswapfield, ismodifyfield, false, modifyop, "atomic_pointermodify");
915 [ # # ]: 0 : if (issetfield)
916 : 0 : ret = e;
917 : 0 : return ret;
918 : : }
919 : : }
920 : :
921 : 519 : static Value *emit_checked_srem_int(jl_codectx_t &ctx, Value *x, Value *den)
922 : : {
923 : 519 : Type *t = den->getType();
924 : 1038 : raise_exception_unless(ctx,
925 : 519 : ctx.builder.CreateICmpNE(den, ConstantInt::get(t, 0)),
926 : : literal_pointer_val(ctx, jl_diverror_exception));
927 : 519 : BasicBlock *m1BB = BasicBlock::Create(ctx.builder.getContext(), "minus1", ctx.f);
928 : 519 : BasicBlock *okBB = BasicBlock::Create(ctx.builder.getContext(), "oksrem", ctx.f);
929 : 519 : BasicBlock *cont = BasicBlock::Create(ctx.builder.getContext(), "after_srem", ctx.f);
930 : 519 : PHINode *ret = PHINode::Create(t, 2);
931 : 519 : ctx.builder.CreateCondBr(ctx.builder.CreateICmpEQ(den ,ConstantInt::get(t, -1, true)),
932 : : m1BB, okBB);
933 : 519 : ctx.builder.SetInsertPoint(m1BB);
934 : 519 : ctx.builder.CreateBr(cont);
935 : 519 : ctx.builder.SetInsertPoint(okBB);
936 : 519 : Value *sremval = ctx.builder.CreateSRem(x, den);
937 : 519 : ctx.builder.CreateBr(cont);
938 : 519 : ctx.builder.SetInsertPoint(cont);
939 : 519 : ret->addIncoming(// rem(typemin, -1) is undefined
940 : 519 : ConstantInt::get(t, 0), m1BB);
941 : 519 : ret->addIncoming(sremval, okBB);
942 : 519 : ctx.builder.Insert(ret);
943 : 519 : return ret;
944 : : }
945 : :
946 : : // Temporarily switch the ctx.builder to fast-math mode if requested
947 : : struct math_builder {
948 : : IRBuilder<> &ctxbuilder;
949 : : FastMathFlags old_fmf;
950 : 8610 : math_builder(jl_codectx_t &ctx, bool always_fast = false, bool contract = false)
951 : 8610 : : ctxbuilder(ctx.builder),
952 : 8610 : old_fmf(ctxbuilder.getFastMathFlags())
953 : : {
954 : 8610 : FastMathFlags fmf;
955 [ + - + - ]: 8610 : if (jl_options.fast_math != JL_OPTIONS_FAST_MATH_OFF &&
956 : 8610 : (always_fast ||
957 [ - + ]: 8610 : jl_options.fast_math == JL_OPTIONS_FAST_MATH_ON)) {
958 : 0 : fmf.setFast();
959 : : }
960 [ + + ]: 8610 : if (contract)
961 : 408 : fmf.setAllowContract(true);
962 : 8610 : ctxbuilder.setFastMathFlags(fmf);
963 : 8610 : }
964 : 9018 : IRBuilder<>& operator()() const { return ctxbuilder; }
965 : 17220 : ~math_builder() {
966 : 8610 : ctxbuilder.setFastMathFlags(old_fmf);
967 : 8610 : }
968 : : };
969 : :
970 : : static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **argvalues, size_t nargs,
971 : : jl_datatype_t **newtyp, jl_value_t *xtyp);
972 : :
973 : :
974 : 103170 : static jl_cgval_t emit_ifelse(jl_codectx_t &ctx, jl_cgval_t c, jl_cgval_t x, jl_cgval_t y, jl_value_t *rt_hint)
975 : : {
976 : 103170 : Value *isfalse = emit_condition(ctx, c, "ifelse");
977 : 103170 : jl_value_t *t1 = x.typ;
978 : 103170 : jl_value_t *t2 = y.typ;
979 : : // handle cases where the condition is irrelevant based on type info
980 [ - + - - ]: 103170 : if (t1 == jl_bottom_type && t2 == jl_bottom_type)
981 : 0 : return jl_cgval_t(); // undefined
982 [ - + ]: 103170 : if (t1 == jl_bottom_type)
983 : 0 : return y;
984 [ - + ]: 103170 : if (t2 == jl_bottom_type)
985 : 0 : return x;
986 : :
987 [ - + ]: 103170 : if (t1 != t2) {
988 : : // type inference may know something we don't, in which case it may
989 : : // be illegal for us to convert to rt_hint. Check first if either
990 : : // of the types have empty intersection with the result type,
991 : : // in which case, we may use the other one.
992 [ # # ]: 0 : if (jl_type_intersection(t1, rt_hint) == jl_bottom_type)
993 : 0 : return y;
994 [ # # ]: 0 : else if (jl_type_intersection(t2, rt_hint) == jl_bottom_type)
995 : 0 : return x;
996 : : // if they aren't the same type, consider using the expr type
997 : : // to instantiate a union-split optimization
998 : 0 : x = convert_julia_type(ctx, x, rt_hint);
999 : 0 : y = convert_julia_type(ctx, y, rt_hint);
1000 : 0 : t1 = x.typ;
1001 : 0 : t2 = y.typ;
1002 : : }
1003 : :
1004 : : Value *ifelse_result;
1005 [ + - + + ]: 103170 : bool isboxed = t1 != t2 || !deserves_stack(t1);
1006 [ + + ]: 103170 : Type *llt1 = isboxed ? ctx.types().T_prjlvalue : julia_type_to_llvm(ctx, t1);
1007 [ + + ]: 103170 : if (!isboxed) {
1008 [ - + ]: 103169 : if (type_is_ghost(llt1))
1009 : 0 : return x;
1010 : 103169 : ifelse_result = ctx.builder.CreateSelect(isfalse,
1011 : : emit_unbox(ctx, llt1, y, t1),
1012 : : emit_unbox(ctx, llt1, x, t1));
1013 : : }
1014 : : else {
1015 : 1 : Value *x_tindex = x.TIndex;
1016 : 1 : Value *y_tindex = y.TIndex;
1017 [ + - - + ]: 1 : if (x_tindex || y_tindex) {
1018 [ # # ]: 0 : if (!x.isghost)
1019 : 0 : x = value_to_pointer(ctx, x);
1020 [ # # ]: 0 : if (!y.isghost)
1021 : 0 : y = value_to_pointer(ctx, y);
1022 : 0 : Value *x_vboxed = x.Vboxed;
1023 : 0 : Value *y_vboxed = y.Vboxed;
1024 [ # # ]: 0 : Value *x_ptr = (x.isghost ? NULL : data_pointer(ctx, x));
1025 [ # # ]: 0 : Value *y_ptr = (y.isghost ? NULL : data_pointer(ctx, y));
1026 : : MDNode *ifelse_tbaa;
1027 [ # # # # ]: 0 : if (!x.isghost && x.constant)
1028 : 0 : x_vboxed = boxed(ctx, x);
1029 [ # # # # ]: 0 : if (!y.isghost && y.constant)
1030 : 0 : y_vboxed = boxed(ctx, y);
1031 [ # # # # ]: 0 : if (!x_ptr && !y_ptr) { // both ghost
1032 : 0 : ifelse_result = NULL;
1033 : 0 : ifelse_tbaa = ctx.tbaa().tbaa_stack;
1034 : : }
1035 [ # # ]: 0 : else if (!x_ptr) {
1036 : 0 : ifelse_result = y_ptr;
1037 : 0 : ifelse_tbaa = y.tbaa;
1038 : : }
1039 [ # # ]: 0 : else if (!y_ptr) {
1040 : 0 : ifelse_result = x_ptr;
1041 : 0 : ifelse_tbaa = x.tbaa;
1042 : : }
1043 : : else {
1044 : 0 : x_ptr = decay_derived(ctx, x_ptr);
1045 : 0 : y_ptr = decay_derived(ctx, y_ptr);
1046 [ # # ]: 0 : if (x_ptr->getType() != y_ptr->getType())
1047 : 0 : y_ptr = ctx.builder.CreateBitCast(y_ptr, x_ptr->getType());
1048 : 0 : ifelse_result = ctx.builder.CreateSelect(isfalse, y_ptr, x_ptr);
1049 : 0 : ifelse_tbaa = MDNode::getMostGenericTBAA(x.tbaa, y.tbaa);
1050 [ # # ]: 0 : if (ifelse_tbaa == NULL) {
1051 : : // LLVM won't return a TBAA result for the root, but mark_julia_struct requires it: make it now
1052 : 0 : auto *OffsetNode = ConstantAsMetadata::get(ConstantInt::get(getInt64Ty(ctx.builder.getContext()), 0));
1053 : 0 : Metadata *Ops[] = {ctx.tbaa().tbaa_root, ctx.tbaa().tbaa_root, OffsetNode};
1054 : 0 : ifelse_tbaa = MDNode::get(ctx.builder.getContext(), Ops);
1055 : : }
1056 : : }
1057 : : Value *tindex;
1058 [ # # # # ]: 0 : if (!x_tindex && x.constant) {
1059 : 0 : x_tindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80 | get_box_tindex((jl_datatype_t*)jl_typeof(x.constant), rt_hint));
1060 : : }
1061 [ # # # # ]: 0 : if (!y_tindex && y.constant) {
1062 : 0 : y_tindex = ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80 | get_box_tindex((jl_datatype_t*)jl_typeof(y.constant), rt_hint));
1063 : : }
1064 [ # # # # ]: 0 : if (x_tindex && y_tindex) {
1065 : 0 : tindex = ctx.builder.CreateSelect(isfalse, y_tindex, x_tindex);
1066 : : }
1067 : : else {
1068 : 0 : PHINode *ret = PHINode::Create(getInt8Ty(ctx.builder.getContext()), 2);
1069 : 0 : BasicBlock *post = BasicBlock::Create(ctx.builder.getContext(), "post", ctx.f);
1070 : 0 : BasicBlock *compute = BasicBlock::Create(ctx.builder.getContext(), "compute_tindex", ctx.f);
1071 : : // compute tindex if we select the previously-boxed value
1072 [ # # ]: 0 : if (x_tindex) {
1073 [ # # # # ]: 0 : assert(y.isboxed && y.V);
1074 : 0 : ctx.builder.CreateCondBr(isfalse, compute, post);
1075 : 0 : ret->addIncoming(x_tindex, ctx.builder.GetInsertBlock());
1076 : 0 : ctx.builder.SetInsertPoint(compute);
1077 : 0 : tindex = compute_tindex_unboxed(ctx, y, rt_hint);
1078 : : }
1079 : : else {
1080 [ # # ]: 0 : assert(x.isboxed);
1081 : 0 : ctx.builder.CreateCondBr(isfalse, post, compute);
1082 : 0 : ret->addIncoming(y_tindex, ctx.builder.GetInsertBlock());
1083 : 0 : ctx.builder.SetInsertPoint(compute);
1084 : 0 : tindex = compute_tindex_unboxed(ctx, x, rt_hint);
1085 : : }
1086 : 0 : tindex = ctx.builder.CreateOr(tindex, ConstantInt::get(getInt8Ty(ctx.builder.getContext()), 0x80));
1087 : 0 : compute = ctx.builder.GetInsertBlock(); // could have changed
1088 : 0 : ctx.builder.CreateBr(post);
1089 : 0 : ret->addIncoming(tindex, compute);
1090 : 0 : ctx.builder.SetInsertPoint(post);
1091 : 0 : ctx.builder.Insert(ret);
1092 : 0 : tindex = ret;
1093 : : }
1094 : 0 : jl_cgval_t ret = mark_julia_slot(ifelse_result, rt_hint, tindex, ifelse_tbaa);
1095 [ # # # # ]: 0 : if (x_vboxed || y_vboxed) {
1096 [ # # ]: 0 : if (!x_vboxed)
1097 : 0 : x_vboxed = ConstantPointerNull::get(cast<PointerType>(y_vboxed->getType()));
1098 [ # # ]: 0 : if (!y_vboxed)
1099 : 0 : y_vboxed = ConstantPointerNull::get(cast<PointerType>(x_vboxed->getType()));
1100 : 0 : ret.Vboxed = ctx.builder.CreateSelect(isfalse, y_vboxed, x_vboxed);
1101 [ # # ]: 0 : assert(ret.Vboxed->getType() == ctx.types().T_prjlvalue);
1102 : : }
1103 : 0 : return ret;
1104 : : }
1105 : 1 : ifelse_result = ctx.builder.CreateSelect(isfalse,
1106 : : boxed(ctx, y),
1107 : : boxed(ctx, x));
1108 : : }
1109 [ + - ]: 103170 : jl_value_t *jt = (t1 == t2 ? t1 : rt_hint);
1110 : 103170 : return mark_julia_type(ctx, ifelse_result, isboxed, jt);
1111 : : }
1112 : :
1113 : 1689020 : static jl_cgval_t emit_intrinsic(jl_codectx_t &ctx, intrinsic f, jl_value_t **args, size_t nargs)
1114 : : {
1115 [ - + ]: 1689020 : assert(f < num_intrinsics);
1116 [ + + + + ]: 1689020 : if (f == cglobal && nargs == 1)
1117 : 132 : f = cglobal_auto;
1118 : 1689020 : unsigned expected_nargs = jl_intrinsic_nargs((int)f);
1119 [ + + - + ]: 1689020 : if (expected_nargs && expected_nargs != nargs) {
1120 : 0 : jl_errorf("intrinsic #%d %s: wrong number of arguments", f, jl_intrinsic_name((int)f));
1121 : : }
1122 : :
1123 [ + + ]: 1689020 : if (f == llvmcall)
1124 : 410 : return emit_llvmcall(ctx, args, nargs);
1125 [ + + + + ]: 1688620 : if (f == cglobal_auto || f == cglobal)
1126 : 3299 : return emit_cglobal(ctx, args, nargs);
1127 : :
1128 : 1685320 : jl_cgval_t *argv = (jl_cgval_t*)alloca(sizeof(jl_cgval_t) * nargs);
1129 [ + + ]: 4798900 : for (size_t i = 0; i < nargs; ++i) {
1130 : 3113590 : argv[i] = emit_expr(ctx, args[i + 1]);
1131 : : }
1132 : :
1133 : : // this forces everything to use runtime-intrinsics (e.g. for testing)
1134 : : // return emit_runtime_call(ctx, f, argv, nargs);
1135 : :
1136 [ + + + + : 1685320 : switch (f) {
+ - + + +
+ + + + +
+ + + +
+ ]
1137 : 77678 : case arraylen: {
1138 : 77678 : ++Emitted_arraylen;
1139 [ - + ]: 77678 : assert(nargs == 1);
1140 : 77678 : const jl_cgval_t &x = argv[0];
1141 : 77678 : jl_value_t *typ = jl_unwrap_unionall(x.typ);
1142 [ + - - + ]: 77678 : if (!jl_is_datatype(typ) || ((jl_datatype_t*)typ)->name != jl_array_typename)
1143 : 0 : return emit_runtime_call(ctx, f, argv, nargs);
1144 : 77678 : return mark_julia_type(ctx, emit_arraylen(ctx, x), false, jl_long_type);
1145 : : }
1146 : 10756 : case pointerref:
1147 : 10756 : ++Emitted_pointerref;
1148 [ - + ]: 10756 : assert(nargs == 3);
1149 : 10756 : return emit_pointerref(ctx, argv);
1150 : 2366 : case pointerset:
1151 : 2366 : ++Emitted_pointerset;
1152 [ - + ]: 2366 : assert(nargs == 4);
1153 : 2366 : return emit_pointerset(ctx, argv);
1154 : 10 : case atomic_fence:
1155 : 10 : ++Emitted_atomic_fence;
1156 [ - + ]: 10 : assert(nargs == 1);
1157 : 10 : return emit_atomicfence(ctx, argv);
1158 : 1878 : case atomic_pointerref:
1159 : 1878 : ++Emitted_atomic_pointerref;
1160 [ - + ]: 1878 : assert(nargs == 2);
1161 : 1878 : return emit_atomic_pointerref(ctx, argv);
1162 : 0 : case atomic_pointerset:
1163 : : case atomic_pointerswap:
1164 : : case atomic_pointermodify:
1165 : : case atomic_pointerreplace:
1166 : 0 : ++Emitted_atomic_pointerop;
1167 : 0 : return emit_atomic_pointerop(ctx, f, argv, nargs, nullptr);
1168 : 258375 : case bitcast:
1169 : 258375 : ++Emitted_bitcast;
1170 [ - + ]: 258375 : assert(nargs == 2);
1171 : 258375 : return generic_bitcast(ctx, argv);
1172 : 38575 : case trunc_int:
1173 : 38575 : ++Emitted_trunc_int;
1174 [ - + ]: 38575 : assert(nargs == 2);
1175 : 38575 : return generic_cast(ctx, f, Instruction::Trunc, argv, true, true);
1176 : 18523 : case sext_int:
1177 : 18523 : ++Emitted_sext_int;
1178 [ - + ]: 18523 : assert(nargs == 2);
1179 : 18523 : return generic_cast(ctx, f, Instruction::SExt, argv, true, true);
1180 : 32421 : case zext_int:
1181 : 32421 : ++Emitted_zext_int;
1182 [ - + ]: 32421 : assert(nargs == 2);
1183 : 32421 : return generic_cast(ctx, f, Instruction::ZExt, argv, true, true);
1184 : 236 : case uitofp:
1185 : 236 : ++Emitted_uitofp;
1186 [ - + ]: 236 : assert(nargs == 2);
1187 : 236 : return generic_cast(ctx, f, Instruction::UIToFP, argv, false, true);
1188 : 832 : case sitofp:
1189 : 832 : ++Emitted_sitofp;
1190 [ - + ]: 832 : assert(nargs == 2);
1191 : 832 : return generic_cast(ctx, f, Instruction::SIToFP, argv, false, true);
1192 : 48 : case fptoui:
1193 : 48 : ++Emitted_fptoui;
1194 [ - + ]: 48 : assert(nargs == 2);
1195 : 48 : return generic_cast(ctx, f, Instruction::FPToUI, argv, true, false);
1196 : 314 : case fptosi:
1197 : 314 : ++Emitted_fptosi;
1198 [ - + ]: 314 : assert(nargs == 2);
1199 : 314 : return generic_cast(ctx, f, Instruction::FPToSI, argv, true, false);
1200 : 18 : case fptrunc:
1201 : 18 : ++Emitted_fptrunc;
1202 [ - + ]: 18 : assert(nargs == 2);
1203 : 18 : return generic_cast(ctx, f, Instruction::FPTrunc, argv, false, false);
1204 : 16 : case fpext:
1205 : 16 : ++Emitted_fpext;
1206 [ - + ]: 16 : assert(nargs == 2);
1207 : 16 : return generic_cast(ctx, f, Instruction::FPExt, argv, false, false);
1208 : :
1209 : 163908 : case not_int: {
1210 : 163908 : ++Emitted_not_int;
1211 [ - + ]: 163908 : assert(nargs == 1);
1212 : 163908 : const jl_cgval_t &x = argv[0];
1213 [ + + ]: 163908 : if (!jl_is_primitivetype(x.typ))
1214 : 19 : return emit_runtime_call(ctx, f, argv, nargs);
1215 : 163889 : Type *xt = INTT(bitstype_to_llvm(x.typ, ctx.builder.getContext(), true));
1216 : 163889 : Value *from = emit_unbox(ctx, xt, x, x.typ);
1217 : 163889 : Value *ans = ctx.builder.CreateNot(from);
1218 : 163889 : return mark_julia_type(ctx, ans, false, x.typ);
1219 : : }
1220 : :
1221 : 292 : case have_fma: {
1222 : 292 : ++Emitted_have_fma;
1223 [ - + ]: 292 : assert(nargs == 1);
1224 : 292 : const jl_cgval_t &x = argv[0];
1225 [ + - - + ]: 292 : if (!x.constant || !jl_is_datatype(x.constant))
1226 : 0 : return emit_runtime_call(ctx, f, argv, nargs);
1227 : 292 : jl_datatype_t *dt = (jl_datatype_t*) x.constant;
1228 : :
1229 : : // select the appropriated overloaded intrinsic
1230 : 584 : std::string intr_name = "julia.cpu.have_fma.";
1231 [ - + ]: 292 : if (dt == jl_float32_type)
1232 : 0 : intr_name += "f32";
1233 [ + - ]: 292 : else if (dt == jl_float64_type)
1234 : 292 : intr_name += "f64";
1235 : : else
1236 : 0 : return emit_runtime_call(ctx, f, argv, nargs);
1237 : :
1238 : 292 : FunctionCallee intr = jl_Module->getOrInsertFunction(intr_name, getInt1Ty(ctx.builder.getContext()));
1239 : 292 : auto ret = ctx.builder.CreateCall(intr);
1240 : 292 : return mark_julia_type(ctx, ret, false, jl_bool_type);
1241 : : }
1242 : :
1243 : 1079070 : default: {
1244 [ - + ]: 1079070 : assert(nargs >= 1 && "invalid nargs for intrinsic call");
1245 : 1079070 : const jl_cgval_t &xinfo = argv[0];
1246 : :
1247 : : // verify argument types
1248 [ + + ]: 1079070 : if (!jl_is_primitivetype(xinfo.typ))
1249 : 173 : return emit_runtime_call(ctx, f, argv, nargs);
1250 : 1078900 : Type *xtyp = bitstype_to_llvm(xinfo.typ, ctx.builder.getContext(), true);
1251 [ + + ]: 1078900 : if (float_func()[f])
1252 : 9552 : xtyp = FLOATT(xtyp);
1253 : : else
1254 : 1069340 : xtyp = INTT(xtyp);
1255 [ - + ]: 1078900 : if (!xtyp)
1256 : 0 : return emit_runtime_call(ctx, f, argv, nargs);
1257 : : ////Bool are required to be in the range [0,1]
1258 : : ////so while they are represented as i8,
1259 : : ////the operations need to be done in mod 1
1260 : : ////we can either do that now, or truncate them
1261 : : ////later into mod 1.
1262 : : ////LLVM seems to emit better code if we do the latter,
1263 : : ////(more likely to fold away the cast) so that's what we'll do.
1264 : : //if (xtyp == (jl_value_t*)jl_bool_type)
1265 : : // r = getInt1Ty(ctx.builder.getContext());
1266 : :
1267 : 1078900 : Type **argt = (Type**)alloca(sizeof(Type*) * nargs);
1268 : 1078900 : argt[0] = xtyp;
1269 : :
1270 [ + + + + : 1078900 : if (f == shl_int || f == lshr_int || f == ashr_int) {
+ + ]
1271 [ - + ]: 158100 : if (!jl_is_primitivetype(argv[1].typ))
1272 : 0 : return emit_runtime_call(ctx, f, argv, nargs);
1273 : 158100 : argt[1] = INTT(bitstype_to_llvm(argv[1].typ, ctx.builder.getContext(), true));
1274 : : }
1275 : : else {
1276 [ + + ]: 1810970 : for (size_t i = 1; i < nargs; ++i) {
1277 [ + + ]: 890175 : if (xinfo.typ != argv[i].typ)
1278 : 3 : return emit_runtime_call(ctx, f, argv, nargs);
1279 : 890172 : argt[i] = xtyp;
1280 : : }
1281 : : }
1282 : :
1283 : : // unbox the arguments
1284 : 1078890 : Value **argvalues = (Value**)alloca(sizeof(Value*) * nargs);
1285 [ + + ]: 3206060 : for (size_t i = 0; i < nargs; ++i) {
1286 : 2127170 : argvalues[i] = emit_unbox(ctx, argt[i], argv[i], argv[i].typ);
1287 : : }
1288 : :
1289 : : // call the intrinsic
1290 : 1078890 : jl_value_t *newtyp = xinfo.typ;
1291 : 1078890 : Value *r = emit_untyped_intrinsic(ctx, f, argvalues, nargs, (jl_datatype_t**)&newtyp, xinfo.typ);
1292 : : // Turn Bool operations into mod 1 now, if needed
1293 [ + + - + : 1078890 : if (newtyp == (jl_value_t*)jl_bool_type && !r->getType()->isIntegerTy(1))
- + ]
1294 : 0 : r = ctx.builder.CreateTrunc(r, getInt1Ty(ctx.builder.getContext()));
1295 : 1078890 : return mark_julia_type(ctx, r, false, newtyp);
1296 : : }
1297 : : }
1298 : : assert(0 && "unreachable");
1299 : : }
1300 : :
1301 : 1078890 : static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, Value **argvalues, size_t nargs,
1302 : : jl_datatype_t **newtyp, jl_value_t *xtyp)
1303 : : {
1304 : 1078890 : ++EmittedUntypedIntrinsics;
1305 [ + - ]: 1078890 : Value *x = nargs > 0 ? argvalues[0] : NULL;
1306 [ + + ]: 1078890 : Value *y = nargs > 1 ? argvalues[1] : NULL;
1307 [ + + ]: 1078890 : Value *z = nargs > 2 ? argvalues[2] : NULL;
1308 : 1078890 : Type *t = x->getType();
1309 : :
1310 [ + + + + : 1078890 : switch (f) {
- - - - +
+ + - + +
+ + + - -
- - - + +
+ + + + +
+ - + + +
+ + + + +
- - - - +
+ + + + +
+ + + + +
+ + + + +
+ + + -
- ]
1311 : 22772 : case neg_int:
1312 : 22772 : return ctx.builder.CreateNeg(x);
1313 : 178458 : case add_int: return ctx.builder.CreateAdd(x, y);
1314 : 124253 : case sub_int: return ctx.builder.CreateSub(x, y);
1315 : 25097 : case mul_int: return ctx.builder.CreateMul(x, y);
1316 : 0 : case sdiv_int: return ctx.builder.CreateSDiv(x, y);
1317 : 0 : case udiv_int: return ctx.builder.CreateUDiv(x, y);
1318 : 0 : case srem_int: return ctx.builder.CreateSRem(x, y);
1319 : 0 : case urem_int: return ctx.builder.CreateURem(x, y);
1320 : :
1321 : : // LLVM will not fold ptrtoint+arithmetic+inttoptr to GEP. The reason for this
1322 : : // has to do with alias analysis. When adding two integers, either one of them
1323 : : // could be the pointer base. With getelementptr, it is clear which of the
1324 : : // operands is the pointer base. We also have this information at the julia
1325 : : // level. Thus, to not lose information, we need to have a separate intrinsic
1326 : : // for pointer arithmetic which lowers to getelementptr.
1327 : 14815 : case add_ptr: {
1328 : 59260 : return ctx.builder.CreatePtrToInt(
1329 : 14815 : ctx.builder.CreateGEP(getInt8Ty(ctx.builder.getContext()),
1330 : 29630 : emit_inttoptr(ctx, x, getInt8PtrTy(ctx.builder.getContext())), y), t);
1331 : :
1332 : : }
1333 : :
1334 : 8710 : case sub_ptr: {
1335 : 34840 : return ctx.builder.CreatePtrToInt(
1336 : 8710 : ctx.builder.CreateGEP(getInt8Ty(ctx.builder.getContext()),
1337 : 17420 : emit_inttoptr(ctx, x, getInt8PtrTy(ctx.builder.getContext())), ctx.builder.CreateNeg(y)), t);
1338 : :
1339 : : }
1340 : :
1341 : 168 : case neg_float: return math_builder(ctx)().CreateFNeg(x);
1342 : 0 : case neg_float_fast: return math_builder(ctx, true)().CreateFNeg(x);
1343 : 868 : case add_float: return math_builder(ctx)().CreateFAdd(x, y);
1344 : 1470 : case sub_float: return math_builder(ctx)().CreateFSub(x, y);
1345 : 1754 : case mul_float: return math_builder(ctx)().CreateFMul(x, y);
1346 : 548 : case div_float: return math_builder(ctx)().CreateFDiv(x, y);
1347 : 52 : case rem_float: return math_builder(ctx)().CreateFRem(x, y);
1348 : 0 : case add_float_fast: return math_builder(ctx, true)().CreateFAdd(x, y);
1349 : 0 : case sub_float_fast: return math_builder(ctx, true)().CreateFSub(x, y);
1350 : 0 : case mul_float_fast: return math_builder(ctx, true)().CreateFMul(x, y);
1351 : 0 : case div_float_fast: return math_builder(ctx, true)().CreateFDiv(x, y);
1352 : 0 : case rem_float_fast: return math_builder(ctx, true)().CreateFRem(x, y);
1353 : 228 : case fma_float: {
1354 [ - + ]: 228 : assert(y->getType() == x->getType());
1355 [ - + ]: 228 : assert(z->getType() == y->getType());
1356 : 228 : FunctionCallee fmaintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::fma, makeArrayRef(t));
1357 : 228 : return ctx.builder.CreateCall(fmaintr, {x, y, z});
1358 : : }
1359 : 408 : case muladd_float: {
1360 : : // LLVM 5.0 can create FMA in the backend for contractable fmul and fadd
1361 : : // Emitting fmul and fadd here since they are easier for other LLVM passes to
1362 : : // optimize.
1363 : 408 : auto mathb = math_builder(ctx, false, true);
1364 : 408 : return mathb().CreateFAdd(mathb().CreateFMul(x, y), z);
1365 : : }
1366 : :
1367 : 210 : case checked_sadd_int:
1368 : : case checked_uadd_int:
1369 : : case checked_ssub_int:
1370 : : case checked_usub_int:
1371 : : case checked_smul_int:
1372 : : case checked_umul_int: {
1373 [ - + ]: 210 : assert(x->getType() == y->getType());
1374 : 210 : Intrinsic::ID intr_id =
1375 [ + + + + : 210 : (f == checked_sadd_int ?
+ + + - +
+ ]
1376 : : Intrinsic::sadd_with_overflow :
1377 : : (f == checked_uadd_int ?
1378 : : Intrinsic::uadd_with_overflow :
1379 : : (f == checked_ssub_int ?
1380 : : Intrinsic::ssub_with_overflow :
1381 : : (f == checked_usub_int ?
1382 : : Intrinsic::usub_with_overflow :
1383 : : (f == checked_smul_int ?
1384 : : Intrinsic::smul_with_overflow :
1385 : : Intrinsic::umul_with_overflow)))));
1386 : 210 : FunctionCallee intr = Intrinsic::getDeclaration(jl_Module, intr_id, makeArrayRef(t));
1387 : 210 : Value *res = ctx.builder.CreateCall(intr, {x, y});
1388 : 210 : Value *val = ctx.builder.CreateExtractValue(res, ArrayRef<unsigned>(0));
1389 : 210 : Value *obit = ctx.builder.CreateExtractValue(res, ArrayRef<unsigned>(1));
1390 : 210 : Value *obyte = ctx.builder.CreateZExt(obit, getInt8Ty(ctx.builder.getContext()));
1391 : :
1392 : : jl_value_t *params[2];
1393 : 210 : params[0] = xtyp;
1394 : 210 : params[1] = (jl_value_t*)jl_bool_type;
1395 : 210 : jl_datatype_t *tuptyp = jl_apply_tuple_type_v(params, 2);
1396 : 210 : *newtyp = tuptyp;
1397 : :
1398 : : Value *tupval;
1399 : 210 : tupval = UndefValue::get(julia_type_to_llvm(ctx, (jl_value_t*)tuptyp));
1400 : 210 : tupval = ctx.builder.CreateInsertValue(tupval, val, ArrayRef<unsigned>(0));
1401 : 210 : tupval = ctx.builder.CreateInsertValue(tupval, obyte, ArrayRef<unsigned>(1));
1402 : 210 : return tupval;
1403 : : }
1404 : :
1405 : 2695 : case checked_sdiv_int: {
1406 : 2695 : Value *typemin = ctx.builder.CreateShl(ConstantInt::get(t, 1), t->getPrimitiveSizeInBits() - 1);
1407 : 8085 : raise_exception_unless(ctx,
1408 : : ctx.builder.CreateAnd(
1409 : 2695 : ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)),
1410 : : ctx.builder.CreateOr(
1411 : 2695 : ctx.builder.CreateICmpNE(y, ConstantInt::get(t, -1, true)),
1412 : : ctx.builder.CreateICmpNE(x, typemin))),
1413 : : literal_pointer_val(ctx, jl_diverror_exception));
1414 : :
1415 : 2695 : return ctx.builder.CreateSDiv(x, y);
1416 : : }
1417 : 2380 : case checked_udiv_int:
1418 : 4760 : raise_exception_unless(ctx,
1419 : 2380 : ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)),
1420 : : literal_pointer_val(ctx, jl_diverror_exception));
1421 : 2380 : return ctx.builder.CreateUDiv(x, y);
1422 : :
1423 : 519 : case checked_srem_int:
1424 : 519 : return emit_checked_srem_int(ctx, x, y);
1425 : :
1426 : 1166 : case checked_urem_int:
1427 : 2332 : raise_exception_unless(ctx,
1428 : 1166 : ctx.builder.CreateICmpNE(y, ConstantInt::get(t, 0)),
1429 : : literal_pointer_val(ctx, jl_diverror_exception));
1430 : 1166 : return ctx.builder.CreateURem(x, y);
1431 : :
1432 : 31489 : case eq_int: *newtyp = jl_bool_type; return ctx.builder.CreateICmpEQ(x, y);
1433 : 0 : case ne_int: *newtyp = jl_bool_type; return ctx.builder.CreateICmpNE(x, y);
1434 : 143220 : case slt_int: *newtyp = jl_bool_type; return ctx.builder.CreateICmpSLT(x, y);
1435 : 32874 : case ult_int: *newtyp = jl_bool_type; return ctx.builder.CreateICmpULT(x, y);
1436 : 136179 : case sle_int: *newtyp = jl_bool_type; return ctx.builder.CreateICmpSLE(x, y);
1437 : 14367 : case ule_int: *newtyp = jl_bool_type; return ctx.builder.CreateICmpULE(x, y);
1438 : :
1439 : 1058 : case eq_float: *newtyp = jl_bool_type; return math_builder(ctx)().CreateFCmpOEQ(x, y);
1440 : 1118 : case ne_float: *newtyp = jl_bool_type; return math_builder(ctx)().CreateFCmpUNE(x, y);
1441 : 854 : case lt_float: *newtyp = jl_bool_type; return math_builder(ctx)().CreateFCmpOLT(x, y);
1442 : 312 : case le_float: *newtyp = jl_bool_type; return math_builder(ctx)().CreateFCmpOLE(x, y);
1443 : :
1444 : 0 : case eq_float_fast: *newtyp = jl_bool_type; return math_builder(ctx, true)().CreateFCmpOEQ(x, y);
1445 : 0 : case ne_float_fast: *newtyp = jl_bool_type; return math_builder(ctx, true)().CreateFCmpUNE(x, y);
1446 : 0 : case lt_float_fast: *newtyp = jl_bool_type; return math_builder(ctx, true)().CreateFCmpOLT(x, y);
1447 : 0 : case le_float_fast: *newtyp = jl_bool_type; return math_builder(ctx, true)().CreateFCmpOLE(x, y);
1448 : :
1449 : 96 : case fpiseq: {
1450 : 96 : *newtyp = jl_bool_type;
1451 : 96 : Type *it = INTT(t);
1452 : 96 : Value *xi = ctx.builder.CreateBitCast(x, it);
1453 : 96 : Value *yi = ctx.builder.CreateBitCast(y, it);
1454 : 192 : return ctx.builder.CreateOr(ctx.builder.CreateAnd(ctx.builder.CreateFCmpUNO(x, x),
1455 : : ctx.builder.CreateFCmpUNO(y, y)),
1456 : 96 : ctx.builder.CreateICmpEQ(xi, yi));
1457 : : }
1458 : :
1459 : 110818 : case and_int: return ctx.builder.CreateAnd(x, y);
1460 : 35286 : case or_int: return ctx.builder.CreateOr(x, y);
1461 : 13936 : case xor_int: return ctx.builder.CreateXor(x, y);
1462 : :
1463 : 62509 : case shl_int: {
1464 : 62509 : Value *the_shl = ctx.builder.CreateShl(x, uint_cnvt(ctx, t, y));
1465 [ + - ]: 62509 : if (ConstantInt::isValueValidForType(y->getType(), t->getPrimitiveSizeInBits())) {
1466 : 187527 : return ctx.builder.CreateSelect(
1467 : 62509 : ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1468 : 125018 : t->getPrimitiveSizeInBits())),
1469 : 62509 : ConstantInt::get(t, 0),
1470 : 62509 : the_shl);
1471 : : }
1472 : : else {
1473 : 0 : return the_shl;
1474 : : }
1475 : : }
1476 : 86290 : case lshr_int: {
1477 : 86290 : Value *the_shr = ctx.builder.CreateLShr(x, uint_cnvt(ctx, t, y));
1478 [ + - ]: 86290 : if (ConstantInt::isValueValidForType(y->getType(), t->getPrimitiveSizeInBits())) {
1479 : 258870 : return ctx.builder.CreateSelect(
1480 : 86290 : ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1481 : 172580 : t->getPrimitiveSizeInBits())),
1482 : 86290 : ConstantInt::get(t, 0),
1483 : 86290 : the_shr);
1484 : : }
1485 : : else {
1486 : 0 : return the_shr;
1487 : : }
1488 : : }
1489 : 9301 : case ashr_int: {
1490 : 9301 : Value *the_shr = ctx.builder.CreateAShr(x, uint_cnvt(ctx, t, y));
1491 [ + - ]: 9301 : if (ConstantInt::isValueValidForType(y->getType(), t->getPrimitiveSizeInBits())) {
1492 : 27903 : return ctx.builder.CreateSelect(
1493 : 9301 : ctx.builder.CreateICmpUGE(y, ConstantInt::get(y->getType(),
1494 : 9301 : t->getPrimitiveSizeInBits())),
1495 : 18602 : ctx.builder.CreateAShr(x, ConstantInt::get(t, t->getPrimitiveSizeInBits() - 1)),
1496 : 9301 : the_shr);
1497 : : }
1498 : : else {
1499 : 0 : return the_shr;
1500 : : }
1501 : : }
1502 : 1472 : case bswap_int: {
1503 : 1472 : FunctionCallee bswapintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::bswap, makeArrayRef(t));
1504 : 1472 : return ctx.builder.CreateCall(bswapintr, x);
1505 : : }
1506 : 362 : case ctpop_int: {
1507 : 362 : FunctionCallee ctpopintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::ctpop, makeArrayRef(t));
1508 : 362 : return ctx.builder.CreateCall(ctpopintr, x);
1509 : : }
1510 : 4218 : case ctlz_int: {
1511 : 4218 : FunctionCallee ctlz = Intrinsic::getDeclaration(jl_Module, Intrinsic::ctlz, makeArrayRef(t));
1512 : 4218 : y = ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0);
1513 : 4218 : return ctx.builder.CreateCall(ctlz, {x, y});
1514 : : }
1515 : 1722 : case cttz_int: {
1516 : 1722 : FunctionCallee cttz = Intrinsic::getDeclaration(jl_Module, Intrinsic::cttz, makeArrayRef(t));
1517 : 1722 : y = ConstantInt::get(getInt1Ty(ctx.builder.getContext()), 0);
1518 : 1722 : return ctx.builder.CreateCall(cttz, {x, y});
1519 : : }
1520 : :
1521 : 138 : case abs_float: {
1522 : 138 : FunctionCallee absintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::fabs, makeArrayRef(t));
1523 : 138 : return ctx.builder.CreateCall(absintr, x);
1524 : : }
1525 : 74 : case copysign_float: {
1526 : 74 : FunctionCallee copyintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::copysign, makeArrayRef(t));
1527 : 74 : return ctx.builder.CreateCall(copyintr, {x, y});
1528 : : }
1529 : 4224 : case flipsign_int: {
1530 : 4224 : ConstantInt *cx = dyn_cast<ConstantInt>(x);
1531 : 4224 : ConstantInt *cy = dyn_cast<ConstantInt>(y);
1532 [ - + - - ]: 4224 : if (cx && cy) {
1533 : 0 : APInt ix = cx->getValue();
1534 : 0 : APInt iy = cy->getValue();
1535 [ # # # # ]: 0 : return ConstantInt::get(t, iy.isNonNegative() ? ix : -ix);
1536 : : }
1537 [ + + ]: 4224 : if (cy) {
1538 : 1376 : APInt iy = cy->getValue();
1539 [ + - ]: 1376 : return iy.isNonNegative() ? x : ctx.builder.CreateSub(ConstantInt::get(t, 0), x);
1540 : : }
1541 : 2848 : Value *tmp = ctx.builder.CreateAShr(y, ConstantInt::get(t, cast<IntegerType>(t)->getBitWidth() - 1));
1542 : 2848 : return ctx.builder.CreateXor(ctx.builder.CreateAdd(x, tmp), tmp);
1543 : : }
1544 : 56 : case ceil_llvm: {
1545 : 56 : FunctionCallee ceilintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::ceil, makeArrayRef(t));
1546 : 56 : return ctx.builder.CreateCall(ceilintr, x);
1547 : : }
1548 : 118 : case floor_llvm: {
1549 : 118 : FunctionCallee floorintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::floor, makeArrayRef(t));
1550 : 118 : return ctx.builder.CreateCall(floorintr, x);
1551 : : }
1552 : 104 : case trunc_llvm: {
1553 : 104 : FunctionCallee truncintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::trunc, makeArrayRef(t));
1554 : 104 : return ctx.builder.CreateCall(truncintr, x);
1555 : : }
1556 : 116 : case rint_llvm: {
1557 : 116 : FunctionCallee rintintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::rint, makeArrayRef(t));
1558 : 116 : return ctx.builder.CreateCall(rintintr, x);
1559 : : }
1560 : 12 : case sqrt_llvm: {
1561 : 12 : FunctionCallee sqrtintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::sqrt, makeArrayRef(t));
1562 : 12 : return ctx.builder.CreateCall(sqrtintr, x);
1563 : : }
1564 : 0 : case sqrt_llvm_fast: {
1565 : 0 : FunctionCallee sqrtintr = Intrinsic::getDeclaration(jl_Module, Intrinsic::sqrt, makeArrayRef(t));
1566 : 0 : return math_builder(ctx, true)().CreateCall(sqrtintr, x);
1567 : : }
1568 : :
1569 : 0 : default:
1570 : 0 : assert(0 && "invalid intrinsic");
1571 : : abort();
1572 : : }
1573 : : assert(0 && "unreachable");
1574 : : }
1575 : :
1576 : : //Redefine us as being part of codegen
1577 : : #undef DEBUG_TYPE
1578 : : #define DEBUG_TYPE "julia_irgen_codegen"
|