@@ -27,6 +27,7 @@ use rustc_span::{Symbol, sym};
27
27
28
28
pub ( crate ) use self :: llvm:: codegen_llvm_intrinsic_call;
29
29
use crate :: cast:: clif_intcast;
30
+ use crate :: intrinsics;
30
31
use crate :: prelude:: * ;
31
32
32
33
fn bug_on_incorrect_arg_count ( intrinsic : impl std:: fmt:: Display ) -> ! {
@@ -50,6 +51,12 @@ fn report_atomic_type_validation_error<'tcx>(
50
51
fx. bcx . ins ( ) . trap ( TrapCode :: user ( 1 /* unreachable */ ) . unwrap ( ) ) ;
51
52
}
52
53
54
+ pub ( crate ) fn long_double_is_f128 ( tcx : TyCtxt < ' _ > ) -> bool {
55
+ !tcx. sess . target . is_like_windows
56
+ && !tcx. sess . target . is_like_darwin
57
+ && matches ! ( & * tcx. sess. target. arch, "aarch64" | "riscv64" | "s390x" )
58
+ }
59
+
53
60
pub ( crate ) fn clif_vector_type < ' tcx > ( tcx : TyCtxt < ' tcx > , layout : TyAndLayout < ' tcx > ) -> Type {
54
61
let ( element, count) = match layout. backend_repr {
55
62
BackendRepr :: SimdVector { element, count } => ( element, count) ,
@@ -248,8 +255,10 @@ fn bool_to_zero_or_max_uint<'tcx>(
248
255
let ty = fx. clif_type ( ty) . unwrap ( ) ;
249
256
250
257
let int_ty = match ty {
258
+ types:: F16 => types:: I16 ,
251
259
types:: F32 => types:: I32 ,
252
260
types:: F64 => types:: I64 ,
261
+ types:: F128 => types:: I128 ,
253
262
ty => ty,
254
263
} ;
255
264
@@ -308,45 +317,83 @@ fn codegen_float_intrinsic_call<'tcx>(
308
317
ret : CPlace < ' tcx > ,
309
318
) -> bool {
310
319
let ( name, arg_count, ty, clif_ty) = match intrinsic {
320
+ sym:: expf16 => ( "expf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
311
321
sym:: expf32 => ( "expf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
312
322
sym:: expf64 => ( "exp" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
323
+ sym:: expf128 => ( "expf128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
324
+ sym:: exp2f16 => ( "exp2f16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
313
325
sym:: exp2f32 => ( "exp2f" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
314
326
sym:: exp2f64 => ( "exp2" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
327
+ sym:: exp2f128 => ( "exp2f128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
328
+ sym:: sqrtf16 => ( "sqrtf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
315
329
sym:: sqrtf32 => ( "sqrtf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
316
330
sym:: sqrtf64 => ( "sqrt" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
331
+ sym:: sqrtf128 => ( "sqrtf128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
332
+ sym:: powif16 => ( "__powisf2" , 2 , fx. tcx . types . f16 , types:: F16 ) , // compiler-builtins
317
333
sym:: powif32 => ( "__powisf2" , 2 , fx. tcx . types . f32 , types:: F32 ) , // compiler-builtins
318
334
sym:: powif64 => ( "__powidf2" , 2 , fx. tcx . types . f64 , types:: F64 ) , // compiler-builtins
335
+ sym:: powif128 => ( "__powitf2" , 2 , fx. tcx . types . f128 , types:: F128 ) , // compiler-builtins
336
+ sym:: powf16 => ( "powf16" , 2 , fx. tcx . types . f16 , types:: F16 ) ,
319
337
sym:: powf32 => ( "powf" , 2 , fx. tcx . types . f32 , types:: F32 ) ,
320
338
sym:: powf64 => ( "pow" , 2 , fx. tcx . types . f64 , types:: F64 ) ,
339
+ sym:: powf128 => ( "powf128" , 2 , fx. tcx . types . f128 , types:: F128 ) ,
340
+ sym:: logf16 => ( "logf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
321
341
sym:: logf32 => ( "logf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
322
342
sym:: logf64 => ( "log" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
343
+ sym:: logf128 => ( "logf128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
344
+ sym:: log2f16 => ( "log2f16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
323
345
sym:: log2f32 => ( "log2f" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
324
346
sym:: log2f64 => ( "log2" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
347
+ sym:: log2f128 => ( "log2f16" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
348
+ sym:: log10f16 => ( "log10f16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
325
349
sym:: log10f32 => ( "log10f" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
326
350
sym:: log10f64 => ( "log10" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
351
+ sym:: log10f128 => ( "log10f128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
352
+ sym:: fabsf16 => ( "fabsf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
327
353
sym:: fabsf32 => ( "fabsf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
328
354
sym:: fabsf64 => ( "fabs" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
355
+ sym:: fabsf128 => ( "fabsf128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
356
+ sym:: fmaf16 => ( "fmaf16" , 3 , fx. tcx . types . f16 , types:: F16 ) ,
329
357
sym:: fmaf32 => ( "fmaf" , 3 , fx. tcx . types . f32 , types:: F32 ) ,
330
358
sym:: fmaf64 => ( "fma" , 3 , fx. tcx . types . f64 , types:: F64 ) ,
359
+ sym:: fmaf128 => ( "fmaf128" , 3 , fx. tcx . types . f128 , types:: F128 ) ,
331
360
// FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation
361
+ sym:: fmuladdf16 => ( "fmaf16" , 3 , fx. tcx . types . f16 , types:: F16 ) , // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f16
332
362
sym:: fmuladdf32 => ( "fmaf" , 3 , fx. tcx . types . f32 , types:: F32 ) , // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f32
333
363
sym:: fmuladdf64 => ( "fma" , 3 , fx. tcx . types . f64 , types:: F64 ) , // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f64
364
+ sym:: fmuladdf128 => ( "fmaf128" , 3 , fx. tcx . types . f128 , types:: F128 ) , // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f128
365
+ sym:: copysignf16 => ( "copysignf16" , 2 , fx. tcx . types . f16 , types:: F16 ) ,
334
366
sym:: copysignf32 => ( "copysignf" , 2 , fx. tcx . types . f32 , types:: F32 ) ,
335
367
sym:: copysignf64 => ( "copysign" , 2 , fx. tcx . types . f64 , types:: F64 ) ,
368
+ sym:: copysignf128 => ( "copysignf128" , 2 , fx. tcx . types . f128 , types:: F128 ) ,
369
+ sym:: floorf16 => ( "floorf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
336
370
sym:: floorf32 => ( "floorf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
337
371
sym:: floorf64 => ( "floor" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
372
+ sym:: floorf128 => ( "floorf128" , 1 , fx. tcx . types . f16 , types:: F128 ) ,
373
+ sym:: ceilf16 => ( "ceilf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
338
374
sym:: ceilf32 => ( "ceilf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
339
375
sym:: ceilf64 => ( "ceil" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
376
+ sym:: ceilf128 => ( "ceilf128" , 1 , fx. tcx . types . f16 , types:: F128 ) ,
377
+ sym:: truncf16 => ( "truncf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
340
378
sym:: truncf32 => ( "truncf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
341
379
sym:: truncf64 => ( "trunc" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
380
+ sym:: truncf128 => ( "truncf128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
381
+ sym:: round_ties_even_f16 => ( "rintf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
342
382
sym:: round_ties_even_f32 => ( "rintf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
343
383
sym:: round_ties_even_f64 => ( "rint" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
384
+ sym:: round_ties_even_f128 => ( "rintf128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
385
+ sym:: roundf16 => ( "roundf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
344
386
sym:: roundf32 => ( "roundf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
345
387
sym:: roundf64 => ( "round" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
388
+ sym:: roundf128 => ( "roundf128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
389
+ sym:: sinf16 => ( "sinf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
346
390
sym:: sinf32 => ( "sinf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
347
391
sym:: sinf64 => ( "sin" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
392
+ sym:: sinf128 => ( "sinf128" , 1 , fx. tcx . types . f16 , types:: F128 ) ,
393
+ sym:: cosf16 => ( "cosf16" , 1 , fx. tcx . types . f16 , types:: F16 ) ,
348
394
sym:: cosf32 => ( "cosf" , 1 , fx. tcx . types . f32 , types:: F32 ) ,
349
395
sym:: cosf64 => ( "cos" , 1 , fx. tcx . types . f64 , types:: F64 ) ,
396
+ sym:: cosf128 => ( "cosf128" , 1 , fx. tcx . types . f128 , types:: F128 ) ,
350
397
_ => return false ,
351
398
} ;
352
399
@@ -380,33 +427,61 @@ fn codegen_float_intrinsic_call<'tcx>(
380
427
381
428
let layout = fx. layout_of ( ty) ;
382
429
let res = match intrinsic {
383
- sym:: fmaf32 | sym:: fmaf64 | sym:: fmuladdf32 | sym:: fmuladdf64 => {
384
- CValue :: by_val ( fx. bcx . ins ( ) . fma ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) , layout)
385
- }
386
- sym:: copysignf32 | sym:: copysignf64 => {
430
+ sym:: fmaf16
431
+ | sym:: fmaf32
432
+ | sym:: fmaf64
433
+ | sym:: fmaf128
434
+ | sym:: fmuladdf16
435
+ | sym:: fmuladdf32
436
+ | sym:: fmuladdf64
437
+ | sym:: fmuladdf128 => CValue :: by_val ( fx. bcx . ins ( ) . fma ( args[ 0 ] , args[ 1 ] , args[ 2 ] ) , layout) ,
438
+ sym:: copysignf16 | sym:: copysignf32 | sym:: copysignf64 | sym:: copysignf128 => {
387
439
CValue :: by_val ( fx. bcx . ins ( ) . fcopysign ( args[ 0 ] , args[ 1 ] ) , layout)
388
440
}
389
- sym:: fabsf32
441
+ sym:: fabsf16
442
+ | sym:: fabsf32
390
443
| sym:: fabsf64
444
+ | sym:: fabsf128
445
+ | sym:: floorf16
391
446
| sym:: floorf32
392
447
| sym:: floorf64
448
+ | sym:: floorf128
449
+ | sym:: ceilf16
393
450
| sym:: ceilf32
394
451
| sym:: ceilf64
452
+ | sym:: ceilf128
453
+ | sym:: truncf16
395
454
| sym:: truncf32
396
455
| sym:: truncf64
456
+ | sym:: truncf128
457
+ | sym:: round_ties_even_f16
397
458
| sym:: round_ties_even_f32
398
459
| sym:: round_ties_even_f64
460
+ | sym:: round_ties_even_f128
461
+ | sym:: sqrtf16
399
462
| sym:: sqrtf32
400
- | sym:: sqrtf64 => {
463
+ | sym:: sqrtf64
464
+ | sym:: sqrtf128 => {
401
465
let val = match intrinsic {
402
- sym:: fabsf32 | sym:: fabsf64 => fx. bcx . ins ( ) . fabs ( args[ 0 ] ) ,
403
- sym:: floorf32 | sym:: floorf64 => fx. bcx . ins ( ) . floor ( args[ 0 ] ) ,
404
- sym:: ceilf32 | sym:: ceilf64 => fx. bcx . ins ( ) . ceil ( args[ 0 ] ) ,
405
- sym:: truncf32 | sym:: truncf64 => fx. bcx . ins ( ) . trunc ( args[ 0 ] ) ,
406
- sym:: round_ties_even_f32 | sym:: round_ties_even_f64 => {
407
- fx. bcx . ins ( ) . nearest ( args[ 0 ] )
466
+ sym:: fabsf16 | sym:: fabsf32 | sym:: fabsf64 | sym:: fabsf128 => {
467
+ fx. bcx . ins ( ) . fabs ( args[ 0 ] )
468
+ }
469
+ sym:: floorf16 | sym:: floorf32 | sym:: floorf64 | sym:: floorf128 => {
470
+ fx. bcx . ins ( ) . floor ( args[ 0 ] )
471
+ }
472
+ sym:: ceilf16 | sym:: ceilf32 | sym:: ceilf64 | sym:: ceilf128 => {
473
+ fx. bcx . ins ( ) . ceil ( args[ 0 ] )
474
+ }
475
+ sym:: truncf16 | sym:: truncf32 | sym:: truncf64 | sym:: truncf128 => {
476
+ fx. bcx . ins ( ) . trunc ( args[ 0 ] )
477
+ }
478
+ sym:: round_ties_even_f16
479
+ | sym:: round_ties_even_f32
480
+ | sym:: round_ties_even_f64
481
+ | sym:: round_ties_even_f128 => fx. bcx . ins ( ) . nearest ( args[ 0 ] ) ,
482
+ sym:: sqrtf16 | sym:: sqrtf32 | sym:: sqrtf64 | sym:: sqrtf128 => {
483
+ fx. bcx . ins ( ) . sqrt ( args[ 0 ] )
408
484
}
409
- sym:: sqrtf32 | sym:: sqrtf64 => fx. bcx . ins ( ) . sqrt ( args[ 0 ] ) ,
410
485
_ => unreachable ! ( ) ,
411
486
} ;
412
487
@@ -415,12 +490,32 @@ fn codegen_float_intrinsic_call<'tcx>(
415
490
416
491
// These intrinsics aren't supported natively by Cranelift.
417
492
// Lower them to a libcall.
418
- sym:: powif32 | sym:: powif64 => {
493
+ sym:: powif16 | sym:: powif32 | sym:: powif64 | sym:: powif128 => {
494
+ let temp;
495
+ let ( clif_ty, args) = if intrinsic == sym:: powif16 {
496
+ temp = [ fx. bcx . ins ( ) . fpromote ( types:: F32 , args[ 0 ] ) , args[ 1 ] ] ;
497
+ ( types:: F32 , temp. as_slice ( ) )
498
+ } else {
499
+ ( clif_ty, args)
500
+ } ;
419
501
let input_tys: Vec < _ > = vec ! [ AbiParam :: new( clif_ty) , AbiParam :: new( types:: I32 ) ] ;
420
502
let ret_val = fx. lib_call ( name, input_tys, vec ! [ AbiParam :: new( clif_ty) ] , & args) [ 0 ] ;
503
+ let ret_val = if intrinsic == sym:: powif16 {
504
+ fx. bcx . ins ( ) . fdemote ( types:: F16 , ret_val)
505
+ } else {
506
+ ret_val
507
+ } ;
421
508
CValue :: by_val ( ret_val, fx. layout_of ( ty) )
422
509
}
423
510
_ => {
511
+ let temp;
512
+ let name = match name. strip_suffix ( "f128" ) {
513
+ Some ( base) if intrinsics:: long_double_is_f128 ( fx. tcx ) => {
514
+ temp = format ! ( "{base}l" ) ;
515
+ & temp
516
+ }
517
+ _ => name,
518
+ } ;
424
519
let input_tys: Vec < _ > = args. iter ( ) . map ( |_| AbiParam :: new ( clif_ty) ) . collect ( ) ;
425
520
let ret_val = fx. lib_call ( name, input_tys, vec ! [ AbiParam :: new( clif_ty) ] , & args) [ 0 ] ;
426
521
CValue :: by_val ( ret_val, fx. layout_of ( ty) )
@@ -1117,40 +1212,24 @@ fn codegen_regular_intrinsic_call<'tcx>(
1117
1212
ret. write_cvalue ( fx, old) ;
1118
1213
}
1119
1214
1120
- sym:: minnumf32 => {
1215
+ sym:: minnumf16 | sym :: minnumf32 | sym :: minnumf64 | sym :: minnumf128 => {
1121
1216
intrinsic_args ! ( fx, args => ( a, b) ; intrinsic) ;
1217
+ let layout = a. layout ( ) ;
1122
1218
let a = a. load_scalar ( fx) ;
1123
1219
let b = b. load_scalar ( fx) ;
1124
1220
1125
1221
let val = crate :: num:: codegen_float_min ( fx, a, b) ;
1126
- let val = CValue :: by_val ( val, fx. layout_of ( fx. tcx . types . f32 ) ) ;
1127
- ret. write_cvalue ( fx, val) ;
1128
- }
1129
- sym:: minnumf64 => {
1130
- intrinsic_args ! ( fx, args => ( a, b) ; intrinsic) ;
1131
- let a = a. load_scalar ( fx) ;
1132
- let b = b. load_scalar ( fx) ;
1133
-
1134
- let val = crate :: num:: codegen_float_min ( fx, a, b) ;
1135
- let val = CValue :: by_val ( val, fx. layout_of ( fx. tcx . types . f64 ) ) ;
1136
- ret. write_cvalue ( fx, val) ;
1137
- }
1138
- sym:: maxnumf32 => {
1139
- intrinsic_args ! ( fx, args => ( a, b) ; intrinsic) ;
1140
- let a = a. load_scalar ( fx) ;
1141
- let b = b. load_scalar ( fx) ;
1142
-
1143
- let val = crate :: num:: codegen_float_max ( fx, a, b) ;
1144
- let val = CValue :: by_val ( val, fx. layout_of ( fx. tcx . types . f32 ) ) ;
1222
+ let val = CValue :: by_val ( val, layout) ;
1145
1223
ret. write_cvalue ( fx, val) ;
1146
1224
}
1147
- sym:: maxnumf64 => {
1225
+ sym:: maxnumf16 | sym :: maxnumf32 | sym :: maxnumf64 | sym :: maxnumf128 => {
1148
1226
intrinsic_args ! ( fx, args => ( a, b) ; intrinsic) ;
1227
+ let layout = a. layout ( ) ;
1149
1228
let a = a. load_scalar ( fx) ;
1150
1229
let b = b. load_scalar ( fx) ;
1151
1230
1152
1231
let val = crate :: num:: codegen_float_max ( fx, a, b) ;
1153
- let val = CValue :: by_val ( val, fx . layout_of ( fx . tcx . types . f64 ) ) ;
1232
+ let val = CValue :: by_val ( val, layout ) ;
1154
1233
ret. write_cvalue ( fx, val) ;
1155
1234
}
1156
1235
0 commit comments