@@ -518,6 +518,13 @@ fn random_nan<S: Semantics>(rng: &mut StdRng) -> IeeeFloat<S> {
518518/// - logf32, logf64, log2f32, log2f64, log10f32, log10f64
519519/// - powf32, powf64
520520///
521+ /// # Return
522+ ///
523+ /// Returns `Some(output)` if the `intrinsic` results in a defined fixed `output` specified in the C standard
524+ /// (specifically, C23 annex F.10) when given `args` as arguments. Outputs that are unaffected by a relative error
525+ /// (such as INF and zero) are not handled here, they are assumed to be handled by the underlying
526+ /// implementation. Returns `None` if no specific value is guaranteed.
527+ ///
521528/// # Note
522529///
523530/// For `powf*` operations of the form:
@@ -532,12 +539,7 @@ fn random_nan<S: Semantics>(rng: &mut StdRng) -> IeeeFloat<S> {
532539/// This discrepancy exists because SNaN handling is not consistently defined across platforms,
533540/// and the C standard leaves behavior for SNaNs unspecified.
534541///
535- /// # Return
536- ///
537- /// Returns `Some(output)` if the `intrinsic` results in a defined fixed `output` specified in the C standard
538- /// (specifically, C23 annex F.10) when given `args` as arguments. Outputs that are unaffected by a relative error
539- /// (such as INF and zero) are not handled here, they are assumed to be handled by the underlying
540- /// implementation. Returns `None` if no specific value is guaranteed.
542+ /// Miri chooses to adhere to both implementations and returns either one of them non-deterministically.
541543fn fixed_float_value < ' tcx , S : Semantics > (
542544 ecx : & mut MiriInterpCx < ' tcx > ,
543545 intrinsic_name : & str ,
@@ -551,12 +553,15 @@ fn fixed_float_value<'tcx, S: Semantics>(
551553 // e^0 = 1
552554 ( "expf32" | "expf64" | "exp2f32" | "exp2f64" , [ input] ) if input. is_zero ( ) => one,
553555
554- // 1^y = 1 for any y, even a NaN
555- ( "powf32" | "powf64" , [ base, _] ) if * base == one => one,
556-
557556 // (-1)^(±INF) = 1
558557 ( "powf32" | "powf64" , [ base, exp] ) if * base == -one && exp. is_infinite ( ) => one,
559558
559+ // 1^y = 1 for any y, even a NaN, *but* not a SNaN
560+ ( "powf32" | "powf64" , [ base, exp] ) if * base == one => {
561+ let rng = ecx. machine . rng . get_mut ( ) ;
562+ // Handle both the musl and glibc cases non-deterministically.
563+ if !exp. is_signaling ( ) || rng. random ( ) { one } else { random_nan ( rng) }
564+ }
560565 // x^(±0) = 1 for any x, even a NaN, *but* not a SNaN
561566 ( "powf32" | "powf64" , [ base, exp] ) if exp. is_zero ( ) => {
562567 // Handle both the musl and glibc cases non-deterministically.
0 commit comments