Commit 23d99a49 by Nicolas Capens

Emulate vectors shorter than 128-bit.

Bug swiftshader:15 Change-Id: I065c52711719b12fe55cf0190e735240c008629e Reviewed-on: https://swiftshader-review.googlesource.com/7712Reviewed-by: 's avatarNicolas Capens <capn@google.com> Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-on: https://swiftshader-review.googlesource.com/7390Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 16b5f15b
......@@ -33,7 +33,7 @@ int reference(int *p, int y)
return sum;
}
TEST(SubzeroReactorSample, SubzeroReactor)
TEST(SubzeroReactorTest, Sample)
{
Routine *routine = nullptr;
......@@ -73,6 +73,66 @@ TEST(SubzeroReactorSample, SubzeroReactor)
delete routine;
}
TEST(SubzeroReactorTest, SubVectorLoadStore)
{
Routine *routine = nullptr;
{
Function<Int(Pointer<Byte>, Pointer<Byte>)> function;
{
Pointer<Byte> in = function.Arg<0>();
Pointer<Byte> out = function.Arg<1>();
*Pointer<Int4>(out + 16 * 0) = *Pointer<Int4>(in + 16 * 0);
*Pointer<Short4>(out + 16 * 1) = *Pointer<Short4>(in + 16 * 1);
*Pointer<Byte8>(out + 16 * 2) = *Pointer<Byte8>(in + 16 * 2);
*Pointer<Byte4>(out + 16 * 3) = *Pointer<Byte4>(in + 16 * 3);
*Pointer<Short2>(out + 16 * 4) = *Pointer<Short2>(in + 16 * 4);
Return(0);
}
routine = function(L"one");
if(routine)
{
int8_t in[16 * 5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0,
25, 26, 27, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0,
33, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37, 38, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int8_t out[16 * 5] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
int (*callable)(void*, void*) = (int(*)(void*,void*))routine->getEntry();
callable(in, out);
for(int row = 0; row < 5; row++)
{
for(int col = 0; col < 16; col++)
{
int i = row * 16 + col;
if(in[i] == 0)
{
EXPECT_EQ(out[i], -1) << "Row " << row << " column " << col << " not left untouched.";
}
else
{
EXPECT_EQ(out[i], in[i]) << "Row " << row << " column " << col << " not equal to input.";
}
}
}
}
}
delete routine;
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
......
......@@ -254,6 +254,8 @@
<ClInclude Include="$(SolutionDir)third_party\pnacl-subzero\src\IceTypes.h" />
<ClInclude Include="$(SolutionDir)third_party\pnacl-subzero\src\IceUtils.h" />
<ClInclude Include="$(SolutionDir)third_party\pnacl-subzero\src\IceVariableSplitting.h" />
<ClInclude Include="$(SolutionDir)third_party\pnacl-subzero\src\IceTargetLoweringX8664.h" />
<ClInclude Include="$(SolutionDir)third_party\pnacl-subzero\src\IceTargetLoweringX8664Traits.h" />
</ItemGroup>
<ItemGroup>
<None Include="$(SolutionDir)third_party\pnacl-subzero\src\IceClFlags.def" />
......
......@@ -269,6 +269,12 @@
<ClInclude Include="$(SolutionDir)third_party\pnacl-subzero\src\IceVariableSplitting.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)third_party\pnacl-subzero\src\IceTargetLoweringX8664Traits.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)third_party\pnacl-subzero\src\IceTargetLoweringX8664.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="$(SolutionDir)third_party\pnacl-subzero\src\IceClFlags.def">
......
......@@ -52,13 +52,29 @@ namespace
namespace sw
{
enum EmulatedType
{
EmulatedShift = 16,
EmulatedV2 = 2 << EmulatedShift,
EmulatedV4 = 4 << EmulatedShift,
EmulatedV8 = 8 << EmulatedShift,
EmulatedBits = EmulatedV2 | EmulatedV4 | EmulatedV8,
Type_v2i32 = Ice::IceType_v4i32 | EmulatedV2,
Type_v4i16 = Ice::IceType_v8i16 | EmulatedV4,
Type_v2i16 = Ice::IceType_v8i16 | EmulatedV2,
Type_v8i8 = Ice::IceType_v16i8 | EmulatedV8,
Type_v4i8 = Ice::IceType_v16i8 | EmulatedV4,
};
class Value : public Ice::Variable {};
class Constant : public Ice::Constant {};
class BasicBlock : public Ice::CfgNode {};
Ice::Type T(Type *t)
{
return (Ice::Type)reinterpret_cast<std::intptr_t>(t);
static_assert(Ice::IceType_NUM < EmulatedBits, "Ice::Type overlaps with our emulated types!");
return (Ice::Type)(reinterpret_cast<std::intptr_t>(t) & ~EmulatedBits);
}
Type *T(Ice::Type t)
......@@ -66,6 +82,11 @@ namespace sw
return reinterpret_cast<Type*>(t);
}
Type *T(EmulatedType t)
{
return reinterpret_cast<Type*>(t);
}
Value *V(Ice::Variable *v)
{
return reinterpret_cast<Value*>(v);
......@@ -461,16 +482,92 @@ namespace sw
Value *Nucleus::createLoad(Value *ptr, Type *type, bool isVolatile, unsigned int align)
{
Ice::Variable *value = ::function->makeVariable(T(type));
auto load = Ice::InstLoad::create(::function, value, ptr, align);
::basicBlock->appendInst(load);
return V(value);
int valueType = (int)reinterpret_cast<intptr_t>(type);
Ice::Variable *result = ::function->makeVariable(T(type));
if(valueType & EmulatedBits)
{
switch(valueType)
{
case Type_v4i8:
case Type_v2i16:
{
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::LoadSubVector, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
auto target = ::context->getConstantUndef(Ice::IceType_i32);
auto load = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic);
load->addArg(::context->getConstantInt32(4));
load->addArg(ptr);
::basicBlock->appendInst(load);
}
break;
case Type_v2i32:
case Type_v8i8:
case Type_v4i16:
{
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::LoadSubVector, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
auto target = ::context->getConstantUndef(Ice::IceType_i32);
auto load = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic);
load->addArg(::context->getConstantInt32(8));
load->addArg(ptr);
::basicBlock->appendInst(load);
}
break;
default: assert(false && "UNIMPLEMENTED");
}
}
else
{
auto load = Ice::InstLoad::create(::function, result, ptr, align);
::basicBlock->appendInst(load);
}
return V(result);
}
Value *Nucleus::createStore(Value *value, Value *ptr, Type *type, bool isVolatile, unsigned int align)
{
auto store = Ice::InstStore::create(::function, value, ptr, align);
::basicBlock->appendInst(store);
int valueType = (int)reinterpret_cast<intptr_t>(type);
if(valueType & EmulatedBits)
{
switch(valueType)
{
case Type_v4i8:
case Type_v2i16:
{
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::StoreSubVector, Ice::Intrinsics::SideEffects_T, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_T};
auto target = ::context->getConstantUndef(Ice::IceType_i32);
auto store = Ice::InstIntrinsicCall::create(::function, 3, nullptr, target, intrinsic);
store->addArg(::context->getConstantInt32(4));
store->addArg(value);
store->addArg(ptr);
::basicBlock->appendInst(store);
}
break;
case Type_v2i32:
case Type_v8i8:
case Type_v4i16:
{
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::StoreSubVector, Ice::Intrinsics::SideEffects_T, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_T};
auto target = ::context->getConstantUndef(Ice::IceType_i32);
auto store = Ice::InstIntrinsicCall::create(::function, 3, nullptr, target, intrinsic);
store->addArg(::context->getConstantInt32(8));
store->addArg(value);
store->addArg(ptr);
::basicBlock->appendInst(store);
}
break;
default: assert(false && "UNIMPLEMENTED");
}
}
else
{
assert(T(value->getType()) == type);
auto store = Ice::InstStore::create(::function, value, ptr, align);
::basicBlock->appendInst(store);
}
return value;
}
......@@ -505,7 +602,7 @@ namespace sw
static Value *createCast(Ice::InstCast::OpKind op, Value *v, Type *destType)
{
if(T(v->getType()) == destType)
if(v->getType() == T(destType))
{
return v;
}
......@@ -1955,7 +2052,7 @@ namespace sw
Type *Byte4::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Type_v4i8);
}
Type *SByte4::getType()
......@@ -2178,7 +2275,7 @@ namespace sw
Type *Byte8::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Type_v8i8);
}
SByte8::SByte8()
......@@ -2442,12 +2539,12 @@ namespace sw
Type *Byte16::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Ice::IceType_v16i8);
}
Type *SByte16::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Ice::IceType_v16i8);
}
Short2::Short2(RValue<Short4> cast)
......@@ -2457,7 +2554,7 @@ namespace sw
Type *Short2::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Type_v2i16);
}
UShort2::UShort2(RValue<UShort4> cast)
......@@ -2467,7 +2564,7 @@ namespace sw
Type *UShort2::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Type_v2i16);
}
Short4::Short4(RValue<Int> cast)
......@@ -2821,7 +2918,7 @@ namespace sw
Type *Short4::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Type_v4i16);
}
UShort4::UShort4(RValue<Int4> cast)
......@@ -3057,7 +3154,7 @@ namespace sw
Type *UShort4::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Type_v4i16);
}
Short8::Short8(short c0, short c1, short c2, short c3, short c4, short c5, short c6, short c7)
......@@ -4797,7 +4894,7 @@ namespace sw
Type *Int4::getType()
{
assert(false && "UNIMPLEMENTED"); return nullptr;
return T(Ice::IceType_v4i32);
}
UInt4::UInt4(RValue<Float4> cast)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment