Auto merge of #149085 - matthiaskrgr:rollup-f8ia15e, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang/rust#147171 (recommend using a HashMap if a HashSet's second generic parameter doesn't implement BuildHasher) - rust-lang/rust#147421 (Add check if span is from macro expansion) - rust-lang/rust#147521 (Make SIMD intrinsics available in `const`-contexts) - rust-lang/rust#148201 (Start documenting autodiff activities) - rust-lang/rust#148797 (feat: Add `bit_width` for unsigned `NonZero<T>`) - rust-lang/rust#148798 (Match <OsString as Debug>::fmt to that of str) - rust-lang/rust#149082 (autodiff: update formating, improve examples for the unstable-book) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
140044cffa
44 changed files with 884 additions and 425 deletions
|
|
@ -1754,6 +1754,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.note(note);
|
||||
}
|
||||
|
||||
if let ty::Adt(adt_def, _) = rcvr_ty.kind() {
|
||||
unsatisfied_predicates.iter().find(|(pred, _parent, _cause)| {
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
|
||||
pred.kind().skip_binder()
|
||||
{
|
||||
self.suggest_hashmap_on_unsatisfied_hashset_buildhasher(
|
||||
err, &pred, *adt_def,
|
||||
)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
*suggested_derive = self.suggest_derive(err, unsatisfied_predicates);
|
||||
*unsatisfied_bounds = true;
|
||||
}
|
||||
|
|
@ -2990,7 +3004,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
match pred.self_ty().kind() {
|
||||
ty::Adt(_, _) => Some(pred),
|
||||
ty::Adt(_, _) => Some((e.root_obligation.predicate, pred)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -3000,7 +3014,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
// Note for local items and foreign items respectively.
|
||||
let (mut local_preds, mut foreign_preds): (Vec<_>, Vec<_>) =
|
||||
preds.iter().partition(|&pred| {
|
||||
preds.iter().partition(|&(_, pred)| {
|
||||
if let ty::Adt(def, _) = pred.self_ty().kind() {
|
||||
def.did().is_local()
|
||||
} else {
|
||||
|
|
@ -3008,10 +3022,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
});
|
||||
|
||||
local_preds.sort_by_key(|pred: &&ty::TraitPredicate<'_>| pred.trait_ref.to_string());
|
||||
local_preds.sort_by_key(|(_, pred)| pred.trait_ref.to_string());
|
||||
let local_def_ids = local_preds
|
||||
.iter()
|
||||
.filter_map(|pred| match pred.self_ty().kind() {
|
||||
.filter_map(|(_, pred)| match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => Some(def.did()),
|
||||
_ => None,
|
||||
})
|
||||
|
|
@ -3024,7 +3038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
for pred in &local_preds {
|
||||
for (_, pred) in &local_preds {
|
||||
if let ty::Adt(def, _) = pred.self_ty().kind() {
|
||||
local_spans.push_span_label(
|
||||
self.tcx.def_span(def.did()),
|
||||
|
|
@ -3033,7 +3047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
if local_spans.primary_span().is_some() {
|
||||
let msg = if let [local_pred] = local_preds.as_slice() {
|
||||
let msg = if let [(_, local_pred)] = local_preds.as_slice() {
|
||||
format!(
|
||||
"an implementation of `{}` might be missing for `{}`",
|
||||
local_pred.trait_ref.print_trait_sugared(),
|
||||
|
|
@ -3051,9 +3065,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
err.span_note(local_spans, msg);
|
||||
}
|
||||
|
||||
foreign_preds.sort_by_key(|pred: &&ty::TraitPredicate<'_>| pred.trait_ref.to_string());
|
||||
foreign_preds
|
||||
.sort_by_key(|(_, pred): &(_, ty::TraitPredicate<'_>)| pred.trait_ref.to_string());
|
||||
|
||||
for pred in foreign_preds {
|
||||
for (_, pred) in &foreign_preds {
|
||||
let ty = pred.self_ty();
|
||||
let ty::Adt(def, _) = ty.kind() else { continue };
|
||||
let span = self.tcx.def_span(def.did());
|
||||
|
|
@ -3066,6 +3081,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
mspan,
|
||||
format!("`{ty}` does not implement `{}`", pred.trait_ref.print_trait_sugared()),
|
||||
);
|
||||
|
||||
foreign_preds.iter().find(|&(root_pred, pred)| {
|
||||
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(root_pred)) =
|
||||
root_pred.kind().skip_binder()
|
||||
&& let Some(root_adt) = root_pred.self_ty().ty_adt_def()
|
||||
{
|
||||
self.suggest_hashmap_on_unsatisfied_hashset_buildhasher(err, pred, root_adt)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let preds: Vec<_> = errors
|
||||
|
|
@ -4388,6 +4414,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
self.autoderef(span, rcvr_ty).silence_errors().any(|(ty, _)| is_local(ty))
|
||||
}
|
||||
|
||||
fn suggest_hashmap_on_unsatisfied_hashset_buildhasher(
|
||||
&self,
|
||||
err: &mut Diag<'_>,
|
||||
pred: &ty::TraitPredicate<'_>,
|
||||
adt: ty::AdtDef<'_>,
|
||||
) -> bool {
|
||||
if self.tcx.is_diagnostic_item(sym::HashSet, adt.did())
|
||||
&& self.tcx.is_diagnostic_item(sym::BuildHasher, pred.def_id())
|
||||
{
|
||||
err.help("you might have intended to use a HashMap instead");
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
|
|
|||
|
|
@ -124,6 +124,11 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
|
|||
return;
|
||||
};
|
||||
|
||||
// This check needs to avoid ICE from when `receiver_arg` is from macro expansion
|
||||
// Which leads to empty span in span arithmetic below
|
||||
// cc: https://github.com/rust-lang/rust/issues/147408
|
||||
let span = receiver_arg.span.find_ancestor_in_same_ctxt(expr.span);
|
||||
|
||||
// If this expression comes from the `IntoIter::into_iter` inside of a for loop,
|
||||
// we should just suggest removing the `.into_iter()` or changing it to `.iter()`
|
||||
// to disambiguate if we want to iterate by-value or by-ref.
|
||||
|
|
@ -134,14 +139,15 @@ impl<'tcx> LateLintPass<'tcx> for ShadowedIntoIter {
|
|||
&& let hir::ExprKind::Call(path, [_]) = &arg.kind
|
||||
&& let hir::ExprKind::Path(qpath) = path.kind
|
||||
&& cx.tcx.qpath_is_lang_item(qpath, LangItem::IntoIterIntoIter)
|
||||
&& let Some(span) = span
|
||||
{
|
||||
Some(ShadowedIntoIterDiagSub::RemoveIntoIter {
|
||||
span: receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
span: span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
})
|
||||
} else if can_suggest_ufcs {
|
||||
} else if can_suggest_ufcs && let Some(span) = span {
|
||||
Some(ShadowedIntoIterDiagSub::UseExplicitIntoIter {
|
||||
start_span: expr.span.shrink_to_lo(),
|
||||
end_span: receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
end_span: span.shrink_to_hi().to(expr.span.shrink_to_hi()),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -191,6 +191,7 @@ symbols! {
|
|||
Borrow,
|
||||
BorrowMut,
|
||||
Break,
|
||||
BuildHasher,
|
||||
C,
|
||||
CStr,
|
||||
C_dash_unwind: "C-unwind",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ optimize_for_size = []
|
|||
# Make `RefCell` store additional debugging information, which is printed out when
|
||||
# a borrow error occurs
|
||||
debug_refcell = []
|
||||
llvm_enzyme = []
|
||||
|
||||
[lints.rust.unexpected_cfgs]
|
||||
level = "warn"
|
||||
|
|
@ -38,4 +39,6 @@ check-cfg = [
|
|||
'cfg(target_has_reliable_f16_math)',
|
||||
'cfg(target_has_reliable_f128)',
|
||||
'cfg(target_has_reliable_f128_math)',
|
||||
'cfg(llvm_enzyme)',
|
||||
|
||||
]
|
||||
|
|
|
|||
|
|
@ -633,6 +633,7 @@ impl<H: Hasher + ?Sized> Hasher for &mut H {
|
|||
///
|
||||
/// [`build_hasher`]: BuildHasher::build_hasher
|
||||
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "BuildHasher")]
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
pub trait BuildHasher {
|
||||
/// Type of the hasher that will be created.
|
||||
|
|
|
|||
|
|
@ -64,21 +64,21 @@ pub unsafe fn simd_extract_dyn<T, U>(x: T, idx: u32) -> U {
|
|||
/// `T` must be a vector of integers or floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_add<T>(x: T, y: T) -> T;
|
||||
pub const unsafe fn simd_add<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Subtracts `rhs` from `lhs` elementwise.
|
||||
///
|
||||
/// `T` must be a vector of integers or floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_sub<T>(lhs: T, rhs: T) -> T;
|
||||
pub const unsafe fn simd_sub<T>(lhs: T, rhs: T) -> T;
|
||||
|
||||
/// Multiplies two simd vectors elementwise.
|
||||
///
|
||||
/// `T` must be a vector of integers or floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_mul<T>(x: T, y: T) -> T;
|
||||
pub const unsafe fn simd_mul<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Divides `lhs` by `rhs` elementwise.
|
||||
///
|
||||
|
|
@ -89,7 +89,7 @@ pub unsafe fn simd_mul<T>(x: T, y: T) -> T;
|
|||
/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_div<T>(lhs: T, rhs: T) -> T;
|
||||
pub const unsafe fn simd_div<T>(lhs: T, rhs: T) -> T;
|
||||
|
||||
/// Returns remainder of two vectors elementwise.
|
||||
///
|
||||
|
|
@ -100,7 +100,7 @@ pub unsafe fn simd_div<T>(lhs: T, rhs: T) -> T;
|
|||
/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_rem<T>(lhs: T, rhs: T) -> T;
|
||||
pub const unsafe fn simd_rem<T>(lhs: T, rhs: T) -> T;
|
||||
|
||||
/// Shifts vector left elementwise, with UB on overflow.
|
||||
///
|
||||
|
|
@ -113,7 +113,7 @@ pub unsafe fn simd_rem<T>(lhs: T, rhs: T) -> T;
|
|||
/// Each element of `rhs` must be less than `<int>::BITS`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
|
||||
pub const unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
|
||||
|
||||
/// Shifts vector right elementwise, with UB on overflow.
|
||||
///
|
||||
|
|
@ -126,7 +126,7 @@ pub unsafe fn simd_shl<T>(lhs: T, rhs: T) -> T;
|
|||
/// Each element of `rhs` must be less than `<int>::BITS`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
|
||||
pub const unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
|
||||
|
||||
/// Funnel Shifts vector left elementwise, with UB on overflow.
|
||||
///
|
||||
|
|
@ -143,7 +143,7 @@ pub unsafe fn simd_shr<T>(lhs: T, rhs: T) -> T;
|
|||
/// Each element of `shift` must be less than `<int>::BITS`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T;
|
||||
pub const unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T;
|
||||
|
||||
/// Funnel Shifts vector right elementwise, with UB on overflow.
|
||||
///
|
||||
|
|
@ -160,28 +160,28 @@ pub unsafe fn simd_funnel_shl<T>(a: T, b: T, shift: T) -> T;
|
|||
/// Each element of `shift` must be less than `<int>::BITS`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_funnel_shr<T>(a: T, b: T, shift: T) -> T;
|
||||
pub const unsafe fn simd_funnel_shr<T>(a: T, b: T, shift: T) -> T;
|
||||
|
||||
/// "And"s vectors elementwise.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_and<T>(x: T, y: T) -> T;
|
||||
pub const unsafe fn simd_and<T>(x: T, y: T) -> T;
|
||||
|
||||
/// "Ors" vectors elementwise.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_or<T>(x: T, y: T) -> T;
|
||||
pub const unsafe fn simd_or<T>(x: T, y: T) -> T;
|
||||
|
||||
/// "Exclusive ors" vectors elementwise.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_xor<T>(x: T, y: T) -> T;
|
||||
pub const unsafe fn simd_xor<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Numerically casts a vector, elementwise.
|
||||
///
|
||||
|
|
@ -202,7 +202,7 @@ pub unsafe fn simd_xor<T>(x: T, y: T) -> T;
|
|||
/// * Be representable in the return type, after truncating off its fractional part
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_cast<T, U>(x: T) -> U;
|
||||
pub const unsafe fn simd_cast<T, U>(x: T) -> U;
|
||||
|
||||
/// Numerically casts a vector, elementwise.
|
||||
///
|
||||
|
|
@ -216,7 +216,7 @@ pub unsafe fn simd_cast<T, U>(x: T) -> U;
|
|||
/// Otherwise, truncates or extends the value, maintaining the sign for signed integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_as<T, U>(x: T) -> U;
|
||||
pub const unsafe fn simd_as<T, U>(x: T) -> U;
|
||||
|
||||
/// Negates a vector elementwise.
|
||||
///
|
||||
|
|
@ -225,14 +225,14 @@ pub unsafe fn simd_as<T, U>(x: T) -> U;
|
|||
/// Rust panics for `-<int>::Min` due to overflow, but it is not UB with this intrinsic.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_neg<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_neg<T>(x: T) -> T;
|
||||
|
||||
/// Returns absolute value of a vector, elementwise.
|
||||
///
|
||||
/// `T` must be a vector of floating-point primitive types.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_fabs<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_fabs<T>(x: T) -> T;
|
||||
|
||||
/// Returns the minimum of two vectors, elementwise.
|
||||
///
|
||||
|
|
@ -241,7 +241,7 @@ pub unsafe fn simd_fabs<T>(x: T) -> T;
|
|||
/// Follows IEEE-754 `minNum` semantics.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_fmin<T>(x: T, y: T) -> T;
|
||||
pub const unsafe fn simd_fmin<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Returns the maximum of two vectors, elementwise.
|
||||
///
|
||||
|
|
@ -250,7 +250,7 @@ pub unsafe fn simd_fmin<T>(x: T, y: T) -> T;
|
|||
/// Follows IEEE-754 `maxNum` semantics.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_fmax<T>(x: T, y: T) -> T;
|
||||
pub const unsafe fn simd_fmax<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Tests elementwise equality of two vectors.
|
||||
///
|
||||
|
|
@ -261,7 +261,7 @@ pub unsafe fn simd_fmax<T>(x: T, y: T) -> T;
|
|||
/// Returns `0` for false and `!0` for true.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_eq<T, U>(x: T, y: T) -> U;
|
||||
pub const unsafe fn simd_eq<T, U>(x: T, y: T) -> U;
|
||||
|
||||
/// Tests elementwise inequality equality of two vectors.
|
||||
///
|
||||
|
|
@ -272,7 +272,7 @@ pub unsafe fn simd_eq<T, U>(x: T, y: T) -> U;
|
|||
/// Returns `0` for false and `!0` for true.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_ne<T, U>(x: T, y: T) -> U;
|
||||
pub const unsafe fn simd_ne<T, U>(x: T, y: T) -> U;
|
||||
|
||||
/// Tests if `x` is less than `y`, elementwise.
|
||||
///
|
||||
|
|
@ -283,7 +283,7 @@ pub unsafe fn simd_ne<T, U>(x: T, y: T) -> U;
|
|||
/// Returns `0` for false and `!0` for true.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_lt<T, U>(x: T, y: T) -> U;
|
||||
pub const unsafe fn simd_lt<T, U>(x: T, y: T) -> U;
|
||||
|
||||
/// Tests if `x` is less than or equal to `y`, elementwise.
|
||||
///
|
||||
|
|
@ -294,7 +294,7 @@ pub unsafe fn simd_lt<T, U>(x: T, y: T) -> U;
|
|||
/// Returns `0` for false and `!0` for true.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_le<T, U>(x: T, y: T) -> U;
|
||||
pub const unsafe fn simd_le<T, U>(x: T, y: T) -> U;
|
||||
|
||||
/// Tests if `x` is greater than `y`, elementwise.
|
||||
///
|
||||
|
|
@ -305,7 +305,7 @@ pub unsafe fn simd_le<T, U>(x: T, y: T) -> U;
|
|||
/// Returns `0` for false and `!0` for true.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_gt<T, U>(x: T, y: T) -> U;
|
||||
pub const unsafe fn simd_gt<T, U>(x: T, y: T) -> U;
|
||||
|
||||
/// Tests if `x` is greater than or equal to `y`, elementwise.
|
||||
///
|
||||
|
|
@ -316,7 +316,7 @@ pub unsafe fn simd_gt<T, U>(x: T, y: T) -> U;
|
|||
/// Returns `0` for false and `!0` for true.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_ge<T, U>(x: T, y: T) -> U;
|
||||
pub const unsafe fn simd_ge<T, U>(x: T, y: T) -> U;
|
||||
|
||||
/// Shuffles two vectors by const indices.
|
||||
///
|
||||
|
|
@ -332,7 +332,7 @@ pub unsafe fn simd_ge<T, U>(x: T, y: T) -> U;
|
|||
/// of `xy`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
|
||||
pub const unsafe fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
|
||||
|
||||
/// Reads a vector of pointers.
|
||||
///
|
||||
|
|
@ -353,7 +353,7 @@ pub unsafe fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
|
|||
/// `mask` must only contain `0` or `!0` values.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
|
||||
pub const unsafe fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
|
||||
|
||||
/// Writes to a vector of pointers.
|
||||
///
|
||||
|
|
@ -377,7 +377,7 @@ pub unsafe fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T;
|
|||
/// `mask` must only contain `0` or `!0` values.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V);
|
||||
pub const unsafe fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V);
|
||||
|
||||
/// A type for alignment options for SIMD masked load/store intrinsics.
|
||||
#[derive(Debug, ConstParamTy, PartialEq, Eq)]
|
||||
|
|
@ -412,7 +412,8 @@ pub enum SimdAlign {
|
|||
/// `mask` must only contain `0` or `!0` values.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_masked_load<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T) -> T;
|
||||
pub const unsafe fn simd_masked_load<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T)
|
||||
-> T;
|
||||
|
||||
/// Writes to a vector of pointers.
|
||||
///
|
||||
|
|
@ -433,14 +434,14 @@ pub unsafe fn simd_masked_load<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U,
|
|||
/// `mask` must only contain `0` or `!0` values.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_masked_store<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T);
|
||||
pub const unsafe fn simd_masked_store<V, U, T, const ALIGN: SimdAlign>(mask: V, ptr: U, val: T);
|
||||
|
||||
/// Adds two simd vectors elementwise, with saturation.
|
||||
///
|
||||
/// `T` must be a vector of integer primitive types.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_saturating_add<T>(x: T, y: T) -> T;
|
||||
pub const unsafe fn simd_saturating_add<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Subtracts two simd vectors elementwise, with saturation.
|
||||
///
|
||||
|
|
@ -449,7 +450,7 @@ pub unsafe fn simd_saturating_add<T>(x: T, y: T) -> T;
|
|||
/// Subtract `rhs` from `lhs`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T;
|
||||
pub const unsafe fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T;
|
||||
|
||||
/// Adds elements within a vector from left to right.
|
||||
///
|
||||
|
|
@ -460,7 +461,7 @@ pub unsafe fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T;
|
|||
/// Starting with the value `y`, add the elements of `x` and accumulate.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
|
||||
pub const unsafe fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
|
||||
|
||||
/// Adds elements within a vector in arbitrary order. May also be re-associated with
|
||||
/// unordered additions on the inputs/outputs.
|
||||
|
|
@ -481,7 +482,7 @@ pub unsafe fn simd_reduce_add_unordered<T, U>(x: T) -> U;
|
|||
/// Starting with the value `y`, multiply the elements of `x` and accumulate.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
|
||||
pub const unsafe fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
|
||||
|
||||
/// Multiplies elements within a vector in arbitrary order. May also be re-associated with
|
||||
/// unordered additions on the inputs/outputs.
|
||||
|
|
@ -501,7 +502,7 @@ pub unsafe fn simd_reduce_mul_unordered<T, U>(x: T) -> U;
|
|||
/// `x` must contain only `0` or `!0`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_all<T>(x: T) -> bool;
|
||||
pub const unsafe fn simd_reduce_all<T>(x: T) -> bool;
|
||||
|
||||
/// Checks if any mask value is true.
|
||||
///
|
||||
|
|
@ -511,7 +512,7 @@ pub unsafe fn simd_reduce_all<T>(x: T) -> bool;
|
|||
/// `x` must contain only `0` or `!0`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_any<T>(x: T) -> bool;
|
||||
pub const unsafe fn simd_reduce_any<T>(x: T) -> bool;
|
||||
|
||||
/// Returns the maximum element of a vector.
|
||||
///
|
||||
|
|
@ -522,7 +523,7 @@ pub unsafe fn simd_reduce_any<T>(x: T) -> bool;
|
|||
/// For floating-point values, uses IEEE-754 `maxNum`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_max<T, U>(x: T) -> U;
|
||||
pub const unsafe fn simd_reduce_max<T, U>(x: T) -> U;
|
||||
|
||||
/// Returns the minimum element of a vector.
|
||||
///
|
||||
|
|
@ -533,7 +534,7 @@ pub unsafe fn simd_reduce_max<T, U>(x: T) -> U;
|
|||
/// For floating-point values, uses IEEE-754 `minNum`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_min<T, U>(x: T) -> U;
|
||||
pub const unsafe fn simd_reduce_min<T, U>(x: T) -> U;
|
||||
|
||||
/// Logical "and"s all elements together.
|
||||
///
|
||||
|
|
@ -542,7 +543,7 @@ pub unsafe fn simd_reduce_min<T, U>(x: T) -> U;
|
|||
/// `U` must be the element type of `T`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_and<T, U>(x: T) -> U;
|
||||
pub const unsafe fn simd_reduce_and<T, U>(x: T) -> U;
|
||||
|
||||
/// Logical "ors" all elements together.
|
||||
///
|
||||
|
|
@ -551,7 +552,7 @@ pub unsafe fn simd_reduce_and<T, U>(x: T) -> U;
|
|||
/// `U` must be the element type of `T`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_or<T, U>(x: T) -> U;
|
||||
pub const unsafe fn simd_reduce_or<T, U>(x: T) -> U;
|
||||
|
||||
/// Logical "exclusive ors" all elements together.
|
||||
///
|
||||
|
|
@ -560,7 +561,7 @@ pub unsafe fn simd_reduce_or<T, U>(x: T) -> U;
|
|||
/// `U` must be the element type of `T`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_reduce_xor<T, U>(x: T) -> U;
|
||||
pub const unsafe fn simd_reduce_xor<T, U>(x: T) -> U;
|
||||
|
||||
/// Truncates an integer vector to a bitmask.
|
||||
///
|
||||
|
|
@ -597,7 +598,7 @@ pub unsafe fn simd_reduce_xor<T, U>(x: T) -> U;
|
|||
/// `x` must contain only `0` and `!0`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_bitmask<T, U>(x: T) -> U;
|
||||
pub const unsafe fn simd_bitmask<T, U>(x: T) -> U;
|
||||
|
||||
/// Selects elements from a mask.
|
||||
///
|
||||
|
|
@ -613,7 +614,7 @@ pub unsafe fn simd_bitmask<T, U>(x: T) -> U;
|
|||
/// `mask` must only contain `0` and `!0`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
|
||||
pub const unsafe fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
|
||||
|
||||
/// Selects elements from a bitmask.
|
||||
///
|
||||
|
|
@ -629,7 +630,7 @@ pub unsafe fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T;
|
|||
/// The bitmask bit order matches `simd_bitmask`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
|
||||
pub const unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
|
||||
|
||||
/// Calculates the offset from a pointer vector elementwise, potentially
|
||||
/// wrapping.
|
||||
|
|
@ -641,14 +642,14 @@ pub unsafe fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T;
|
|||
/// Operates as if by `<ptr>::wrapping_offset`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T;
|
||||
pub const unsafe fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T;
|
||||
|
||||
/// Casts a vector of pointers.
|
||||
///
|
||||
/// `T` and `U` must be vectors of pointers with the same number of elements.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_cast_ptr<T, U>(ptr: T) -> U;
|
||||
pub const unsafe fn simd_cast_ptr<T, U>(ptr: T) -> U;
|
||||
|
||||
/// Exposes a vector of pointers as a vector of addresses.
|
||||
///
|
||||
|
|
@ -666,56 +667,56 @@ pub unsafe fn simd_expose_provenance<T, U>(ptr: T) -> U;
|
|||
/// `U` must be a vector of pointers, with the same length as `T`.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_with_exposed_provenance<T, U>(addr: T) -> U;
|
||||
pub const unsafe fn simd_with_exposed_provenance<T, U>(addr: T) -> U;
|
||||
|
||||
/// Swaps bytes of each element.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_bswap<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_bswap<T>(x: T) -> T;
|
||||
|
||||
/// Reverses bits of each element.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_bitreverse<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_bitreverse<T>(x: T) -> T;
|
||||
|
||||
/// Counts the leading zeros of each element.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_ctlz<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_ctlz<T>(x: T) -> T;
|
||||
|
||||
/// Counts the number of ones in each element.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_ctpop<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_ctpop<T>(x: T) -> T;
|
||||
|
||||
/// Counts the trailing zeros of each element.
|
||||
///
|
||||
/// `T` must be a vector of integers.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_cttz<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_cttz<T>(x: T) -> T;
|
||||
|
||||
/// Rounds up each element to the next highest integer-valued float.
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_ceil<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_ceil<T>(x: T) -> T;
|
||||
|
||||
/// Rounds down each element to the next lowest integer-valued float.
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_floor<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_floor<T>(x: T) -> T;
|
||||
|
||||
/// Rounds each element to the closest integer-valued float.
|
||||
/// Ties are resolved by rounding away from 0.
|
||||
|
|
@ -723,7 +724,7 @@ pub unsafe fn simd_floor<T>(x: T) -> T;
|
|||
/// `T` must be a vector of floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_round<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_round<T>(x: T) -> T;
|
||||
|
||||
/// Rounds each element to the closest integer-valued float.
|
||||
/// Ties are resolved by rounding to the number with an even least significant digit
|
||||
|
|
@ -731,7 +732,7 @@ pub unsafe fn simd_round<T>(x: T) -> T;
|
|||
/// `T` must be a vector of floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_round_ties_even<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_round_ties_even<T>(x: T) -> T;
|
||||
|
||||
/// Returns the integer part of each element as an integer-valued float.
|
||||
/// In other words, non-integer values are truncated towards zero.
|
||||
|
|
@ -739,7 +740,7 @@ pub unsafe fn simd_round_ties_even<T>(x: T) -> T;
|
|||
/// `T` must be a vector of floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_trunc<T>(x: T) -> T;
|
||||
pub const unsafe fn simd_trunc<T>(x: T) -> T;
|
||||
|
||||
/// Takes the square root of each element.
|
||||
///
|
||||
|
|
@ -753,7 +754,7 @@ pub unsafe fn simd_fsqrt<T>(x: T) -> T;
|
|||
/// `T` must be a vector of floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_fma<T>(x: T, y: T, z: T) -> T;
|
||||
pub const unsafe fn simd_fma<T>(x: T, y: T, z: T) -> T;
|
||||
|
||||
/// Computes `(x*y) + z` for each element, non-deterministically executing either
|
||||
/// a fused multiply-add or two operations with rounding of the intermediate result.
|
||||
|
|
@ -768,7 +769,7 @@ pub unsafe fn simd_fma<T>(x: T, y: T, z: T) -> T;
|
|||
/// `T` must be a vector of floats.
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T;
|
||||
pub const unsafe fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T;
|
||||
|
||||
// Computes the sine of each element.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
|
|||
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
|
||||
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
|
||||
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
|
||||
///
|
||||
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
|
||||
///
|
||||
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
|
||||
/// if we are not interested in computing the derivatives with respect to this argument.
|
||||
///
|
||||
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
|
||||
/// indirect input arguments. It can also be used on a scalar float return value.
|
||||
/// If used on a return value, the generated function will return a tuple of two float scalars.
|
||||
/// If used on an input argument, a new shadow argument of the same type will be created,
|
||||
/// directly following the original argument.
|
||||
///
|
||||
/// ### Usage examples:
|
||||
///
|
||||
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
|
||||
/// #![feature(autodiff)]
|
||||
/// use std::autodiff::*;
|
||||
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
|
||||
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
|
||||
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
|
||||
/// fn rosenbrock(x: f64, y: f64) -> f64 {
|
||||
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
|
||||
/// }
|
||||
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
|
||||
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
|
||||
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
|
||||
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
|
||||
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
|
||||
/// // When seeding both arguments at once the tangent return is the sum of both.
|
||||
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
|
||||
///
|
||||
/// let mut out = 0.0;
|
||||
/// let mut dout = 0.0;
|
||||
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
|
||||
/// // (out, dout) == (400.0, -400.0)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// We might want to track how one input float affects one or more output floats. In this case,
|
||||
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
|
||||
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
|
||||
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
|
||||
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
|
||||
/// more efficient if we have more output floats marked as `Dual` than input floats.
|
||||
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
|
||||
#[unstable(feature = "autodiff", issue = "124509")]
|
||||
#[allow_internal_unstable(rustc_attrs)]
|
||||
#[allow_internal_unstable(core_intrinsics)]
|
||||
|
|
@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
|
|||
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
|
||||
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
|
||||
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
|
||||
///
|
||||
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
|
||||
///
|
||||
/// `Active` can be used for float scalar values.
|
||||
/// If used on an input, a new float will be appended to the return tuple of the generated
|
||||
/// function. If the function returns a float scalar, `Active` can be used for the return as
|
||||
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
|
||||
///
|
||||
/// `Duplicated` can be used on references, raw pointers, or other indirect input
|
||||
/// arguments. It creates a new shadow argument of the same type, following the original argument.
|
||||
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
|
||||
///
|
||||
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
|
||||
/// if we are not interested in computing the derivatives with respect to this argument.
|
||||
///
|
||||
/// ### Usage examples:
|
||||
///
|
||||
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
|
||||
/// #![feature(autodiff)]
|
||||
/// use std::autodiff::*;
|
||||
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
|
||||
/// fn rosenbrock(x: f64, y: f64) -> f64 {
|
||||
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
|
||||
/// }
|
||||
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
|
||||
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
|
||||
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
|
||||
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
|
||||
/// let mut output2 = 0.0;
|
||||
/// let mut seed = 1.0;
|
||||
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
|
||||
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// We often want to track how one or more input floats affect one output float. This output can
|
||||
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
|
||||
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
|
||||
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
|
||||
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
|
||||
/// shadow of the outputs ("seed") will be reset to zero.
|
||||
/// If the function has more than one output float marked as active or duplicated, users might want to
|
||||
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.
|
||||
/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
|
||||
/// inputs.
|
||||
/// Reverse mode is generally more efficient if we have more active/duplicated input than
|
||||
/// output floats.
|
||||
///
|
||||
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
|
||||
#[unstable(feature = "autodiff", issue = "124509")]
|
||||
#[allow_internal_unstable(rustc_attrs)]
|
||||
#[allow_internal_unstable(core_intrinsics)]
|
||||
|
|
|
|||
|
|
@ -1781,6 +1781,33 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
|
|||
// SAFETY: `self.get()` can't be zero
|
||||
unsafe { NonZero::new_unchecked(self.get().cast_signed()) }
|
||||
}
|
||||
|
||||
/// Returns the minimum number of bits required to represent `self`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(uint_bit_width)]
|
||||
///
|
||||
/// # use core::num::NonZero;
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::MIN.bit_width(), NonZero::new(1)?);")]
|
||||
#[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0b111)?.bit_width(), NonZero::new(3)?);")]
|
||||
#[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0b1110)?.bit_width(), NonZero::new(4)?);")]
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "uint_bit_width", issue = "142326")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn bit_width(self) -> NonZero<u32> {
|
||||
// SAFETY: Since `self.leading_zeros()` is always less than
|
||||
// `Self::BITS`, this subtraction can never be zero.
|
||||
unsafe { NonZero::new_unchecked(Self::BITS - self.leading_zeros()) }
|
||||
}
|
||||
};
|
||||
|
||||
// Associated items for signed nonzero types only.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use super::char::EscapeDebugExtArgs;
|
||||
use super::from_utf8_unchecked;
|
||||
use super::validations::utf8_char_width;
|
||||
use crate::fmt;
|
||||
|
|
@ -121,7 +122,11 @@ impl fmt::Debug for Debug<'_> {
|
|||
let valid = chunk.valid();
|
||||
let mut from = 0;
|
||||
for (i, c) in valid.char_indices() {
|
||||
let esc = c.escape_debug();
|
||||
let esc = c.escape_debug_ext(EscapeDebugExtArgs {
|
||||
escape_grapheme_extended: true,
|
||||
escape_single_quote: false,
|
||||
escape_double_quote: true,
|
||||
});
|
||||
// If char needs escaping, flush backlog so far and write, else skip
|
||||
if esc.len() != 1 {
|
||||
f.write_str(&valid[from..i])?;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// implementations, so, we'll have to add more doc(hidden)s anyway
|
||||
#![doc(hidden)]
|
||||
|
||||
use crate::char::encode_utf16_raw;
|
||||
use crate::char::{EscapeDebugExtArgs, encode_utf16_raw};
|
||||
use crate::clone::CloneToUninit;
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::hash::{Hash, Hasher};
|
||||
|
|
@ -144,14 +144,20 @@ impl AsRef<[u8]> for Wtf8 {
|
|||
impl fmt::Debug for Wtf8 {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result {
|
||||
use crate::fmt::Write;
|
||||
for c in s.chars().flat_map(|c| c.escape_debug()) {
|
||||
use crate::fmt::Write as _;
|
||||
for c in s.chars().flat_map(|c| {
|
||||
c.escape_debug_ext(EscapeDebugExtArgs {
|
||||
escape_grapheme_extended: true,
|
||||
escape_single_quote: false,
|
||||
escape_double_quote: true,
|
||||
})
|
||||
}) {
|
||||
f.write_char(c)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
formatter.write_str("\"")?;
|
||||
formatter.write_char('"')?;
|
||||
let mut pos = 0;
|
||||
while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
|
||||
// SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes.
|
||||
|
|
@ -164,7 +170,7 @@ impl fmt::Debug for Wtf8 {
|
|||
|
||||
// SAFETY: after next_surrogate returns None, the remainder is valid UTF-8.
|
||||
write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?;
|
||||
formatter.write_str("\"")
|
||||
formatter.write_char('"')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -570,3 +570,21 @@ fn test_nonzero_lowest_one() {
|
|||
nonzero_int_impl!(i8, i16, i32, i64, i128, isize);
|
||||
nonzero_uint_impl!(u8, u16, u32, u64, u128, usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonzero_bit_width() {
|
||||
macro_rules! nonzero_uint_impl {
|
||||
($($T:ty),+) => {
|
||||
$(
|
||||
{
|
||||
assert_eq!(NonZero::<$T>::new(0b010_1100).unwrap().bit_width(), NonZero::new(6).unwrap());
|
||||
assert_eq!(NonZero::<$T>::new(0b111_1001).unwrap().bit_width(), NonZero::new(7).unwrap());
|
||||
assert_eq!(NonZero::<$T>::MIN.bit_width(), NonZero::new(1).unwrap());
|
||||
assert_eq!(NonZero::<$T>::MAX.bit_width(), NonZero::new(<$T>::BITS).unwrap());
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
nonzero_uint_impl!(u8, u16, u32, u64, u128, usize);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,4 +80,5 @@ fn debug() {
|
|||
b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa".utf8_chunks().debug(),
|
||||
),
|
||||
);
|
||||
assert_eq!("\"'\"", &format!("{:?}", b"'".utf8_chunks().debug()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
|
|||
# a borrow error occurs
|
||||
debug_refcell = ["core/debug_refcell"]
|
||||
|
||||
llvm_enzyme = ["core/llvm_enzyme"]
|
||||
|
||||
# Enable std_detect features:
|
||||
std_detect_file_io = ["std_detect/std_detect_file_io"]
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ impl Iterator for Vars {
|
|||
impl fmt::Debug for Vars {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { inner: VarsOs { inner } } = self;
|
||||
f.debug_struct("Vars").field("inner", &inner.str_debug()).finish()
|
||||
f.debug_struct("Vars").field("inner", inner).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -303,3 +303,9 @@ fn clone_to_uninit() {
|
|||
unsafe { a.clone_to_uninit(ptr::from_mut::<OsStr>(&mut b).cast()) };
|
||||
assert_eq!(a, &*b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn debug() {
|
||||
let s = "'single quotes'";
|
||||
assert_eq!(format!("{:?}", OsStr::new(s)), format!("{:?}", s));
|
||||
}
|
||||
|
|
|
|||
17
library/std/src/sys/env/common.rs
vendored
17
library/std/src/sys/env/common.rs
vendored
|
|
@ -5,27 +5,10 @@ pub struct Env {
|
|||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
slice: &'a [(OsString, OsString)],
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list()
|
||||
.entries(self.slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self {
|
||||
Env { iter: env.into_iter() }
|
||||
}
|
||||
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
EnvStrDebug { slice: self.iter.as_slice() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
|
|
|
|||
7
library/std/src/sys/env/unsupported.rs
vendored
7
library/std/src/sys/env/unsupported.rs
vendored
|
|
@ -3,13 +3,6 @@ use crate::{fmt, io};
|
|||
|
||||
pub struct Env(!);
|
||||
|
||||
impl Env {
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
|
|
|
|||
24
library/std/src/sys/env/windows.rs
vendored
24
library/std/src/sys/env/windows.rs
vendored
|
|
@ -8,30 +8,6 @@ pub struct Env {
|
|||
iter: EnvIterator,
|
||||
}
|
||||
|
||||
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
|
||||
pub struct EnvStrDebug<'a> {
|
||||
iter: &'a EnvIterator,
|
||||
}
|
||||
|
||||
impl fmt::Debug for EnvStrDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { iter } = self;
|
||||
let iter: EnvIterator = (*iter).clone();
|
||||
let mut list = f.debug_list();
|
||||
for (a, b) in iter {
|
||||
list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
|
||||
}
|
||||
list.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn str_debug(&self) -> impl fmt::Debug + '_ {
|
||||
let Self { base: _, iter } = self;
|
||||
EnvStrDebug { iter }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { base: _, iter } = self;
|
||||
|
|
|
|||
|
|
@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
|
|||
std_detect_file_io = ["std/std_detect_file_io"]
|
||||
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
|
||||
windows_raw_dylib = ["std/windows_raw_dylib"]
|
||||
llvm_enzyme = ["std/llvm_enzyme"]
|
||||
|
|
|
|||
|
|
@ -846,6 +846,10 @@ impl Build {
|
|||
features.insert("compiler-builtins-mem");
|
||||
}
|
||||
|
||||
if self.config.llvm_enzyme {
|
||||
features.insert("llvm_enzyme");
|
||||
}
|
||||
|
||||
features.into_iter().collect::<Vec<_>>().join(" ")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,16 +6,37 @@ The tracking issue for this feature is: [#124509](https://github.com/rust-lang/r
|
|||
|
||||
This feature allows you to differentiate functions using automatic differentiation.
|
||||
Set the `-Zautodiff=<options>` compiler flag to adjust the behaviour of the autodiff feature.
|
||||
Multiple options can be separated with a comma. Valid options are:
|
||||
Multiple options can be separated with a comma.
|
||||
|
||||
`Enable` - Required flag to enable autodiff
|
||||
`PrintTA` - print Type Analysis Information
|
||||
`PrintTAFn` - print Type Analysis Information for a specific function
|
||||
`PrintAA` - print Activity Analysis Information
|
||||
`PrintPerf` - print Performance Warnings from Enzyme
|
||||
`PrintSteps` - prints all intermediate transformations
|
||||
`PrintModBefore` - print the whole module, before running opts
|
||||
`PrintModAfter` - print the module after Enzyme differentiated everything
|
||||
`LooseTypes` - Enzyme's loose type debug helper (can cause incorrect gradients)
|
||||
`Inline` - runs Enzyme specific Inlining
|
||||
`RuntimeActivity` - allow specifying activity at runtime
|
||||
## Syntax
|
||||
```bash
|
||||
rustc -Z autodiff=Enable[,options]
|
||||
```
|
||||
|
||||
Where `options` can be:
|
||||
|
||||
- `Enable` - Required flag to enable autodiff
|
||||
- `PrintTA` - print Type Analysis Information
|
||||
- `PrintTAFn=<fn_name>` - print Type Analysis Information for a specific function (consider combining it with `no_mangle`)
|
||||
- `PrintAA` - print Activity Analysis Information
|
||||
- `PrintPerf` - print Performance Warnings from Enzyme
|
||||
- `PrintSteps` - prints all intermediate transformations
|
||||
- `PrintModBefore` - print the whole module, before running opts
|
||||
- `PrintModAfter` - print the module after Enzyme differentiated everything
|
||||
- `LooseTypes` - Enzyme's loose type debug helper (can cause incorrect gradients)
|
||||
- `Inline` - runs Enzyme specific Inlining
|
||||
- `RuntimeActivity` - allow specifying activity at runtime
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# Enable autodiff via cargo, assuming `enzyme` being a toolchain that supports autodiff
|
||||
"RUSTFLAGS=-Zautodiff=Enable" cargo +enzyme build
|
||||
|
||||
# Enable autodiff directly via rustc
|
||||
rustc -Z autodiff=Enable
|
||||
|
||||
# Print TypeAnalysis updates for the function `foo`, as well as Activity Analysis for all differentiated code.
|
||||
rustc -Z autodiff=Enable,PrintTAFn=foo,PrintAA
|
||||
```
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ impl<T: Copy, const N: usize> PackedSimd<T, N> {
|
|||
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_nounwind]
|
||||
pub unsafe fn simd_shuffle_const_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
|
||||
pub const unsafe fn simd_shuffle_const_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
|
||||
|
||||
fn simd_ops_f16() {
|
||||
use intrinsics::*;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@
|
|||
|
||||
#![allow(unused)]
|
||||
#![allow(non_camel_case_types)]
|
||||
// FIXME: `cfg(minisimd_const)` is used to toggle use of const trait impls, which require a few
|
||||
// nightly features. Remove this when `const_trait_impls`, `const_cmp` and `const_index` are
|
||||
// stablilized.
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
// The field is currently left `pub` for convenience in porting tests, many of
|
||||
// which attempt to just construct it directly. That still works; it's just the
|
||||
|
|
@ -24,39 +28,32 @@ impl<T: Copy, const N: usize> Clone for Simd<T, N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, const N: usize> PartialEq for Simd<T, N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_array() == other.as_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: core::fmt::Debug, const N: usize> core::fmt::Debug for Simd<T, N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
|
||||
<[T; N] as core::fmt::Debug>::fmt(self.as_array(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> core::ops::Index<usize> for Simd<T, N> {
|
||||
type Output = T;
|
||||
fn index(&self, i: usize) -> &T {
|
||||
&self.as_array()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> Simd<T, N> {
|
||||
pub const fn from_array(a: [T; N]) -> Self {
|
||||
Simd(a)
|
||||
}
|
||||
pub fn as_array(&self) -> &[T; N] {
|
||||
pub const fn as_array(&self) -> &[T; N] {
|
||||
let p: *const Self = self;
|
||||
unsafe { &*p.cast::<[T; N]>() }
|
||||
}
|
||||
pub fn into_array(self) -> [T; N]
|
||||
pub const fn into_array(self) -> [T; N]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
*self.as_array()
|
||||
}
|
||||
pub const fn splat(a: T) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Self([a; N])
|
||||
}
|
||||
}
|
||||
|
||||
pub type u8x2 = Simd<u8, 2>;
|
||||
|
|
@ -109,6 +106,14 @@ pub type i64x8 = Simd<i64, 8>;
|
|||
pub type i128x2 = Simd<i128, 2>;
|
||||
pub type i128x4 = Simd<i128, 4>;
|
||||
|
||||
pub type usizex2 = Simd<usize, 2>;
|
||||
pub type usizex4 = Simd<usize, 4>;
|
||||
pub type usizex8 = Simd<usize, 8>;
|
||||
|
||||
pub type isizex2 = Simd<isize, 2>;
|
||||
pub type isizex4 = Simd<isize, 4>;
|
||||
pub type isizex8 = Simd<isize, 8>;
|
||||
|
||||
pub type f32x2 = Simd<f32, 2>;
|
||||
pub type f32x4 = Simd<f32, 4>;
|
||||
pub type f32x8 = Simd<f32, 8>;
|
||||
|
|
@ -122,7 +127,7 @@ pub type f64x8 = Simd<f64, 8>;
|
|||
// which attempt to just construct it directly. That still works; it's just the
|
||||
// `.0` projection that doesn't.
|
||||
#[repr(simd, packed)]
|
||||
#[derive(Copy)]
|
||||
#[derive(Copy, Eq)]
|
||||
pub struct PackedSimd<T, const N: usize>(pub [T; N]);
|
||||
|
||||
impl<T: Copy, const N: usize> Clone for PackedSimd<T, N> {
|
||||
|
|
@ -131,12 +136,6 @@ impl<T: Copy, const N: usize> Clone for PackedSimd<T, N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, const N: usize> PartialEq for PackedSimd<T, N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_array() == other.as_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: core::fmt::Debug, const N: usize> core::fmt::Debug for PackedSimd<T, N> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
|
||||
<[T; N] as core::fmt::Debug>::fmt(self.as_array(), f)
|
||||
|
|
@ -147,14 +146,81 @@ impl<T, const N: usize> PackedSimd<T, N> {
|
|||
pub const fn from_array(a: [T; N]) -> Self {
|
||||
PackedSimd(a)
|
||||
}
|
||||
pub fn as_array(&self) -> &[T; N] {
|
||||
pub const fn as_array(&self) -> &[T; N] {
|
||||
let p: *const Self = self;
|
||||
unsafe { &*p.cast::<[T; N]>() }
|
||||
}
|
||||
pub fn into_array(self) -> [T; N]
|
||||
pub const fn into_array(self) -> [T; N]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
*self.as_array()
|
||||
}
|
||||
pub const fn splat(a: T) -> Self
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
Self([a; N])
|
||||
}
|
||||
}
|
||||
|
||||
// As `const_trait_impl` is a language feature with specialized syntax, we have to use them in a way
|
||||
// such that it doesn't get parsed as Rust code unless `cfg(minisimd_const)` is on. The easiest way
|
||||
// for that is a macro
|
||||
|
||||
macro_rules! impl_traits {
|
||||
($($const_:ident)?) => {
|
||||
impl<T: $([$const_])? PartialEq, const N: usize> $($const_)? PartialEq for Simd<T, N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_array() == other.as_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, const N: usize> $($const_)? core::ops::Index<usize> for Simd<T, N> {
|
||||
type Output = T;
|
||||
fn index(&self, i: usize) -> &T {
|
||||
&self.as_array()[i]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: $([$const_])? PartialEq, const N: usize> $($const_)? PartialEq for PackedSimd<T, N>
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_array() == other.as_array()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(minisimd_const)]
|
||||
impl_traits!(const);
|
||||
|
||||
#[cfg(not(minisimd_const))]
|
||||
impl_traits!();
|
||||
|
||||
/// Version of `assert_eq` that ignores fancy runtime printing in const context.
|
||||
/// FIXME: Remove once <https://github.com/rust-lang/rust/issues/119826> is fixed.
|
||||
#[cfg(minisimd_const)]
|
||||
#[macro_export]
|
||||
macro_rules! assert_eq {
|
||||
($left:expr, $right:expr $(,)?) => {
|
||||
assert_eq!(
|
||||
$left,
|
||||
$right,
|
||||
concat!("`", stringify!($left), "` == `", stringify!($right), "`")
|
||||
);
|
||||
};
|
||||
($left:expr, $right:expr$(, $($arg:tt)+)?) => {
|
||||
{
|
||||
let left = $left;
|
||||
let right = $right;
|
||||
// type inference works better with the concrete type on the
|
||||
// left, but humans work better with the expected on the
|
||||
// right
|
||||
assert!(right == left, $($($arg)*),*);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(minisimd_const)]
|
||||
use assert_eq;
|
||||
|
|
|
|||
20
tests/ui/hashmap/hashset_generics.rs
Normal file
20
tests/ui/hashmap/hashset_generics.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
//~^ NOTE in this expansion of
|
||||
//~| NOTE in this expansion of
|
||||
//~| NOTE in this expansion of
|
||||
pub struct MyStruct {
|
||||
pub parameters: HashSet<String, String>,
|
||||
//~^ NOTE `String` does not implement `BuildHasher`
|
||||
//~| ERROR binary operation
|
||||
//~| HELP use a HashMap
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let h1 = HashSet::<usize, usize>::with_hasher(0);
|
||||
h1.insert(1);
|
||||
//~^ ERROR its trait bounds were not satisfied
|
||||
//~| NOTE the following trait bounds
|
||||
//~| HELP use a HashMap
|
||||
}
|
||||
29
tests/ui/hashmap/hashset_generics.stderr
Normal file
29
tests/ui/hashmap/hashset_generics.stderr
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
error[E0369]: binary operation `==` cannot be applied to type `HashSet<String, String>`
|
||||
--> $DIR/hashset_generics.rs:8:5
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| --------- in this derive macro expansion
|
||||
...
|
||||
LL | pub parameters: HashSet<String, String>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: `String` does not implement `BuildHasher`
|
||||
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
||||
|
|
||||
= note: `String` is defined in another crate
|
||||
= help: you might have intended to use a HashMap instead
|
||||
|
||||
error[E0599]: the method `insert` exists for struct `HashSet<usize, usize>`, but its trait bounds were not satisfied
|
||||
--> $DIR/hashset_generics.rs:16:8
|
||||
|
|
||||
LL | h1.insert(1);
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: the following trait bounds were not satisfied:
|
||||
`usize: BuildHasher`
|
||||
= help: you might have intended to use a HashMap instead
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0369, E0599.
|
||||
For more information about an error, try `rustc --explain E0369`.
|
||||
24
tests/ui/macros/macro-expansion-empty-span-147408.rs
Normal file
24
tests/ui/macros/macro-expansion-empty-span-147408.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
//@ check-pass
|
||||
//@ compile-flags: -Afor_loops_over_fallibles -Warray_into_iter
|
||||
|
||||
fn main() {
|
||||
macro_rules! mac {
|
||||
(iter $e:expr) => {
|
||||
$e.iter()
|
||||
};
|
||||
(into_iter $e:expr) => {
|
||||
$e.into_iter() //~ WARN this method call resolves to
|
||||
//~^ WARN this changes meaning in Rust 2021
|
||||
};
|
||||
(next $e:expr) => {
|
||||
$e.iter().next()
|
||||
};
|
||||
}
|
||||
|
||||
for _ in dbg!([1, 2]).iter() {}
|
||||
for _ in dbg!([1, 2]).into_iter() {} //~ WARN this method call resolves to
|
||||
//~^ WARN this changes meaning in Rust 2021
|
||||
for _ in mac!(iter [1, 2]) {}
|
||||
for _ in mac!(into_iter [1, 2]) {}
|
||||
for _ in mac!(next [1, 2]) {}
|
||||
}
|
||||
35
tests/ui/macros/macro-expansion-empty-span-147408.stderr
Normal file
35
tests/ui/macros/macro-expansion-empty-span-147408.stderr
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
|
||||
--> $DIR/macro-expansion-empty-span-147408.rs:19:27
|
||||
|
|
||||
LL | for _ in dbg!([1, 2]).into_iter() {}
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= warning: this changes meaning in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/IntoIterator-for-arrays.html>
|
||||
= note: requested on the command line with `-W array-into-iter`
|
||||
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
||||
|
|
||||
LL - for _ in dbg!([1, 2]).into_iter() {}
|
||||
LL + for _ in dbg!([1, 2]).iter() {}
|
||||
|
|
||||
help: or remove `.into_iter()` to iterate by value
|
||||
|
|
||||
LL - for _ in dbg!([1, 2]).into_iter() {}
|
||||
LL + for _ in dbg!([1, 2]) {}
|
||||
|
|
||||
|
||||
warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021
|
||||
--> $DIR/macro-expansion-empty-span-147408.rs:10:16
|
||||
|
|
||||
LL | $e.into_iter()
|
||||
| ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter`
|
||||
...
|
||||
LL | for _ in mac!(into_iter [1, 2]) {}
|
||||
| ---------------------- in this macro invocation
|
||||
|
|
||||
= warning: this changes meaning in Rust 2021
|
||||
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/IntoIterator-for-arrays.html>
|
||||
= note: this warning originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
//@ run-pass
|
||||
//@ ignore-emscripten
|
||||
//@ ignore-android
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// FIXME: this test fails on arm-android because the NDK version 14 is too old.
|
||||
// It needs at least version 18. We disable it on all android build bots because
|
||||
|
|
@ -8,7 +9,7 @@
|
|||
|
||||
// Test that the simd floating-point math intrinsics produce correct results.
|
||||
|
||||
#![feature(repr_simd, intrinsics, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
|
|
@ -20,7 +21,10 @@ use std::intrinsics::simd::*;
|
|||
macro_rules! assert_approx_eq_f32 {
|
||||
($a:expr, $b:expr) => {{
|
||||
let (a, b) = (&$a, &$b);
|
||||
assert!((*a - *b).abs() < 1.0e-6, "{} is not approximately equal to {}", *a, *b);
|
||||
assert!(
|
||||
(*a - *b).abs() < 1.0e-6,
|
||||
concat!(stringify!($a), " is not approximately equal to ", stringify!($b))
|
||||
);
|
||||
}};
|
||||
}
|
||||
macro_rules! assert_approx_eq {
|
||||
|
|
@ -34,7 +38,7 @@ macro_rules! assert_approx_eq {
|
|||
}};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const fn simple_math() {
|
||||
let x = f32x4::from_array([1.0, 1.0, 1.0, 1.0]);
|
||||
let y = f32x4::from_array([-1.0, -1.0, -1.0, -1.0]);
|
||||
let z = f32x4::from_array([0.0, 0.0, 0.0, 0.0]);
|
||||
|
|
@ -43,37 +47,7 @@ fn main() {
|
|||
|
||||
unsafe {
|
||||
let r = simd_fabs(y);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fcos(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fexp(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fexp2(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fma(x, h, h);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_relaxed_fma(x, h, h);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fsqrt(x);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_flog(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_flog2(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_flog10(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_fsin(z);
|
||||
assert_approx_eq!(z, r);
|
||||
assert_eq!(x, r);
|
||||
|
||||
// rounding functions
|
||||
let r = simd_floor(h);
|
||||
|
|
@ -90,5 +64,48 @@ fn main() {
|
|||
|
||||
let r = simd_trunc(h);
|
||||
assert_eq!(z, r);
|
||||
|
||||
let r = simd_fma(x, h, h);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_relaxed_fma(x, h, h);
|
||||
assert_approx_eq!(x, r);
|
||||
}
|
||||
}
|
||||
|
||||
fn special_math() {
|
||||
let x = f32x4::from_array([1.0, 1.0, 1.0, 1.0]);
|
||||
let z = f32x4::from_array([0.0, 0.0, 0.0, 0.0]);
|
||||
|
||||
unsafe {
|
||||
let r = simd_fcos(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fexp(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fexp2(z);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_fsqrt(x);
|
||||
assert_approx_eq!(x, r);
|
||||
|
||||
let r = simd_flog(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_flog2(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_flog10(x);
|
||||
assert_approx_eq!(z, r);
|
||||
|
||||
let r = simd_fsin(z);
|
||||
assert_approx_eq!(z, r);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { simple_math() };
|
||||
simple_math();
|
||||
special_math();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
//@ run-pass
|
||||
//@ ignore-emscripten
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_f{min,max} intrinsics produce the correct results.
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
|
|
@ -12,7 +13,7 @@ use minisimd::*;
|
|||
|
||||
use std::intrinsics::simd::*;
|
||||
|
||||
fn main() {
|
||||
const fn minmax() {
|
||||
let x = f32x4::from_array([1.0, 2.0, 3.0, 4.0]);
|
||||
let y = f32x4::from_array([2.0, 1.0, 4.0, 3.0]);
|
||||
|
||||
|
|
@ -47,3 +48,8 @@ fn main() {
|
|||
assert_eq!(maxn, y);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { minmax() };
|
||||
minmax();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
//@ run-pass
|
||||
//@ ignore-backends: gcc
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -20,7 +21,7 @@ macro_rules! all_eq {
|
|||
|
||||
use std::intrinsics::simd::*;
|
||||
|
||||
fn main() {
|
||||
const fn arithmetic() {
|
||||
let x1 = i32x4::from_array([1, 2, 3, 4]);
|
||||
let y1 = U32::<4>::from_array([1, 2, 3, 4]);
|
||||
let z1 = f32x4::from_array([1.0, 2.0, 3.0, 4.0]);
|
||||
|
|
@ -224,3 +225,8 @@ fn main() {
|
|||
all_eq!(simd_cttz(y1), U32::<4>::from_array([0, 1, 0, 2]));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { arithmetic() };
|
||||
arithmetic();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
//@ run-pass
|
||||
//@ ignore-emscripten
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -12,7 +13,7 @@ use std::intrinsics::simd::{simd_saturating_add, simd_saturating_sub};
|
|||
|
||||
type I32<const N: usize> = Simd<i32, N>;
|
||||
|
||||
fn main() {
|
||||
const fn saturating() {
|
||||
// unsigned
|
||||
{
|
||||
const M: u32 = u32::MAX;
|
||||
|
|
@ -84,3 +85,8 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { saturating() };
|
||||
saturating();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
//@ run-pass
|
||||
//@ ignore-backends: gcc
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -11,7 +12,7 @@ use std::intrinsics::simd::simd_as;
|
|||
|
||||
type V<T> = Simd<T, 2>;
|
||||
|
||||
fn main() {
|
||||
const fn as_simd() {
|
||||
unsafe {
|
||||
let u: V::<u32> = Simd([u32::MIN, u32::MAX]);
|
||||
let i: V<i16> = simd_as(u);
|
||||
|
|
@ -47,3 +48,8 @@ fn main() {
|
|||
assert_eq!(u[1], f[1] as usize);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { as_simd() };
|
||||
as_simd();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +1,31 @@
|
|||
//@ run-pass
|
||||
#![allow(non_camel_case_types)]
|
||||
//@ ignore-emscripten
|
||||
//@ ignore-endian-big behavior of simd_bitmask is endian-specific
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_bitmask intrinsic produces correct results.
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
use minisimd::*;
|
||||
|
||||
use std::intrinsics::simd::simd_bitmask;
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct u32x4(pub [u32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct u8x4(pub [u8; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
struct Tx4<T>(pub [T; 4]);
|
||||
|
||||
fn main() {
|
||||
let z = u32x4([0, 0, 0, 0]);
|
||||
const fn bitmask() {
|
||||
let z = u32x4::from_array([0, 0, 0, 0]);
|
||||
let ez = 0_u8;
|
||||
|
||||
let o = u32x4([!0, !0, !0, !0]);
|
||||
let o = u32x4::from_array([!0, !0, !0, !0]);
|
||||
let eo = 0b_1111_u8;
|
||||
|
||||
let m0 = u32x4([!0, 0, !0, 0]);
|
||||
let m0 = u32x4::from_array([!0, 0, !0, 0]);
|
||||
let e0 = 0b_0000_0101_u8;
|
||||
|
||||
// Check that the MSB is extracted:
|
||||
let m = u8x4([0b_1000_0000, 0b_0100_0001, 0b_1100_0001, 0b_1111_1111]);
|
||||
let e = 0b_1101;
|
||||
|
||||
// Check usize / isize
|
||||
let msize: Tx4<usize> = Tx4([usize::MAX, 0, usize::MAX, usize::MAX]);
|
||||
let msize = usizex4::from_array([usize::MAX, 0, usize::MAX, usize::MAX]);
|
||||
|
||||
unsafe {
|
||||
let r: u8 = simd_bitmask(z);
|
||||
|
|
@ -47,10 +37,12 @@ fn main() {
|
|||
let r: u8 = simd_bitmask(m0);
|
||||
assert_eq!(r, e0);
|
||||
|
||||
let r: u8 = simd_bitmask(m);
|
||||
assert_eq!(r, e);
|
||||
|
||||
let r: u8 = simd_bitmask(msize);
|
||||
assert_eq!(r, e);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { bitmask() };
|
||||
bitmask();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
//@ run-pass
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![allow(non_camel_case_types)]
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -8,9 +8,14 @@ use minisimd::*;
|
|||
|
||||
use std::intrinsics::simd::simd_bswap;
|
||||
|
||||
fn main() {
|
||||
const fn bswap() {
|
||||
unsafe {
|
||||
assert_eq!(simd_bswap(i8x4::from_array([0, 1, 2, 3])).into_array(), [0, 1, 2, 3]);
|
||||
assert_eq!(simd_bswap(u8x4::from_array([0, 1, 2, 3])).into_array(), [0, 1, 2, 3]);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { bswap() };
|
||||
bswap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//@ run-pass
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -12,7 +13,7 @@ use std::cmp::{max, min};
|
|||
|
||||
type V<T> = Simd<T, 2>;
|
||||
|
||||
fn main() {
|
||||
const fn cast() {
|
||||
unsafe {
|
||||
let u: V::<u32> = Simd([i16::MIN as u32, i16::MAX as u32]);
|
||||
let i: V<i16> = simd_cast(u);
|
||||
|
|
@ -56,3 +57,8 @@ fn main() {
|
|||
assert_eq!(u[1], f[1] as usize);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { cast() };
|
||||
cast();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//@ run-pass
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -9,17 +10,16 @@ use std::intrinsics::simd::simd_cast;
|
|||
|
||||
type V<T> = Simd<T, 4>;
|
||||
|
||||
fn main() {
|
||||
const fn cast_ptr_width() {
|
||||
let u: V::<usize> = Simd([0, 1, 2, 3]);
|
||||
let uu32: V<u32> = unsafe { simd_cast(u) };
|
||||
let ui64: V<i64> = unsafe { simd_cast(u) };
|
||||
|
||||
for (u, (uu32, ui64)) in u
|
||||
.as_array()
|
||||
.iter()
|
||||
.zip(uu32.as_array().iter().zip(ui64.as_array().iter()))
|
||||
{
|
||||
assert_eq!(*u as u32, *uu32);
|
||||
assert_eq!(*u as i64, *ui64);
|
||||
}
|
||||
assert_eq!(uu32, V::<u32>::from_array([0, 1, 2, 3]));
|
||||
assert_eq!(ui64, V::<i64>::from_array([0, 1, 2, 3]));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { cast_ptr_width() };
|
||||
cast_ptr_width();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
//@ run-pass
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, core_intrinsics, macro_metavar_expr_concat)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(
|
||||
repr_simd,
|
||||
core_intrinsics,
|
||||
const_trait_impl,
|
||||
const_cmp,
|
||||
const_index,
|
||||
macro_metavar_expr_concat
|
||||
)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -25,27 +32,26 @@ macro_rules! cmp {
|
|||
macro_rules! tests {
|
||||
($($lhs: ident, $rhs: ident;)*) => {{
|
||||
$(
|
||||
(|| {
|
||||
cmp!(eq($lhs, $rhs));
|
||||
cmp!(ne($lhs, $rhs));
|
||||
cmp!(eq($lhs, $rhs));
|
||||
cmp!(ne($lhs, $rhs));
|
||||
|
||||
// test both directions
|
||||
cmp!(lt($lhs, $rhs));
|
||||
cmp!(lt($rhs, $lhs));
|
||||
// test both directions
|
||||
cmp!(lt($lhs, $rhs));
|
||||
cmp!(lt($rhs, $lhs));
|
||||
|
||||
cmp!(le($lhs, $rhs));
|
||||
cmp!(le($rhs, $lhs));
|
||||
cmp!(le($lhs, $rhs));
|
||||
cmp!(le($rhs, $lhs));
|
||||
|
||||
cmp!(gt($lhs, $rhs));
|
||||
cmp!(gt($rhs, $lhs));
|
||||
cmp!(gt($lhs, $rhs));
|
||||
cmp!(gt($rhs, $lhs));
|
||||
|
||||
cmp!(ge($lhs, $rhs));
|
||||
cmp!(ge($rhs, $lhs));
|
||||
})();
|
||||
)*
|
||||
cmp!(ge($lhs, $rhs));
|
||||
cmp!(ge($rhs, $lhs));
|
||||
)*
|
||||
}}
|
||||
}
|
||||
fn main() {
|
||||
|
||||
const fn compare() {
|
||||
// 13 vs. -100 tests that we get signed vs. unsigned comparisons
|
||||
// correct (i32: 13 > -100, u32: 13 < -100). let i1 = i32x4(10, -11, 12, 13);
|
||||
let i1 = i32x4::from_array([10, -11, 12, 13]);
|
||||
|
|
@ -89,3 +95,8 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { compare() };
|
||||
compare();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//@ run-pass
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, intrinsics, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -20,11 +21,59 @@ macro_rules! all_eq {
|
|||
// type inference works better with the concrete type on the
|
||||
// left, but humans work better with the expected on the
|
||||
// right.
|
||||
assert!(b == a, "{:?} != {:?}", a, b);
|
||||
assert!(b == a, concat!(stringify!($a), "!=", stringify!($b)));
|
||||
}};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
fn extract_insert_dyn() {
|
||||
let x2 = i32x2::from_array([20, 21]);
|
||||
let x4 = i32x4::from_array([40, 41, 42, 43]);
|
||||
let x8 = i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 87]);
|
||||
|
||||
unsafe {
|
||||
all_eq!(simd_insert_dyn(x2, 0, 100), i32x2::from_array([100, 21]));
|
||||
all_eq!(simd_insert_dyn(x2, 1, 100), i32x2::from_array([20, 100]));
|
||||
|
||||
all_eq!(simd_insert_dyn(x4, 0, 100), i32x4::from_array([100, 41, 42, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 1, 100), i32x4::from_array([40, 100, 42, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 2, 100), i32x4::from_array([40, 41, 100, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 3, 100), i32x4::from_array([40, 41, 42, 100]));
|
||||
|
||||
all_eq!(simd_insert_dyn(x8, 0, 100), i32x8::from_array([100, 81, 82, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 1, 100), i32x8::from_array([80, 100, 82, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 2, 100), i32x8::from_array([80, 81, 100, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 3, 100), i32x8::from_array([80, 81, 82, 100, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 4, 100), i32x8::from_array([80, 81, 82, 83, 100, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 5, 100), i32x8::from_array([80, 81, 82, 83, 84, 100, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 6, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 100, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 7, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 100]));
|
||||
|
||||
all_eq!(simd_extract_dyn(x2, 0), 20);
|
||||
all_eq!(simd_extract_dyn(x2, 1), 21);
|
||||
|
||||
all_eq!(simd_extract_dyn(x4, 0), 40);
|
||||
all_eq!(simd_extract_dyn(x4, 1), 41);
|
||||
all_eq!(simd_extract_dyn(x4, 2), 42);
|
||||
all_eq!(simd_extract_dyn(x4, 3), 43);
|
||||
|
||||
all_eq!(simd_extract_dyn(x8, 0), 80);
|
||||
all_eq!(simd_extract_dyn(x8, 1), 81);
|
||||
all_eq!(simd_extract_dyn(x8, 2), 82);
|
||||
all_eq!(simd_extract_dyn(x8, 3), 83);
|
||||
all_eq!(simd_extract_dyn(x8, 4), 84);
|
||||
all_eq!(simd_extract_dyn(x8, 5), 85);
|
||||
all_eq!(simd_extract_dyn(x8, 6), 86);
|
||||
all_eq!(simd_extract_dyn(x8, 7), 87);
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! simd_shuffle {
|
||||
($a:expr, $b:expr, $swizzle:expr) => {
|
||||
simd_shuffle($a, $b, const { SimdShuffleIdx($swizzle) })
|
||||
};
|
||||
}
|
||||
|
||||
const fn swizzle() {
|
||||
let x2 = i32x2::from_array([20, 21]);
|
||||
let x4 = i32x4::from_array([40, 41, 42, 43]);
|
||||
let x8 = i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 87]);
|
||||
|
|
@ -63,83 +112,36 @@ fn main() {
|
|||
all_eq!(simd_extract(x8, 6), 86);
|
||||
all_eq!(simd_extract(x8, 7), 87);
|
||||
}
|
||||
unsafe {
|
||||
all_eq!(simd_insert_dyn(x2, 0, 100), i32x2::from_array([100, 21]));
|
||||
all_eq!(simd_insert_dyn(x2, 1, 100), i32x2::from_array([20, 100]));
|
||||
|
||||
all_eq!(simd_insert_dyn(x4, 0, 100), i32x4::from_array([100, 41, 42, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 1, 100), i32x4::from_array([40, 100, 42, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 2, 100), i32x4::from_array([40, 41, 100, 43]));
|
||||
all_eq!(simd_insert_dyn(x4, 3, 100), i32x4::from_array([40, 41, 42, 100]));
|
||||
|
||||
all_eq!(simd_insert_dyn(x8, 0, 100), i32x8::from_array([100, 81, 82, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 1, 100), i32x8::from_array([80, 100, 82, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 2, 100), i32x8::from_array([80, 81, 100, 83, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 3, 100), i32x8::from_array([80, 81, 82, 100, 84, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 4, 100), i32x8::from_array([80, 81, 82, 83, 100, 85, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 5, 100), i32x8::from_array([80, 81, 82, 83, 84, 100, 86, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 6, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 100, 87]));
|
||||
all_eq!(simd_insert_dyn(x8, 7, 100), i32x8::from_array([80, 81, 82, 83, 84, 85, 86, 100]));
|
||||
|
||||
all_eq!(simd_extract_dyn(x2, 0), 20);
|
||||
all_eq!(simd_extract_dyn(x2, 1), 21);
|
||||
|
||||
all_eq!(simd_extract_dyn(x4, 0), 40);
|
||||
all_eq!(simd_extract_dyn(x4, 1), 41);
|
||||
all_eq!(simd_extract_dyn(x4, 2), 42);
|
||||
all_eq!(simd_extract_dyn(x4, 3), 43);
|
||||
|
||||
all_eq!(simd_extract_dyn(x8, 0), 80);
|
||||
all_eq!(simd_extract_dyn(x8, 1), 81);
|
||||
all_eq!(simd_extract_dyn(x8, 2), 82);
|
||||
all_eq!(simd_extract_dyn(x8, 3), 83);
|
||||
all_eq!(simd_extract_dyn(x8, 4), 84);
|
||||
all_eq!(simd_extract_dyn(x8, 5), 85);
|
||||
all_eq!(simd_extract_dyn(x8, 6), 86);
|
||||
all_eq!(simd_extract_dyn(x8, 7), 87);
|
||||
}
|
||||
|
||||
let y2 = i32x2::from_array([120, 121]);
|
||||
let y4 = i32x4::from_array([140, 141, 142, 143]);
|
||||
let y8 = i32x8::from_array([180, 181, 182, 183, 184, 185, 186, 187]);
|
||||
unsafe {
|
||||
all_eq!(simd_shuffle!(x2, y2, [3u32, 0]), i32x2::from_array([121, 20]));
|
||||
all_eq!(simd_shuffle!(x2, y2, [3u32, 0, 1, 2]), i32x4::from_array([121, 20, 21, 120]));
|
||||
all_eq!(
|
||||
simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0]) }),
|
||||
i32x2::from_array([121, 20])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2]) }),
|
||||
i32x4::from_array([121, 20, 21, 120])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x2, y2, const { SimdShuffleIdx([3u32, 0, 1, 2, 1, 2, 3, 0]) }),
|
||||
simd_shuffle!(x2, y2, [3u32, 0, 1, 2, 1, 2, 3, 0]),
|
||||
i32x8::from_array([121, 20, 21, 120, 21, 120, 121, 20])
|
||||
);
|
||||
|
||||
all_eq!(simd_shuffle!(x4, y4, [7u32, 2]), i32x2::from_array([143, 42]));
|
||||
all_eq!(simd_shuffle!(x4, y4, [7u32, 2, 5, 0]), i32x4::from_array([143, 42, 141, 40]));
|
||||
all_eq!(
|
||||
simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2]) }),
|
||||
i32x2::from_array([143, 42])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0]) }),
|
||||
i32x4::from_array([143, 42, 141, 40])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x4, y4, const { SimdShuffleIdx([7u32, 2, 5, 0, 3, 6, 4, 1]) }),
|
||||
simd_shuffle!(x4, y4, [7u32, 2, 5, 0, 3, 6, 4, 1]),
|
||||
i32x8::from_array([143, 42, 141, 40, 43, 142, 140, 41])
|
||||
);
|
||||
|
||||
all_eq!(simd_shuffle!(x8, y8, [11u32, 5]), i32x2::from_array([183, 85]));
|
||||
all_eq!(simd_shuffle!(x8, y8, [11u32, 5, 15, 0]), i32x4::from_array([183, 85, 187, 80]));
|
||||
all_eq!(
|
||||
simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5]) }),
|
||||
i32x2::from_array([183, 85])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0]) }),
|
||||
i32x4::from_array([183, 85, 187, 80])
|
||||
);
|
||||
all_eq!(
|
||||
simd_shuffle(x8, y8, const { SimdShuffleIdx([11u32, 5, 15, 0, 3, 8, 12, 1]) }),
|
||||
simd_shuffle!(x8, y8, [11u32, 5, 15, 0, 3, 8, 12, 1]),
|
||||
i32x8::from_array([183, 85, 187, 80, 83, 180, 184, 81])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
extract_insert_dyn();
|
||||
const { swizzle() };
|
||||
swizzle();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
//@ run-pass
|
||||
//@ ignore-emscripten
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_{gather,scatter} intrinsics produce the correct results.
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
|
|
@ -14,48 +15,11 @@ use std::intrinsics::simd::{simd_gather, simd_scatter};
|
|||
|
||||
type x4<T> = Simd<T, 4>;
|
||||
|
||||
fn main() {
|
||||
let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
|
||||
|
||||
let default = x4::from_array([-3_f32, -3., -3., -3.]);
|
||||
let s_strided = x4::from_array([0_f32, 2., -3., 6.]);
|
||||
fn gather_scatter_of_ptrs() {
|
||||
// test modifying array of *const f32
|
||||
let x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
|
||||
let mask = x4::from_array([-1_i32, -1, 0, -1]);
|
||||
|
||||
// reading from *const
|
||||
unsafe {
|
||||
let pointer = x.as_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
assert_eq!(r_strided, s_strided);
|
||||
}
|
||||
|
||||
// reading from *mut
|
||||
unsafe {
|
||||
let pointer = x.as_mut_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
assert_eq!(r_strided, s_strided);
|
||||
}
|
||||
|
||||
// writing to *mut
|
||||
unsafe {
|
||||
let pointer = x.as_mut_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
|
||||
let values = x4::from_array([42_f32, 43_f32, 44_f32, 45_f32]);
|
||||
simd_scatter(values, pointers, mask);
|
||||
|
||||
assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]);
|
||||
}
|
||||
|
||||
// test modifying array of *const f32
|
||||
let mut y = [
|
||||
&x[0] as *const f32,
|
||||
&x[1] as *const f32,
|
||||
|
|
@ -73,8 +37,7 @@ fn main() {
|
|||
// reading from *const
|
||||
unsafe {
|
||||
let pointer = y.as_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
|
|
@ -84,8 +47,7 @@ fn main() {
|
|||
// reading from *mut
|
||||
unsafe {
|
||||
let pointer = y.as_mut_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
|
|
@ -95,8 +57,7 @@ fn main() {
|
|||
// writing to *mut
|
||||
unsafe {
|
||||
let pointer = y.as_mut_ptr();
|
||||
let pointers =
|
||||
x4::from_array(std::array::from_fn(|i| pointer.add(i * 2)));
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let values = x4::from_array([y[7], y[6], y[5], y[1]]);
|
||||
simd_scatter(values, pointers, mask);
|
||||
|
|
@ -114,3 +75,48 @@ fn main() {
|
|||
assert_eq!(y, s);
|
||||
}
|
||||
}
|
||||
|
||||
const fn gather_scatter() {
|
||||
let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
|
||||
|
||||
let default = x4::from_array([-3_f32, -3., -3., -3.]);
|
||||
let s_strided = x4::from_array([0_f32, 2., -3., 6.]);
|
||||
let mask = x4::from_array([-1_i32, -1, 0, -1]);
|
||||
|
||||
// reading from *const
|
||||
unsafe {
|
||||
let pointer = x.as_ptr();
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
assert_eq!(r_strided, s_strided);
|
||||
}
|
||||
|
||||
// reading from *mut
|
||||
unsafe {
|
||||
let pointer = x.as_mut_ptr();
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let r_strided = simd_gather(default, pointers, mask);
|
||||
|
||||
assert_eq!(r_strided, s_strided);
|
||||
}
|
||||
|
||||
// writing to *mut
|
||||
unsafe {
|
||||
let pointer = x.as_mut_ptr();
|
||||
let pointers = x4::from_array([pointer, pointer.add(2), pointer.add(4), pointer.add(6)]);
|
||||
|
||||
let values = x4::from_array([42_f32, 43_f32, 44_f32, 45_f32]);
|
||||
simd_scatter(values, pointers, mask);
|
||||
|
||||
assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { gather_scatter() };
|
||||
gather_scatter();
|
||||
gather_scatter_of_ptrs();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,46 @@
|
|||
//@ run-pass
|
||||
#![allow(non_camel_case_types)]
|
||||
//@ ignore-emscripten
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_reduce_{op} intrinsics produce the correct results.
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
use minisimd::*;
|
||||
|
||||
use std::intrinsics::simd::*;
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct i32x4(pub [i32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct u32x4(pub [u32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct f32x4(pub [f32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct b8x4(pub [i8; 4]);
|
||||
|
||||
fn main() {
|
||||
fn unordered() {
|
||||
unsafe {
|
||||
let x = i32x4([1, -2, 3, 4]);
|
||||
let x = i32x4::from_array([1, -2, 3, 4]);
|
||||
let r: i32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 6_i32);
|
||||
let r: i32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, -24_i32);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let x = u32x4::from_array([1, 2, 3, 4]);
|
||||
let r: u32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 10_u32);
|
||||
let r: u32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, 24_u32);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let x = f32x4::from_array([1., -2., 3., 4.]);
|
||||
let r: f32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 6_f32);
|
||||
let r: f32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, -24_f32);
|
||||
}
|
||||
}
|
||||
|
||||
const fn ordered() {
|
||||
unsafe {
|
||||
let x = i32x4::from_array([1, -2, 3, 4]);
|
||||
let r: i32 = simd_reduce_add_ordered(x, -1);
|
||||
assert_eq!(r, 5_i32);
|
||||
let r: i32 = simd_reduce_mul_ordered(x, -1);
|
||||
|
|
@ -40,7 +51,7 @@ fn main() {
|
|||
let r: i32 = simd_reduce_max(x);
|
||||
assert_eq!(r, 4_i32);
|
||||
|
||||
let x = i32x4([-1, -1, -1, -1]);
|
||||
let x = i32x4::from_array([-1, -1, -1, -1]);
|
||||
let r: i32 = simd_reduce_and(x);
|
||||
assert_eq!(r, -1_i32);
|
||||
let r: i32 = simd_reduce_or(x);
|
||||
|
|
@ -48,7 +59,7 @@ fn main() {
|
|||
let r: i32 = simd_reduce_xor(x);
|
||||
assert_eq!(r, 0_i32);
|
||||
|
||||
let x = i32x4([-1, -1, 0, -1]);
|
||||
let x = i32x4::from_array([-1, -1, 0, -1]);
|
||||
let r: i32 = simd_reduce_and(x);
|
||||
assert_eq!(r, 0_i32);
|
||||
let r: i32 = simd_reduce_or(x);
|
||||
|
|
@ -58,11 +69,7 @@ fn main() {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
let x = u32x4([1, 2, 3, 4]);
|
||||
let r: u32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 10_u32);
|
||||
let r: u32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, 24_u32);
|
||||
let x = u32x4::from_array([1, 2, 3, 4]);
|
||||
let r: u32 = simd_reduce_add_ordered(x, 1);
|
||||
assert_eq!(r, 11_u32);
|
||||
let r: u32 = simd_reduce_mul_ordered(x, 2);
|
||||
|
|
@ -74,7 +81,7 @@ fn main() {
|
|||
assert_eq!(r, 4_u32);
|
||||
|
||||
let t = u32::MAX;
|
||||
let x = u32x4([t, t, t, t]);
|
||||
let x = u32x4::from_array([t, t, t, t]);
|
||||
let r: u32 = simd_reduce_and(x);
|
||||
assert_eq!(r, t);
|
||||
let r: u32 = simd_reduce_or(x);
|
||||
|
|
@ -82,7 +89,7 @@ fn main() {
|
|||
let r: u32 = simd_reduce_xor(x);
|
||||
assert_eq!(r, 0_u32);
|
||||
|
||||
let x = u32x4([t, t, 0, t]);
|
||||
let x = u32x4::from_array([t, t, 0, t]);
|
||||
let r: u32 = simd_reduce_and(x);
|
||||
assert_eq!(r, 0_u32);
|
||||
let r: u32 = simd_reduce_or(x);
|
||||
|
|
@ -92,11 +99,7 @@ fn main() {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
let x = f32x4([1., -2., 3., 4.]);
|
||||
let r: f32 = simd_reduce_add_unordered(x);
|
||||
assert_eq!(r, 6_f32);
|
||||
let r: f32 = simd_reduce_mul_unordered(x);
|
||||
assert_eq!(r, -24_f32);
|
||||
let x = f32x4::from_array([1., -2., 3., 4.]);
|
||||
let r: f32 = simd_reduce_add_ordered(x, 0.);
|
||||
assert_eq!(r, 6_f32);
|
||||
let r: f32 = simd_reduce_mul_ordered(x, 1.);
|
||||
|
|
@ -113,22 +116,28 @@ fn main() {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
let x = b8x4([!0, !0, !0, !0]);
|
||||
let x = i8x4::from_array([!0, !0, !0, !0]);
|
||||
let r: bool = simd_reduce_all(x);
|
||||
assert_eq!(r, true);
|
||||
let r: bool = simd_reduce_any(x);
|
||||
assert_eq!(r, true);
|
||||
|
||||
let x = b8x4([!0, !0, 0, !0]);
|
||||
let x = i8x4::from_array([!0, !0, 0, !0]);
|
||||
let r: bool = simd_reduce_all(x);
|
||||
assert_eq!(r, false);
|
||||
let r: bool = simd_reduce_any(x);
|
||||
assert_eq!(r, true);
|
||||
|
||||
let x = b8x4([0, 0, 0, 0]);
|
||||
let x = i8x4::from_array([0, 0, 0, 0]);
|
||||
let r: bool = simd_reduce_all(x);
|
||||
assert_eq!(r, false);
|
||||
let r: bool = simd_reduce_any(x);
|
||||
assert_eq!(r, false);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unordered();
|
||||
const { ordered() };
|
||||
ordered();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@
|
|||
#![allow(non_camel_case_types)]
|
||||
//@ ignore-emscripten
|
||||
//@ ignore-endian-big behavior of simd_select_bitmask is endian-specific
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
// Test that the simd_select intrinsics produces correct results.
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -14,7 +15,7 @@ use std::intrinsics::simd::{simd_select, simd_select_bitmask};
|
|||
|
||||
type b8x4 = i8x4;
|
||||
|
||||
fn main() {
|
||||
const fn select() {
|
||||
let m0 = b8x4::from_array([!0, !0, !0, !0]);
|
||||
let m1 = b8x4::from_array([0, 0, 0, 0]);
|
||||
let m2 = b8x4::from_array([!0, !0, 0, 0]);
|
||||
|
|
@ -173,3 +174,8 @@ fn main() {
|
|||
assert_eq!(r, e);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { select() };
|
||||
select();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//@ ignore-backends: gcc
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
//@ run-pass
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -8,7 +9,7 @@ use minisimd::*;
|
|||
|
||||
use std::intrinsics::simd::{SimdAlign, simd_masked_load, simd_masked_store};
|
||||
|
||||
fn main() {
|
||||
const fn masked_load_store() {
|
||||
unsafe {
|
||||
let a = Simd::<u8, 4>([0, 1, 2, 3]);
|
||||
let b_src = [4u8, 5, 6, 7];
|
||||
|
|
@ -37,3 +38,8 @@ fn main() {
|
|||
assert_eq!(&output, &[0, 1, 9, 6, u8::MAX]);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { masked_load_store() };
|
||||
masked_load_store();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
// This should be merged into `simd-bitmask` once that's fixed.
|
||||
//@ ignore-endian-big
|
||||
//@ ignore-backends: gcc
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -12,15 +13,10 @@ use minisimd::*;
|
|||
|
||||
use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask};
|
||||
|
||||
fn main() {
|
||||
const fn bitmask() {
|
||||
// Non-power-of-2 multi-byte mask.
|
||||
#[allow(non_camel_case_types)]
|
||||
type i32x10 = PackedSimd<i32, 10>;
|
||||
impl i32x10 {
|
||||
fn splat(x: i32) -> Self {
|
||||
Self([x; 10])
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
let mask = i32x10::from_array([!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]);
|
||||
let mask_bits = if cfg!(target_endian = "little") { 0b0101001011 } else { 0b1101001010 };
|
||||
|
|
@ -49,11 +45,6 @@ fn main() {
|
|||
// Test for a mask where the next multiple of 8 is not a power of two.
|
||||
#[allow(non_camel_case_types)]
|
||||
type i32x20 = PackedSimd<i32, 20>;
|
||||
impl i32x20 {
|
||||
fn splat(x: i32) -> Self {
|
||||
Self([x; 20])
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
let mask = i32x20::from_array([
|
||||
!0, !0, 0, !0, 0,
|
||||
|
|
@ -91,3 +82,8 @@ fn main() {
|
|||
assert_eq!(selected2, mask);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { bitmask() };
|
||||
bitmask();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//@run-pass
|
||||
#![feature(repr_simd, core_intrinsics)]
|
||||
//@ compile-flags: --cfg minisimd_const
|
||||
#![feature(repr_simd, core_intrinsics, const_trait_impl, const_cmp, const_index)]
|
||||
|
||||
#[path = "../../auxiliary/minisimd.rs"]
|
||||
mod minisimd;
|
||||
|
|
@ -7,7 +8,7 @@ use minisimd::*;
|
|||
|
||||
use std::intrinsics::simd::{simd_bitmask, simd_select_bitmask};
|
||||
|
||||
fn main() {
|
||||
const fn bitmask() {
|
||||
unsafe {
|
||||
let v = Simd::<i8, 4>([-1, 0, -1, 0]);
|
||||
let i: u8 = simd_bitmask(v);
|
||||
|
|
@ -68,3 +69,8 @@ fn main() {
|
|||
assert_eq!(r.into_array(), e);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { bitmask() };
|
||||
bitmask();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue