Sfoglia il codice sorgente

Merge pull request #5098 from laytan/fix-nan-comparisons

fix variable NaN comparisons
gingerBill 4 mesi fa
parent
commit
19fe75f020

+ 2 - 2
src/llvm_backend_expr.cpp

@@ -2944,7 +2944,7 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
 		case Token_GtEq:  pred = LLVMRealOGE; break;
 		case Token_Lt:    pred = LLVMRealOLT; break;
 		case Token_LtEq:  pred = LLVMRealOLE; break;
-		case Token_NotEq: pred = LLVMRealONE; break;
+		case Token_NotEq: pred = LLVMRealUNE; break;
 		}
 
 		if (is_type_different_to_arch_endianness(left.type)) {
@@ -2972,7 +2972,7 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
 			LLVMRealPredicate pred = {};
 			switch (op_kind) {
 			case Token_CmpEq: pred = LLVMRealOEQ; break;
-			case Token_NotEq: pred = LLVMRealONE; break;
+			case Token_NotEq: pred = LLVMRealUNE; break;
 			}
 			mask = LLVMBuildFCmp(p->builder, pred, left.value, right.value, "");
 		} else {

+ 1 - 1
src/llvm_backend_proc.cpp

@@ -1442,7 +1442,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn
 			LLVMRealPredicate pred = cast(LLVMRealPredicate)0;
 			switch (builtin_id) {
 			case BuiltinProc_simd_lanes_eq: pred = LLVMRealOEQ; break;
-			case BuiltinProc_simd_lanes_ne: pred = LLVMRealONE; break;
+			case BuiltinProc_simd_lanes_ne: pred = LLVMRealUNE; break;
 			case BuiltinProc_simd_lanes_lt: pred = LLVMRealOLT; break;
 			case BuiltinProc_simd_lanes_le: pred = LLVMRealOLE; break;
 			case BuiltinProc_simd_lanes_gt: pred = LLVMRealOGT; break;

+ 44 - 0
tests/internal/test_nan_constant_comparison.odin → tests/internal/test_nan_comparison.odin

@@ -45,3 +45,47 @@ compare_constant_nans_f64 :: proc(t: ^testing.T) {
 	testing.expect_value(t, NaN >  NaN,     false)
 	testing.expect_value(t, NaN >= NaN,     false)
 }
+
+@(test)
+compare_variable_nans_f32 :: proc(t: ^testing.T) {
+	NaN     := f32(0h7fc0_0000)
+	NaN2    := f32(0h7fc0_0001)
+	Inf     := f32(0h7F80_0000)
+	Neg_Inf := f32(0hFF80_0000)
+
+	testing.expect_value(t, NaN == NaN,     false)
+	testing.expect_value(t, NaN == NaN2,    false)
+	testing.expect_value(t, NaN != 0,       true)
+	testing.expect_value(t, NaN != 5,       true)
+	testing.expect_value(t, NaN != -5,      true)
+	testing.expect_value(t, NaN != NaN,     true)
+	testing.expect_value(t, NaN != NaN2,    true)
+	testing.expect_value(t, NaN != Inf,     true)
+	testing.expect_value(t, NaN != Neg_Inf, true)
+	testing.expect_value(t, NaN <  NaN,     false)
+	testing.expect_value(t, NaN <= NaN,     false)
+	testing.expect_value(t, NaN >  NaN,     false)
+	testing.expect_value(t, NaN >= NaN,     false)
+}
+
+@(test)
+compare_variable_nans_f64 :: proc(t: ^testing.T) {
+	NaN     := f64(0h7fff_0000_0000_0000)
+	NaN2    := f64(0h7fff_0000_0000_0001)
+	Inf     := f64(0h7FF0_0000_0000_0000)
+	Neg_Inf := f64(0hFFF0_0000_0000_0000)
+
+	testing.expect_value(t, NaN == NaN,     false)
+	testing.expect_value(t, NaN == NaN2,    false)
+	testing.expect_value(t, NaN != 0,       true)
+	testing.expect_value(t, NaN != 5,       true)
+	testing.expect_value(t, NaN != -5,      true)
+	testing.expect_value(t, NaN != NaN,     true)
+	testing.expect_value(t, NaN != NaN2,    true)
+	testing.expect_value(t, NaN != Inf,     true)
+	testing.expect_value(t, NaN != Neg_Inf, true)
+	testing.expect_value(t, NaN <  NaN,     false)
+	testing.expect_value(t, NaN <= NaN,     false)
+	testing.expect_value(t, NaN >  NaN,     false)
+	testing.expect_value(t, NaN >= NaN,     false)
+}