@@ -1284,7 +1284,47 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
12841284 }
12851285
12861286 fn fcmp ( & mut self , op : RealPredicate , lhs : RValue < ' gcc > , rhs : RValue < ' gcc > ) -> RValue < ' gcc > {
1287- self . context . new_comparison ( self . location , op. to_gcc_comparison ( ) , lhs, rhs)
1287+ // LLVM has a concept of "unordered compares", where eg ULT returns true if either the two
1288+ // arguments are unordered (i.e. either is NaN), or the lhs is less than the rhs. GCC does
1289+ // not natively have this concept, so in some cases we must manually handle NaNs
1290+ let must_handle_nan = match op {
1291+ RealPredicate :: RealPredicateFalse => unreachable ! ( ) ,
1292+ RealPredicate :: RealOEQ => false ,
1293+ RealPredicate :: RealOGT => false ,
1294+ RealPredicate :: RealOGE => false ,
1295+ RealPredicate :: RealOLT => false ,
1296+ RealPredicate :: RealOLE => false ,
1297+ RealPredicate :: RealONE => false ,
1298+ RealPredicate :: RealORD => unreachable ! ( ) ,
1299+ RealPredicate :: RealUNO => unreachable ! ( ) ,
1300+ RealPredicate :: RealUEQ => false ,
1301+ RealPredicate :: RealUGT => true ,
1302+ RealPredicate :: RealUGE => true ,
1303+ RealPredicate :: RealULT => true ,
1304+ RealPredicate :: RealULE => true ,
1305+ RealPredicate :: RealUNE => false ,
1306+ RealPredicate :: RealPredicateTrue => unreachable ! ( ) ,
1307+ } ;
1308+
1309+ let cmp = self . context . new_comparison ( self . location , op. to_gcc_comparison ( ) , lhs, rhs) ;
1310+
1311+ if must_handle_nan {
1312+ // compare a value to itself to check whether it is NaN
1313+ let is_nan_lhs = self . fcmp ( RealPredicate :: RealONE , lhs, lhs) ;
1314+ let is_nan_rhs = self . fcmp ( RealPredicate :: RealONE , rhs, rhs) ;
1315+
1316+ let is_nan = self . context . new_binary_op (
1317+ self . location ,
1318+ BinaryOp :: LogicalOr ,
1319+ self . cx . bool_type ,
1320+ is_nan_lhs,
1321+ is_nan_rhs,
1322+ ) ;
1323+
1324+ self . context . new_binary_op ( self . location , BinaryOp :: LogicalOr , self . cx . bool_type , is_nan, cmp)
1325+ } else {
1326+ cmp
1327+ }
12881328 }
12891329
12901330 /* Miscellaneous instructions */
0 commit comments