SpirvShader: Add relational ops for ordered and unordered floats

Bug: b/127282157
Change-Id: Id2c5b29d744f6f7ddcbb853db0a95228425d7f83
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/26108
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 7048640..b4f1971 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -6387,38 +6387,38 @@
 		return T(Ice::IceType_v4i32);
 	}
 
-	Half::Half(RValue<Float> cast)

-	{

-		UInt fp32i = As<UInt>(cast);

-		UInt abs = fp32i & 0x7FFFFFFF;

-		UShort fp16i((fp32i & 0x80000000) >> 16); // sign

-

-		If(abs > 0x47FFEFFF) // Infinity

-		{

-			fp16i |= UShort(0x7FFF);

-		}

-		Else

-		{

-			If(abs < 0x38800000) // Denormal

-			{

-				Int mantissa = (abs & 0x007FFFFF) | 0x00800000;

-				Int e = 113 - (abs >> 23);

-				abs = IfThenElse(e < 24, mantissa >> e, Int(0));

-				fp16i |= UShort((abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);

-			}

-			Else

-			{

-				fp16i |= UShort((abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);

-			}

-		}

-

-		storeValue(fp16i.loadValue());

-	}

-

-	Type *Half::getType()

-	{

-		return T(Ice::IceType_i16);

-	}

+	Half::Half(RValue<Float> cast)
+	{
+		UInt fp32i = As<UInt>(cast);
+		UInt abs = fp32i & 0x7FFFFFFF;
+		UShort fp16i((fp32i & 0x80000000) >> 16); // sign
+
+		If(abs > 0x47FFEFFF) // Infinity
+		{
+			fp16i |= UShort(0x7FFF);
+		}
+		Else
+		{
+			If(abs < 0x38800000) // Denormal
+			{
+				Int mantissa = (abs & 0x007FFFFF) | 0x00800000;
+				Int e = 113 - (abs >> 23);
+				abs = IfThenElse(e < 24, mantissa >> e, Int(0));
+				fp16i |= UShort((abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+			}
+			Else
+			{
+				fp16i |= UShort((abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+			}
+		}
+
+		storeValue(fp16i.loadValue());
+	}
+
+	Type *Half::getType()
+	{
+		return T(Ice::IceType_i16);
+	}
 
 	Float::Float(RValue<Int> cast)
 	{
@@ -6435,34 +6435,34 @@
 		storeValue(result.value);
 	}
 
-	Float::Float(RValue<Half> cast)

-	{

-		Int fp16i(As<UShort>(cast));

-

-		Int s = (fp16i >> 15) & 0x00000001;

-		Int e = (fp16i >> 10) & 0x0000001F;

-		Int m = fp16i & 0x000003FF;

-

-		UInt fp32i(s << 31);

-		If(e == 0)

-		{

-			If(m != 0)

-			{

-				While((m & 0x00000400) == 0)

-				{

-					m <<= 1;

-					e -= 1;

-				}

-

-				fp32i |= As<UInt>(((e + (127 - 15) + 1) << 23) | ((m & ~0x00000400) << 13));

-			}

-		}

-		Else

-		{

-			fp32i |= As<UInt>(((e + (127 - 15)) << 23) | (m << 13));

-		}

-

-		storeValue(As<Float>(fp32i).value);

+	Float::Float(RValue<Half> cast)
+	{
+		Int fp16i(As<UShort>(cast));
+
+		Int s = (fp16i >> 15) & 0x00000001;
+		Int e = (fp16i >> 10) & 0x0000001F;
+		Int m = fp16i & 0x000003FF;
+
+		UInt fp32i(s << 31);
+		If(e == 0)
+		{
+			If(m != 0)
+			{
+				While((m & 0x00000400) == 0)
+				{
+					m <<= 1;
+					e -= 1;
+				}
+
+				fp32i |= As<UInt>(((e + (127 - 15) + 1) << 23) | ((m & ~0x00000400) << 13));
+			}
+		}
+		Else
+		{
+			fp32i |= As<UInt>(((e + (127 - 15)) << 23) | (m << 13));
+		}
+
+		storeValue(As<Float>(fp32i).value);
 	}
 
 	Float::Float(float x)
@@ -7049,6 +7049,36 @@
 		return RValue<Int4>(Nucleus::createFCmpOGT(x.value, y.value));
 	}
 
+	RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y)
+	{
+		return RValue<Int4>(Nucleus::createFCmpUEQ(x.value, y.value));
+	}
+
+	RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y)
+	{
+		return RValue<Int4>(Nucleus::createFCmpULT(x.value, y.value));
+	}
+
+	RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y)
+	{
+		return RValue<Int4>(Nucleus::createFCmpULE(x.value, y.value));
+	}
+
+	RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y)
+	{
+		return RValue<Int4>(Nucleus::createFCmpUNE(x.value, y.value));
+	}
+
+	RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y)
+	{
+		return RValue<Int4>(Nucleus::createFCmpUGE(x.value, y.value));
+	}
+
+	RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y)
+	{
+		return RValue<Int4>(Nucleus::createFCmpUGT(x.value, y.value));
+	}
+
 	RValue<Int4> IsInf(RValue<Float4> x)
 	{
 		return CmpEQ(As<Int4>(x) & Int4(0x7FFFFFFF), Int4(0x7F800000));