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/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index d3c0061..1b3e297 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -250,6 +250,18 @@
case spv::OpFAdd:
case spv::OpFSub:
case spv::OpFDiv:
+ case spv::OpFOrdEqual:
+ case spv::OpFUnordEqual:
+ case spv::OpFOrdNotEqual:
+ case spv::OpFUnordNotEqual:
+ case spv::OpFOrdLessThan:
+ case spv::OpFUnordLessThan:
+ case spv::OpFOrdGreaterThan:
+ case spv::OpFUnordGreaterThan:
+ case spv::OpFOrdLessThanEqual:
+ case spv::OpFUnordLessThanEqual:
+ case spv::OpFOrdGreaterThanEqual:
+ case spv::OpFUnordGreaterThanEqual:
case spv::OpUMod:
case spv::OpIEqual:
case spv::OpINotEqual:
@@ -953,6 +965,18 @@
case spv::OpFAdd:
case spv::OpFSub:
case spv::OpFDiv:
+ case spv::OpFOrdEqual:
+ case spv::OpFUnordEqual:
+ case spv::OpFOrdNotEqual:
+ case spv::OpFUnordNotEqual:
+ case spv::OpFOrdLessThan:
+ case spv::OpFUnordLessThan:
+ case spv::OpFOrdGreaterThan:
+ case spv::OpFUnordGreaterThan:
+ case spv::OpFOrdLessThanEqual:
+ case spv::OpFUnordLessThanEqual:
+ case spv::OpFOrdGreaterThanEqual:
+ case spv::OpFUnordGreaterThanEqual:
case spv::OpUMod:
case spv::OpIEqual:
case spv::OpINotEqual:
@@ -1354,6 +1378,42 @@
case spv::OpFDiv:
dst.emplace(i, lhs / rhs);
break;
+ case spv::OpFOrdEqual:
+ dst.emplace(i, As<SIMD::Float>(CmpEQ(lhs, rhs)));
+ break;
+ case spv::OpFUnordEqual:
+ dst.emplace(i, As<SIMD::Float>(CmpUEQ(lhs, rhs)));
+ break;
+ case spv::OpFOrdNotEqual:
+ dst.emplace(i, As<SIMD::Float>(CmpNEQ(lhs, rhs)));
+ break;
+ case spv::OpFUnordNotEqual:
+ dst.emplace(i, As<SIMD::Float>(CmpUNEQ(lhs, rhs)));
+ break;
+ case spv::OpFOrdLessThan:
+ dst.emplace(i, As<SIMD::Float>(CmpLT(lhs, rhs)));
+ break;
+ case spv::OpFUnordLessThan:
+ dst.emplace(i, As<SIMD::Float>(CmpULT(lhs, rhs)));
+ break;
+ case spv::OpFOrdGreaterThan:
+ dst.emplace(i, As<SIMD::Float>(CmpGT(lhs, rhs)));
+ break;
+ case spv::OpFUnordGreaterThan:
+ dst.emplace(i, As<SIMD::Float>(CmpUGT(lhs, rhs)));
+ break;
+ case spv::OpFOrdLessThanEqual:
+ dst.emplace(i, As<SIMD::Float>(CmpLE(lhs, rhs)));
+ break;
+ case spv::OpFUnordLessThanEqual:
+ dst.emplace(i, As<SIMD::Float>(CmpULE(lhs, rhs)));
+ break;
+ case spv::OpFOrdGreaterThanEqual:
+ dst.emplace(i, As<SIMD::Float>(CmpGE(lhs, rhs)));
+ break;
+ case spv::OpFUnordGreaterThanEqual:
+ dst.emplace(i, As<SIMD::Float>(CmpUGE(lhs, rhs)));
+ break;
case spv::OpShiftRightLogical:
dst.emplace(i, As<SIMD::Float>(As<SIMD::UInt>(lhs) >> As<SIMD::UInt>(rhs)));
break;
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index 6831082..d0b6659 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -6809,6 +6809,36 @@
return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpOGT(x.value, y.value), Int4::getType()));
}
+ RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y)
+ {
+ return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUEQ(x.value, y.value), Int4::getType()));
+ }
+
+ RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y)
+ {
+ return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpULT(x.value, y.value), Int4::getType()));
+ }
+
+ RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y)
+ {
+ return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpULE(x.value, y.value), Int4::getType()));
+ }
+
+ RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y)
+ {
+ return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUNE(x.value, y.value), Int4::getType()));
+ }
+
+ RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y)
+ {
+ return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUGE(x.value, y.value), Int4::getType()));
+ }
+
+ RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y)
+ {
+ return RValue<Int4>(Nucleus::createSExt(Nucleus::createFCmpUGT(x.value, y.value), Int4::getType()));
+ }
+
RValue<Int4> IsInf(RValue<Float4> x)
{
return CmpEQ(As<Int4>(x) & Int4(0x7FFFFFFF), Int4(0x7F800000));
diff --git a/src/Reactor/Reactor.hpp b/src/Reactor/Reactor.hpp
index cfbd00a..099ced3 100644
--- a/src/Reactor/Reactor.hpp
+++ b/src/Reactor/Reactor.hpp
@@ -2138,12 +2138,27 @@
RValue<Float4> UnpackHigh(RValue<Float4> x, RValue<Float4> y);
RValue<Float4> Mask(Float4 &lhs, RValue<Float4> rhs, unsigned char select);
RValue<Int> SignMask(RValue<Float4> x);
+
+ // Ordered comparison functions
RValue<Int4> CmpEQ(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpLT(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpLE(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpNEQ(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpNLT(RValue<Float4> x, RValue<Float4> y);
RValue<Int4> CmpNLE(RValue<Float4> x, RValue<Float4> y);
+ inline RValue<Int4> CmpGT(RValue<Float4> x, RValue<Float4> y) { return CmpNLE(x, y); }
+ inline RValue<Int4> CmpGE(RValue<Float4> x, RValue<Float4> y) { return CmpNLT(x, y); }
+
+ // Unordered comparison functions
+ RValue<Int4> CmpUEQ(RValue<Float4> x, RValue<Float4> y);
+ RValue<Int4> CmpULT(RValue<Float4> x, RValue<Float4> y);
+ RValue<Int4> CmpULE(RValue<Float4> x, RValue<Float4> y);
+ RValue<Int4> CmpUNEQ(RValue<Float4> x, RValue<Float4> y);
+ RValue<Int4> CmpUNLT(RValue<Float4> x, RValue<Float4> y);
+ RValue<Int4> CmpUNLE(RValue<Float4> x, RValue<Float4> y);
+ inline RValue<Int4> CmpUGT(RValue<Float4> x, RValue<Float4> y) { return CmpUNLE(x, y); }
+ inline RValue<Int4> CmpUGE(RValue<Float4> x, RValue<Float4> y) { return CmpUNLT(x, y); }
+
RValue<Int4> IsInf(RValue<Float4> x);
RValue<Int4> IsNan(RValue<Float4> x);
RValue<Float4> Round(RValue<Float4> x);
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));