Implement min/max.
Bug swiftshader:15
Change-Id: I785e31724e802a3ed1bca75186e012ccc7cb336e
Reviewed-on: https://swiftshader-review.googlesource.com/7850
Reviewed-by: Nicolas Capens <capn@google.com>
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-on: https://swiftshader-review.googlesource.com/8151
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Reactor/Main.cpp b/src/Reactor/Main.cpp
index cbf6d23..cd7be18 100644
--- a/src/Reactor/Main.cpp
+++ b/src/Reactor/Main.cpp
@@ -342,6 +342,97 @@
delete routine;
}
+TEST(SubzeroReactorTest, MinMax)
+{
+ Routine *routine = nullptr;
+
+ {
+ Function<Int(Pointer<Byte>)> function;
+ {
+ Pointer<Byte> out = function.Arg<0>();
+
+ *Pointer<Float4>(out + 16 * 0) = Min(Float4(1.0f, 0.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
+ *Pointer<Float4>(out + 16 * 1) = Max(Float4(1.0f, 0.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
+
+ *Pointer<Int4>(out + 16 * 2) = Min(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
+ *Pointer<Int4>(out + 16 * 3) = Max(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
+ *Pointer<UInt4>(out + 16 * 4) = Min(UInt4(1, 0, -1, -0), UInt4(0, 1, 0, +0));
+ *Pointer<UInt4>(out + 16 * 5) = Max(UInt4(1, 0, -1, -0), UInt4(0, 1, 0, +0));
+
+ *Pointer<Short4>(out + 16 * 6) = Min(Short4(1, 0, -1, -0), Short4(0, 1, 0, +0));
+ *Pointer<Short4>(out + 16 * 7) = Max(Short4(1, 0, -1, -0), Short4(0, 1, 0, +0));
+ *Pointer<UShort4>(out + 16 * 8) = Min(UShort4(1, 0, -1, -0), UShort4(0, 1, 0, +0));
+ *Pointer<UShort4>(out + 16 * 9) = Max(UShort4(1, 0, -1, -0), UShort4(0, 1, 0, +0));
+
+ Return(0);
+ }
+
+ routine = function(L"one");
+
+ if(routine)
+ {
+ int out[10][4];
+
+ memset(&out, 0, sizeof(out));
+
+ int(*callable)(void*) = (int(*)(void*))routine->getEntry();
+ callable(&out);
+
+ EXPECT_EQ(out[0][0], 0x00000000);
+ EXPECT_EQ(out[0][1], 0x00000000);
+ EXPECT_EQ(out[0][2], 0x80000000);
+ EXPECT_EQ(out[0][3], 0x00000000);
+
+ EXPECT_EQ(out[1][0], 0x3F800000);
+ EXPECT_EQ(out[1][1], 0x3F800000);
+ EXPECT_EQ(out[1][2], 0x00000000);
+ EXPECT_EQ(out[1][3], 0x80000000);
+
+ EXPECT_EQ(out[2][0], 0x00000000);
+ EXPECT_EQ(out[2][1], 0x00000000);
+ EXPECT_EQ(out[2][2], 0xFFFFFFFF);
+ EXPECT_EQ(out[2][3], 0x00000000);
+
+ EXPECT_EQ(out[3][0], 0x00000001);
+ EXPECT_EQ(out[3][1], 0x00000001);
+ EXPECT_EQ(out[3][2], 0x00000000);
+ EXPECT_EQ(out[3][3], 0x00000000);
+
+ EXPECT_EQ(out[4][0], 0x00000000);
+ EXPECT_EQ(out[4][1], 0x00000000);
+ EXPECT_EQ(out[4][2], 0x00000000);
+ EXPECT_EQ(out[4][3], 0x00000000);
+
+ EXPECT_EQ(out[5][0], 0x00000001);
+ EXPECT_EQ(out[5][1], 0x00000001);
+ EXPECT_EQ(out[5][2], 0xFFFFFFFF);
+ EXPECT_EQ(out[5][3], 0x00000000);
+
+ EXPECT_EQ(out[6][0], 0x00000000);
+ EXPECT_EQ(out[6][1], 0x0000FFFF);
+ EXPECT_EQ(out[6][2], 0x00000000);
+ EXPECT_EQ(out[6][3], 0x00000000);
+
+ EXPECT_EQ(out[7][0], 0x00010001);
+ EXPECT_EQ(out[7][1], 0x00000000);
+ EXPECT_EQ(out[7][2], 0x00000000);
+ EXPECT_EQ(out[7][3], 0x00000000);
+
+ EXPECT_EQ(out[8][0], 0x00000000);
+ EXPECT_EQ(out[8][1], 0x00000000);
+ EXPECT_EQ(out[8][2], 0x00000000);
+ EXPECT_EQ(out[8][3], 0x00000000);
+
+ EXPECT_EQ(out[9][0], 0x00010001);
+ EXPECT_EQ(out[9][1], 0x0000FFFF);
+ EXPECT_EQ(out[9][2], 0x00000000);
+ EXPECT_EQ(out[9][3], 0x00000000);
+ }
+ }
+
+ delete routine;
+}
+
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index c15ea8e..dd0f68d 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -1013,7 +1013,13 @@
Value *Nucleus::createSelect(Value *C, Value *ifTrue, Value *ifFalse)
{
- assert(false && "UNIMPLEMENTED"); return nullptr;
+ assert(ifTrue->getType() == ifFalse->getType());
+
+ auto result = ::function->makeVariable(ifTrue->getType());
+ auto *select = Ice::InstSelect::create(::function, result, C, ifTrue, ifFalse);
+ ::basicBlock->appendInst(select);
+
+ return V(result);
}
Value *Nucleus::createSwitch(Value *v, BasicBlock *Dest, unsigned NumCases)
@@ -3162,12 +3168,28 @@
RValue<Short4> Max(RValue<Short4> x, RValue<Short4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<Short4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1);
+ auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sle, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<Short4>(V(result));
}
RValue<Short4> Min(RValue<Short4> x, RValue<Short4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<Short4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1);
+ auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sgt, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<Short4>(V(result));
}
RValue<Short4> AddSat(RValue<Short4> x, RValue<Short4> y)
@@ -3459,12 +3481,28 @@
RValue<UShort4> Max(RValue<UShort4> x, RValue<UShort4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<UShort4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1);
+ auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ule, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<UShort4>(V(result));
}
RValue<UShort4> Min(RValue<UShort4> x, RValue<UShort4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<UShort4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v8i1);
+ auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ugt, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<UShort4>(V(result));
}
RValue<UShort4> AddSat(RValue<UShort4> x, RValue<UShort4> y)
@@ -5181,12 +5219,28 @@
RValue<Int4> Max(RValue<Int4> x, RValue<Int4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<Int4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
+ auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sle, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<Int4>(V(result));
}
RValue<Int4> Min(RValue<Int4> x, RValue<Int4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<Int4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
+ auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Sgt, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<Int4>(V(result));
}
RValue<Int4> RoundInt(RValue<Float4> cast)
@@ -5510,12 +5564,28 @@
RValue<UInt4> Max(RValue<UInt4> x, RValue<UInt4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<UInt4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
+ auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ule, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<UInt4>(V(result));
}
RValue<UInt4> Min(RValue<UInt4> x, RValue<UInt4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<UInt4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
+ auto cmp = Ice::InstIcmp::create(::function, Ice::InstIcmp::Ugt, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<UInt4>(V(result));
}
RValue<UShort8> Pack(RValue<UInt4> x, RValue<UInt4> y)
@@ -5977,12 +6047,28 @@
RValue<Float4> Max(RValue<Float4> x, RValue<Float4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<Float4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
+ auto cmp = Ice::InstFcmp::create(::function, Ice::InstFcmp::Ule, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<Float4>(V(result));
}
RValue<Float4> Min(RValue<Float4> x, RValue<Float4> y)
{
- assert(false && "UNIMPLEMENTED"); return RValue<Float4>(V(nullptr));
+ Ice::Variable *condition = ::function->makeVariable(Ice::IceType_v4i1);
+ auto cmp = Ice::InstFcmp::create(::function, Ice::InstFcmp::Ugt, condition, x.value, y.value);
+ ::basicBlock->appendInst(cmp);
+
+ Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
+ auto select = Ice::InstSelect::create(::function, result, condition, y.value, x.value);
+ ::basicBlock->appendInst(select);
+
+ return RValue<Float4>(V(result));
}
RValue<Float4> Rcp_pp(RValue<Float4> x, bool exactAtPow2)