Commit 9ca48d5c by Nicolas Capens

Emit SSE2 compatible operations if SSE4.1 is not supported.

Bug swiftshader:20 Change-Id: I67818bfe10cb29211559fb2ee047f6bec6ce46d4 Reviewed-on: https://swiftshader-review.googlesource.com/8451Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent ccd5ecb4
...@@ -3311,7 +3311,7 @@ namespace sw ...@@ -3311,7 +3311,7 @@ namespace sw
{ {
if(saturate) if(saturate)
{ {
if(true) // SSE 4.1 if(CPUID::SSE4_1)
{ {
Int4 int4(Min(cast, Float4(0xFFFF))); // packusdw takes care of 0x0000 saturation Int4 int4(Min(cast, Float4(0xFFFF))); // packusdw takes care of 0x0000 saturation
*this = As<Short4>(Pack(As<UInt4>(int4), As<UInt4>(int4))); *this = As<Short4>(Pack(As<UInt4>(int4), As<UInt4>(int4)));
...@@ -4074,11 +4074,12 @@ namespace sw ...@@ -4074,11 +4074,12 @@ namespace sw
RValue<Int> RoundInt(RValue<Float> cast) RValue<Int> RoundInt(RValue<Float> cast)
{ {
RValue<Float> rounded = Round(cast);
Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32); Ice::Variable *result = ::function->makeVariable(Ice::IceType_i32);
auto round = Ice::InstCast::create(::function, Ice::InstCast::Fptosi, result, rounded.value); const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
::basicBlock->appendInst(round); auto target = ::context->getConstantUndef(Ice::IceType_i32);
auto nearbyint = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic);
nearbyint->addArg(cast.value);
::basicBlock->appendInst(nearbyint);
return RValue<Int>(V(result)); return RValue<Int>(V(result));
} }
...@@ -5229,11 +5230,12 @@ namespace sw ...@@ -5229,11 +5230,12 @@ namespace sw
RValue<Int4> RoundInt(RValue<Float4> cast) RValue<Int4> RoundInt(RValue<Float4> cast)
{ {
RValue<Float4> rounded = Round(cast);
Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32); Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4i32);
auto round = Ice::InstCast::create(::function, Ice::InstCast::Fptosi, result, rounded.value); const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Nearbyint, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
::basicBlock->appendInst(round); auto target = ::context->getConstantUndef(Ice::IceType_i32);
auto nearbyint = Ice::InstIntrinsicCall::create(::function, 1, result, target, intrinsic);
nearbyint->addArg(cast.value);
::basicBlock->appendInst(nearbyint);
return RValue<Int4>(V(result)); return RValue<Int4>(V(result));
} }
...@@ -5573,15 +5575,28 @@ namespace sw ...@@ -5573,15 +5575,28 @@ namespace sw
RValue<UShort8> Pack(RValue<UInt4> x, RValue<UInt4> y) RValue<UShort8> Pack(RValue<UInt4> x, RValue<UInt4> y)
{ {
Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16); if(CPUID::SSE4_1)
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::VectorPackUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; {
auto target = ::context->getConstantUndef(Ice::IceType_i32); Ice::Variable *result = ::function->makeVariable(Ice::IceType_v8i16);
auto pack = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::VectorPackUnsigned, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
pack->addArg(x.value); auto target = ::context->getConstantUndef(Ice::IceType_i32);
pack->addArg(y.value); auto pack = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic);
::basicBlock->appendInst(pack); pack->addArg(x.value);
pack->addArg(y.value);
::basicBlock->appendInst(pack);
return RValue<UShort8>(V(result));
}
else
{
RValue<Int4> sx = As<Int4>(x);
RValue<Int4> bx = (sx & ~(sx >> 31)) - Int4(0x8000);
return RValue<UShort8>(V(result)); RValue<Int4> sy = As<Int4>(y);
RValue<Int4> by = (sy & ~(sy >> 31)) - Int4(0x8000);
return As<UShort8>(Pack(bx, by) + Short8(0x8000u));
}
} }
Type *UInt4::getType() Type *UInt4::getType()
...@@ -6162,59 +6177,96 @@ namespace sw ...@@ -6162,59 +6177,96 @@ namespace sw
RValue<Float4> Round(RValue<Float4> x) RValue<Float4> Round(RValue<Float4> x)
{ {
Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); if(CPUID::SSE4_1)
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; {
auto target = ::context->getConstantUndef(Ice::IceType_i32); Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
round->addArg(x.value); auto target = ::context->getConstantUndef(Ice::IceType_i32);
round->addArg(::context->getConstantInt32(0)); auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic);
::basicBlock->appendInst(round); round->addArg(x.value);
round->addArg(::context->getConstantInt32(0));
return RValue<Float4>(V(result)); ::basicBlock->appendInst(round);
return RValue<Float4>(V(result));
}
else
{
return Float4(RoundInt(x));
}
} }
RValue<Float4> Trunc(RValue<Float4> x) RValue<Float4> Trunc(RValue<Float4> x)
{ {
Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); if(CPUID::SSE4_1)
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; {
auto target = ::context->getConstantUndef(Ice::IceType_i32); Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
round->addArg(x.value); auto target = ::context->getConstantUndef(Ice::IceType_i32);
round->addArg(::context->getConstantInt32(3)); auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic);
::basicBlock->appendInst(round); round->addArg(x.value);
round->addArg(::context->getConstantInt32(3));
return RValue<Float4>(V(result)); ::basicBlock->appendInst(round);
return RValue<Float4>(V(result));
}
else
{
return Float4(Int4(x));
}
} }
RValue<Float4> Frac(RValue<Float4> x) RValue<Float4> Frac(RValue<Float4> x)
{ {
return x - Floor(x); if(CPUID::SSE4_1)
{
return x - Floor(x);
}
else
{
Float4 frc = x - Float4(Int4(x)); // Signed fractional part
return frc + As<Float4>(As<Int4>(CmpNLE(Float4(0.0f), frc)) & As<Int4>(Float4(1, 1, 1, 1)));
}
} }
RValue<Float4> Floor(RValue<Float4> x) RValue<Float4> Floor(RValue<Float4> x)
{ {
Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); if(CPUID::SSE4_1)
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; {
auto target = ::context->getConstantUndef(Ice::IceType_i32); Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
round->addArg(x.value); auto target = ::context->getConstantUndef(Ice::IceType_i32);
round->addArg(::context->getConstantInt32(1)); auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic);
::basicBlock->appendInst(round); round->addArg(x.value);
round->addArg(::context->getConstantInt32(1));
return RValue<Float4>(V(result)); ::basicBlock->appendInst(round);
return RValue<Float4>(V(result));
}
else
{
return x - Frac(x);
}
} }
RValue<Float4> Ceil(RValue<Float4> x) RValue<Float4> Ceil(RValue<Float4> x)
{ {
Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32); if(CPUID::SSE4_1)
const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F}; {
auto target = ::context->getConstantUndef(Ice::IceType_i32); Ice::Variable *result = ::function->makeVariable(Ice::IceType_v4f32);
auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic); const Ice::Intrinsics::IntrinsicInfo intrinsic = {Ice::Intrinsics::Round, Ice::Intrinsics::SideEffects_F, Ice::Intrinsics::ReturnsTwice_F, Ice::Intrinsics::MemoryWrite_F};
round->addArg(x.value); auto target = ::context->getConstantUndef(Ice::IceType_i32);
round->addArg(::context->getConstantInt32(2)); auto round = Ice::InstIntrinsicCall::create(::function, 2, result, target, intrinsic);
::basicBlock->appendInst(round); round->addArg(x.value);
round->addArg(::context->getConstantInt32(2));
return RValue<Float4>(V(result)); ::basicBlock->appendInst(round);
return RValue<Float4>(V(result));
}
else
{
return -Floor(-x);
}
} }
Type *Float4::getType() Type *Float4::getType()
......
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