@@ -506,6 +506,13 @@ fn random_nan<S: Semantics>(rng: &mut StdRng) -> IeeeFloat<S> {
506506/// - logf32, logf64, log2f32, log2f64, log10f32, log10f64
507507/// - powf32, powf64
508508///
509+ /// # Return
510+ ///
511+ /// Returns `Some(output)` if the `intrinsic` results in a defined fixed `output` specified in the C standard
512+ /// (specifically, C23 annex F.10) when given `args` as arguments. Outputs that are unaffected by a relative error
513+ /// (such as INF and zero) are not handled here, they are assumed to be handled by the underlying
514+ /// implementation. Returns `None` if no specific value is guaranteed.
515+ ///
509516/// # Note
510517///
511518/// For `powf*` operations of the form:
@@ -520,12 +527,7 @@ fn random_nan<S: Semantics>(rng: &mut StdRng) -> IeeeFloat<S> {
520527/// This discrepancy exists because SNaN handling is not consistently defined across platforms,
521528/// and the C standard leaves behavior for SNaNs unspecified.
522529///
523- /// # Return
524- ///
525- /// Returns `Some(output)` if the `intrinsic` results in a defined fixed `output` specified in the C standard
526- /// (specifically, C23 annex F.10) when given `args` as arguments. Outputs that are unaffected by a relative error
527- /// (such as INF and zero) are not handled here, they are assumed to be handled by the underlying
528- /// implementation. Returns `None` if no specific value is guaranteed.
530+ /// Miri chooses to adhere to both implementations and returns either one of them non-deterministically.
529531fn fixed_float_value < ' tcx , S : Semantics > (
530532 ecx : & mut MiriInterpCx < ' tcx > ,
531533 intrinsic_name : & str ,
@@ -539,12 +541,15 @@ fn fixed_float_value<'tcx, S: Semantics>(
539541 // e^0 = 1
540542 ( "expf32" | "expf64" | "exp2f32" | "exp2f64" , [ input] ) if input. is_zero ( ) => one,
541543
542- // 1^y = 1 for any y, even a NaN
543- ( "powf32" | "powf64" , [ base, _] ) if * base == one => one,
544-
545544 // (-1)^(±INF) = 1
546545 ( "powf32" | "powf64" , [ base, exp] ) if * base == -one && exp. is_infinite ( ) => one,
547546
547+ // 1^y = 1 for any y, even a NaN, *but* not a SNaN
548+ ( "powf32" | "powf64" , [ base, exp] ) if * base == one => {
549+ let rng = ecx. machine . rng . get_mut ( ) ;
550+ // Handle both the musl and glibc cases non-deterministically.
551+ if !exp. is_signaling ( ) || rng. random ( ) { one } else { random_nan ( rng) }
552+ }
548553 // x^(±0) = 1 for any x, even a NaN, *but* not a SNaN
549554 ( "powf32" | "powf64" , [ base, exp] ) if exp. is_zero ( ) => {
550555 // Handle both the musl and glibc cases non-deterministically.
0 commit comments