@@ -1284,7 +1284,50 @@ 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+ let is_nan = self . context . new_binary_op (
1313+ self . location ,
1314+ BinaryOp :: LogicalOr ,
1315+ self . cx . bool_type ,
1316+ // compare a value to itself to check whether it is NaN
1317+ self . context . new_comparison ( self . location , ComparisonOp :: NotEquals , lhs, lhs) ,
1318+ self . context . new_comparison ( self . location , ComparisonOp :: NotEquals , rhs, rhs) ,
1319+ ) ;
1320+
1321+ self . context . new_binary_op (
1322+ self . location ,
1323+ BinaryOp :: LogicalOr ,
1324+ self . cx . bool_type ,
1325+ is_nan,
1326+ cmp,
1327+ )
1328+ } else {
1329+ cmp
1330+ }
12881331 }
12891332
12901333 /* Miscellaneous instructions */
0 commit comments