2020-09-23 13:13:49 +00:00
|
|
|
//! Emulate LLVM intrinsics
|
|
|
|
|
2019-07-30 12:37:20 +00:00
|
|
|
use crate::intrinsics::*;
|
2019-08-31 17:28:09 +00:00
|
|
|
use crate::prelude::*;
|
2019-07-28 07:54:57 +00:00
|
|
|
|
2020-03-27 11:14:45 +00:00
|
|
|
pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
|
2021-03-05 18:12:59 +00:00
|
|
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
2019-07-28 07:54:57 +00:00
|
|
|
intrinsic: &str,
|
2024-01-12 07:21:42 +00:00
|
|
|
args: &[Spanned<mir::Operand<'tcx>>],
|
2022-04-16 13:27:54 +00:00
|
|
|
ret: CPlace<'tcx>,
|
|
|
|
target: Option<BasicBlock>,
|
2023-11-16 21:15:07 +00:00
|
|
|
span: Span,
|
2019-07-28 07:54:57 +00:00
|
|
|
) {
|
2022-12-14 18:30:46 +00:00
|
|
|
if intrinsic.starts_with("llvm.aarch64") {
|
2024-07-01 15:07:22 +00:00
|
|
|
return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(fx, intrinsic, args, ret, target);
|
2022-12-14 18:30:46 +00:00
|
|
|
}
|
|
|
|
if intrinsic.starts_with("llvm.x86") {
|
2024-07-01 15:07:22 +00:00
|
|
|
return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, args, ret, target, span);
|
2022-12-14 18:30:46 +00:00
|
|
|
}
|
2022-10-23 14:22:55 +00:00
|
|
|
|
2022-12-14 18:30:46 +00:00
|
|
|
match intrinsic {
|
2024-01-09 13:16:09 +00:00
|
|
|
"llvm.prefetch" => {
|
|
|
|
// Nothing to do. This is merely a perf hint.
|
|
|
|
}
|
|
|
|
|
2022-12-14 18:30:46 +00:00
|
|
|
_ if intrinsic.starts_with("llvm.ctlz.v") => {
|
2022-07-26 16:53:46 +00:00
|
|
|
intrinsic_args!(fx, args => (a); intrinsic);
|
|
|
|
|
2022-12-14 18:30:46 +00:00
|
|
|
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
|
|
|
|
fx.bcx.ins().clz(lane)
|
2019-07-30 12:37:20 +00:00
|
|
|
});
|
2022-07-26 16:53:46 +00:00
|
|
|
}
|
|
|
|
|
2022-12-14 18:30:46 +00:00
|
|
|
_ if intrinsic.starts_with("llvm.ctpop.v") => {
|
|
|
|
intrinsic_args!(fx, args => (a); intrinsic);
|
2022-07-26 16:53:46 +00:00
|
|
|
|
2022-12-14 18:30:46 +00:00
|
|
|
simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
|
|
|
|
fx.bcx.ins().popcnt(lane)
|
2020-08-15 18:55:03 +00:00
|
|
|
});
|
2022-07-26 16:53:46 +00:00
|
|
|
}
|
|
|
|
|
2023-11-10 11:30:51 +00:00
|
|
|
_ if intrinsic.starts_with("llvm.fma.v") => {
|
|
|
|
intrinsic_args!(fx, args => (x,y,z); intrinsic);
|
|
|
|
|
|
|
|
simd_trio_for_each_lane(
|
|
|
|
fx,
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
z,
|
|
|
|
ret,
|
|
|
|
&|fx, _lane_ty, _res_lane_ty, lane_x, lane_y, lane_z| {
|
|
|
|
fx.bcx.ins().fma(lane_x, lane_y, lane_z)
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-07-26 16:53:46 +00:00
|
|
|
_ => {
|
|
|
|
fx.tcx
|
2023-12-18 11:21:37 +00:00
|
|
|
.dcx()
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 03:26:58 +00:00
|
|
|
.warn(format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
|
2022-07-26 16:53:46 +00:00
|
|
|
crate::trap::trap_unimplemented(fx, intrinsic);
|
2022-08-24 16:40:58 +00:00
|
|
|
return;
|
2022-07-26 16:53:46 +00:00
|
|
|
}
|
2019-07-29 10:43:24 +00:00
|
|
|
}
|
2019-07-28 07:54:57 +00:00
|
|
|
|
2022-04-16 13:27:54 +00:00
|
|
|
let dest = target.expect("all llvm intrinsics used by stdlib should return");
|
2022-03-20 15:55:21 +00:00
|
|
|
let ret_block = fx.get_block(dest);
|
|
|
|
fx.bcx.ins().jump(ret_block, &[]);
|
2019-07-28 07:54:57 +00:00
|
|
|
}
|