@@ -1284,7 +1284,53 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
1284
1284
}
1285
1285
1286
1286
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 (
1325
+ self . location ,
1326
+ BinaryOp :: LogicalOr ,
1327
+ self . cx . bool_type ,
1328
+ is_nan,
1329
+ cmp,
1330
+ )
1331
+ } else {
1332
+ cmp
1333
+ }
1288
1334
}
1289
1335
1290
1336
/* Miscellaneous instructions */
0 commit comments