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));