Skip to content

Commit 31ea518

Browse files
committed
add simd_cttz and simd_ctlz
1 parent 11db9de commit 31ea518

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

src/tools/miri/src/shims/intrinsics/simd.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_apfloat::{Float, Round};
22
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
33
use rustc_middle::{mir, ty, ty::FloatTy};
4+
use rustc_span::{sym, Symbol};
45
use rustc_target::abi::{Endian, HasDataLayout};
56

67
use crate::*;
@@ -25,7 +26,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
2526
| "floor"
2627
| "round"
2728
| "trunc"
28-
| "fsqrt" => {
29+
| "fsqrt"
30+
| "ctlz"
31+
| "cttz"
32+
=> {
2933
let [op] = check_arg_count(args)?;
3034
let (op, op_len) = this.operand_to_simd(op)?;
3135
let (dest, dest_len) = this.place_to_simd(dest)?;
@@ -38,6 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
3842
Abs,
3943
Sqrt,
4044
Round(rustc_apfloat::Round),
45+
Numeric(Symbol),
4146
}
4247
let which = match intrinsic_name {
4348
"neg" => Op::MirOp(mir::UnOp::Neg),
@@ -47,6 +52,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
4752
"floor" => Op::Round(rustc_apfloat::Round::TowardNegative),
4853
"round" => Op::Round(rustc_apfloat::Round::NearestTiesToAway),
4954
"trunc" => Op::Round(rustc_apfloat::Round::TowardZero),
55+
"ctlz" => Op::Numeric(sym::ctlz),
56+
"cttz" => Op::Numeric(sym::cttz),
5057
_ => unreachable!(),
5158
};
5259

@@ -101,6 +108,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
101108
}
102109
}
103110
}
111+
Op::Numeric(name) => {
112+
assert!(op.layout.ty.is_integral());
113+
let size = op.layout.size;
114+
let bits = op.to_scalar().to_bits(size).unwrap();
115+
let extra = 128u128.checked_sub(u128::from(size.bits())).unwrap();
116+
let bits_out = match name {
117+
sym::ctlz => u128::from(bits.leading_zeros()).checked_sub(extra).unwrap(),
118+
sym::cttz => u128::from((bits << extra).trailing_zeros()).checked_sub(extra).unwrap(),
119+
_ => unreachable!(),
120+
};
121+
Scalar::from_uint(bits_out, size)
122+
}
104123
};
105124
this.write_scalar(val, &dest)?;
106125
}
@@ -126,7 +145,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
126145
| "fmin"
127146
| "saturating_add"
128147
| "saturating_sub"
129-
| "arith_offset" => {
148+
| "arith_offset"
149+
=> {
130150
use mir::BinOp;
131151

132152
let [left, right] = check_arg_count(args)?;

src/tools/miri/tests/pass/portable-simd.rs

+5
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ fn simd_ops_i32() {
197197
assert_eq!(b.reduce_or(), -1);
198198
assert_eq!(a.reduce_xor(), 0);
199199
assert_eq!(b.reduce_xor(), -4);
200+
201+
assert_eq!(b.leading_zeros(), u32x4::from_array([31, 30, 30, 0]));
202+
assert_eq!(b.trailing_zeros(), u32x4::from_array([0, 1, 0, 2]));
203+
assert_eq!(b.leading_ones(), u32x4::from_array([0, 0, 0, 30]));
204+
assert_eq!(b.trailing_ones(), u32x4::from_array([1, 0, 2, 0]));
200205
}
201206

202207
fn simd_mask() {

0 commit comments

Comments
 (0)