Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
990 changes: 495 additions & 495 deletions fearless_simd/src/generated/avx2.rs

Large diffs are not rendered by default.

1,520 changes: 760 additions & 760 deletions fearless_simd/src/generated/avx512.rs

Large diffs are not rendered by default.

576 changes: 288 additions & 288 deletions fearless_simd/src/generated/fallback.rs

Large diffs are not rendered by default.

464 changes: 232 additions & 232 deletions fearless_simd/src/generated/neon.rs

Large diffs are not rendered by default.

842 changes: 419 additions & 423 deletions fearless_simd/src/generated/simd_trait.rs

Large diffs are not rendered by default.

858 changes: 513 additions & 345 deletions fearless_simd/src/generated/simd_types.rs

Large diffs are not rendered by default.

662 changes: 331 additions & 331 deletions fearless_simd/src/generated/sse2.rs

Large diffs are not rendered by default.

464 changes: 232 additions & 232 deletions fearless_simd/src/generated/sse4_2.rs

Large diffs are not rendered by default.

296 changes: 148 additions & 148 deletions fearless_simd/src/generated/wasm.rs

Large diffs are not rendered by default.

13 changes: 12 additions & 1 deletion fearless_simd_gen/src/mk_simd_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,18 @@ fn simd_vec_impl(ty: &VecType) -> TokenStream {
let Some(call_args) = sig.forwarding_call_args() else {
continue;
};
let trait_method = generic_op_name(method, ty);
// Integer min/max have no precision-related edge cases, so the precise
// variants deliberately forward to the regular backend operations.
let backend_method = if matches!(ty.scalar, ScalarType::Int | ScalarType::Unsigned) {
match method {
"min_precise" => "min",
"max_precise" => "max",
_ => method,
}
} else {
method
};
let trait_method = generic_op_name(backend_method, ty);
let method_sig = op
.vec_trait_method_sig()
.expect("base trait operation must have a vector method signature");
Expand Down
93 changes: 44 additions & 49 deletions fearless_simd_gen/src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,44 @@ const BASE_OPS: &[Op] = &[
];

const COMMON_BASE_OPS: &[Op] = &[
Op::new(
"max",
OpKind::BaseTraitMethod,
OpSig::Binary,
"Return the element-wise maximum of two vectors.\n\n\
For floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\n\
If one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one.",
),
Op::new(
"min",
OpKind::BaseTraitMethod,
OpSig::Binary,
"Return the element-wise minimum of two vectors.\n\n\
For floating-point vectors, if either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\n\
If one floating-point operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one.",
),
Op::new(
"max_precise",
OpKind::BaseTraitMethod,
OpSig::Binary,
"Return the element-wise maximum of two vectors.\n\n\
For integer vectors, this operation is the same as `max`.\n\n\
For floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\n\
If one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n\
If a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\n\
Signaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them.",
),
Op::new(
"min_precise",
OpKind::BaseTraitMethod,
OpSig::Binary,
"Return the element-wise minimum of two vectors.\n\n\
For integer vectors, this operation is the same as `min`.\n\n\
For floating-point vectors, if one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\n\
If one floating-point operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n\
If a floating-point operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\n\
Signaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them.",
),
Op::new(
"simd_eq",
OpKind::BaseTraitMethod,
Expand Down Expand Up @@ -761,42 +799,6 @@ const FLOAT_OPS: &[Op] = &[
"Return a vector with the magnitude of `{arg0}` and the sign of `{arg1}` for each element.\n\n\
This operation copies the sign bit, so if an input element is NaN, the output element will be a NaN with the same payload and a copied sign bit.",
),
Op::new(
"max",
OpKind::VecTraitMethod,
OpSig::Binary,
"Return the element-wise maximum of two vectors.\n\n\
If either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `max_precise` for a version that returns the non-NaN operand if only one is NaN.\n\n\
If one operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one.",
),
Op::new(
"min",
OpKind::VecTraitMethod,
OpSig::Binary,
"Return the element-wise minimum of two vectors.\n\n\
If either operand is NaN, the result for that lane is implementation-defined-- it could be either the first or second operand. See `min_precise` for a version that returns the non-NaN operand if only one is NaN.\n\n\
If one operand is positive zero and the other is negative zero, the result is also implementation-defined, and it could be either one.",
),
Op::new(
"max_precise",
OpKind::VecTraitMethod,
OpSig::Binary,
"Return the element-wise maximum of two vectors.\n\n\
If one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\n\
If one operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n\
If an operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\n\
Signaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them.",
),
Op::new(
"min_precise",
OpKind::VecTraitMethod,
OpSig::Binary,
"Return the element-wise minimum of two vectors.\n\n\
If one operand is a quiet NaN and the other is not, this operation will choose the non-NaN operand.\n\n\
If one operand is positive zero and the other is negative zero, the result is implementation-defined, and it could be either one.\n\n\
If an operand is a *signaling* NaN, the result is not just implementation-defined, but fully non-deterministic: it may be either NaN or the non-NaN operand.\n\
Signaling NaN values are not produced by floating-point math operations, only from manual initialization with specific bit patterns. You probably don't need to worry about them.",
),
Op::new(
"mul_add",
OpKind::VecTraitMethod,
Expand Down Expand Up @@ -935,18 +937,6 @@ const INT_OPS: &[Op] = &[
"Select elements from {arg1} and {arg2} based on the mask operand {arg0}.\n\n\
This operation's behavior is unspecified if {arg0} was constructed from signed integer lanes that are neither all-zeroes (integer value 0) nor all-ones (integer value -1). See the [`Select`] trait's documentation for more information.",
),
Op::new(
"min",
OpKind::VecTraitMethod,
OpSig::Binary,
"Return the element-wise minimum of two vectors.",
),
Op::new(
"max",
OpKind::VecTraitMethod,
OpSig::Binary,
"Return the element-wise maximum of two vectors.",
),
];

// Long blurb shared between all the mask reduction operations. Needs to be a macro because consts don't work in the
Expand Down Expand Up @@ -1184,7 +1174,12 @@ pub(crate) fn ops_for_type(ty: &VecType) -> Vec<Op> {
ScalarType::Mask => false,
};
if common_ops_follow {
ops.extend_from_slice(COMMON_BASE_OPS);
// Integer precise min/max are exposed by `SimdBase`, but forward to
// the ordinary integer backend operations in `simd_vec_impl`.
ops.extend(COMMON_BASE_OPS.iter().copied().filter(|op| {
ty.scalar == ScalarType::Float
|| !matches!(op.method, "min_precise" | "max_precise")
}));
}
}

Expand Down
Loading