Commit e3cabdaf by Nicolas Capens

Implement vector sign mask intrinsic.

BUG=swiftshader:15 Change-Id: I7fec56518a5b4e07d2189ab01a0a223b038564c1
parent 8b8af824
...@@ -465,8 +465,7 @@ public: ...@@ -465,8 +465,7 @@ public:
void ucomiss(Type Ty, XmmRegister a, XmmRegister b); void ucomiss(Type Ty, XmmRegister a, XmmRegister b);
void ucomiss(Type Ty, XmmRegister a, const Address &b); void ucomiss(Type Ty, XmmRegister a, const Address &b);
void movmskpd(GPRRegister dst, XmmRegister src); void movmsk(Type Ty, GPRRegister dst, XmmRegister src);
void movmskps(GPRRegister dst, XmmRegister src);
void sqrtss(Type Ty, XmmRegister dst, const Address &src); void sqrtss(Type Ty, XmmRegister dst, const Address &src);
void sqrtss(Type Ty, XmmRegister dst, XmmRegister src); void sqrtss(Type Ty, XmmRegister dst, XmmRegister src);
......
...@@ -1916,21 +1916,25 @@ void AssemblerX86Base<TraitsType>::ucomiss(Type Ty, XmmRegister a, ...@@ -1916,21 +1916,25 @@ void AssemblerX86Base<TraitsType>::ucomiss(Type Ty, XmmRegister a,
} }
template <typename TraitsType> template <typename TraitsType>
void AssemblerX86Base<TraitsType>::movmskpd(GPRRegister dst, XmmRegister src) { void AssemblerX86Base<TraitsType>::movmsk(Type Ty, GPRRegister dst,
XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
if (Ty == IceType_v16i8) {
emitUint8(0x66); emitUint8(0x66);
} else if (Ty == IceType_v4f32 || Ty == IceType_v4i32) {
// No operand size prefix
} else {
assert(false && "Unexpected movmsk operand type");
}
emitRexRB(RexTypeIrrelevant, dst, src); emitRexRB(RexTypeIrrelevant, dst, src);
emitUint8(0x0F); emitUint8(0x0F);
if (Ty == IceType_v16i8) {
emitUint8(0xD7);
} else if (Ty == IceType_v4f32 || Ty == IceType_v4i32) {
emitUint8(0x50); emitUint8(0x50);
emitXmmRegisterOperand(dst, src); } else {
} assert(false && "Unexpected movmsk operand type");
}
template <typename TraitsType>
void AssemblerX86Base<TraitsType>::movmskps(GPRRegister dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
emitRexRB(RexTypeIrrelevant, dst, src);
emitUint8(0x0F);
emitUint8(0x50);
emitXmmRegisterOperand(dst, src); emitXmmRegisterOperand(dst, src);
} }
......
...@@ -117,6 +117,7 @@ template <typename TraitsType> struct InstImpl { ...@@ -117,6 +117,7 @@ template <typename TraitsType> struct InstImpl {
Maxss, Maxss,
Mov, Mov,
Movd, Movd,
Movmsk,
Movp, Movp,
Movq, Movq,
MovssRegs, MovssRegs,
...@@ -1250,6 +1251,27 @@ template <typename TraitsType> struct InstImpl { ...@@ -1250,6 +1251,27 @@ template <typename TraitsType> struct InstImpl {
: InstX86BaseUnaryopXmm<InstX86Base::Movd>(Func, Dest, Src) {} : InstX86BaseUnaryopXmm<InstX86Base::Movd>(Func, Dest, Src) {}
}; };
class InstX86Movmsk final : public InstX86Base {
InstX86Movmsk() = delete;
InstX86Movmsk(const InstX86Movmsk &) = delete;
InstX86Movmsk &operator=(const InstX86Movmsk &) = delete;
public:
static InstX86Movmsk *create(Cfg *Func, Variable *Dest, Operand *Source) {
return new (Func->allocate<InstX86Movmsk>())
InstX86Movmsk(Func, Dest, Source);
}
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Instr) {
return InstX86Base::isClassof(Instr, InstX86Base::InstX86Movmsk);
}
private:
InstX86Movmsk(Cfg *Func, Variable *Dest, Operand *Source);
};
class InstX86Sqrtss : public InstX86BaseUnaryopXmm<InstX86Base::Sqrtss> { class InstX86Sqrtss : public InstX86BaseUnaryopXmm<InstX86Base::Sqrtss> {
public: public:
static InstX86Sqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) { static InstX86Sqrtss *create(Cfg *Func, Variable *Dest, Operand *Src) {
...@@ -3005,6 +3027,7 @@ template <typename TraitsType> struct Insts { ...@@ -3005,6 +3027,7 @@ template <typename TraitsType> struct Insts {
using Movsx = typename InstImpl<TraitsType>::InstX86Movsx; using Movsx = typename InstImpl<TraitsType>::InstX86Movsx;
using Movzx = typename InstImpl<TraitsType>::InstX86Movzx; using Movzx = typename InstImpl<TraitsType>::InstX86Movzx;
using Movd = typename InstImpl<TraitsType>::InstX86Movd; using Movd = typename InstImpl<TraitsType>::InstX86Movd;
using Movmsk = typename InstImpl<TraitsType>::InstX86Movmsk;
using Sqrtss = typename InstImpl<TraitsType>::InstX86Sqrtss; using Sqrtss = typename InstImpl<TraitsType>::InstX86Sqrtss;
using Mov = typename InstImpl<TraitsType>::InstX86Mov; using Mov = typename InstImpl<TraitsType>::InstX86Mov;
using Movp = typename InstImpl<TraitsType>::InstX86Movp; using Movp = typename InstImpl<TraitsType>::InstX86Movp;
......
...@@ -181,6 +181,13 @@ InstImpl<TraitsType>::InstX86Call::InstX86Call(Cfg *Func, Variable *Dest, ...@@ -181,6 +181,13 @@ InstImpl<TraitsType>::InstX86Call::InstX86Call(Cfg *Func, Variable *Dest,
} }
template <typename TraitsType> template <typename TraitsType>
InstImpl<TraitsType>::InstX86Movmsk::InstX86Movmsk(Cfg *Func, Variable *Dest,
Operand *Source)
: InstX86Base(Func, InstX86Base::Movmsk, 1, Dest) {
this->addSource(Source);
}
template <typename TraitsType>
InstImpl<TraitsType>::InstX86Cmov::InstX86Cmov(Cfg *Func, Variable *Dest, InstImpl<TraitsType>::InstX86Cmov::InstX86Cmov(Cfg *Func, Variable *Dest,
Operand *Source, Operand *Source,
BrCond Condition) BrCond Condition)
...@@ -1008,6 +1015,64 @@ void InstImpl<TraitsType>::emitIASMovlikeXMM(const Cfg *Func, ...@@ -1008,6 +1015,64 @@ void InstImpl<TraitsType>::emitIASMovlikeXMM(const Cfg *Func,
} }
template <typename TraitsType> template <typename TraitsType>
void InstImpl<TraitsType>::InstX86Movmsk::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
this->dumpDest(Func);
Str << " = movmsk." << this->getSrc(0)->getType() << " ";
this->dumpSources(Func);
}
template <typename TraitsType>
void InstImpl<TraitsType>::InstX86Movmsk::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
assert(this->getSrcSize() == 1);
Type SrcTy = this->getSrc(0)->getType();
assert(isVectorType(SrcTy));
switch (SrcTy) {
case IceType_v16i8:
Str << "\t"
"pmovmskb"
"\t";
break;
case IceType_v4i32:
case IceType_v4f32:
Str << "\t"
"movmskps"
"\t";
break;
default:
llvm_unreachable("Unexpected operand type");
}
this->getSrc(0)->emit(Func);
Str << ", ";
this->getDest()->emit(Func);
}
template <typename TraitsType>
void InstImpl<TraitsType>::InstX86Movmsk::emitIAS(const Cfg *Func) const {
assert(this->getSrcSize() == 1);
Assembler *Asm = Func->getAssembler<Assembler>();
const Variable *Dest = this->getDest();
const Variable *Src = llvm::cast<Variable>(this->getSrc(0));
const Type DestTy = Dest->getType();
const Type SrcTy = Src->getType();
assert(isVectorType(SrcTy));
assert(isScalarIntegerType(DestTy));
if (!Traits::Is64Bit) {
assert(typeWidthInBytes(DestTy) <= 4);
} else {
assert(DestTy == IceType_i32 || DestTy == IceType_i64);
}
XmmRegister SrcReg = Traits::getEncodedXmm(Src->getRegNum());
GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
Asm->movmsk(SrcTy, DestReg, SrcReg);
}
template <typename TraitsType>
void InstImpl<TraitsType>::InstX86Sqrtss::emit(const Cfg *Func) const { void InstImpl<TraitsType>::InstX86Sqrtss::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
......
...@@ -65,7 +65,8 @@ public: ...@@ -65,7 +65,8 @@ public:
LoadSubVector, LoadSubVector,
StoreSubVector, StoreSubVector,
VectorPackSigned, VectorPackSigned,
VectorPackUnsigned VectorPackUnsigned,
SignMask
}; };
/// Operations that can be represented by the AtomicRMW intrinsic. /// Operations that can be represented by the AtomicRMW intrinsic.
......
...@@ -905,6 +905,10 @@ protected: ...@@ -905,6 +905,10 @@ protected:
AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1); AutoMemorySandboxer<> _(this, &Dest, &Src0, &Src1);
Context.insert<typename Traits::Insts::Shufps>(Dest, Src0, Src1); Context.insert<typename Traits::Insts::Shufps>(Dest, Src0, Src1);
} }
void _movmsk(Variable *Dest, Operand *Src0) {
AutoMemorySandboxer<> _(this, &Dest, &Src0);
Context.insert<typename Traits::Insts::Movmsk>(Dest, Src0);
}
void _sqrtss(Variable *Dest, Operand *Src0) { void _sqrtss(Variable *Dest, Operand *Src0) {
AutoMemorySandboxer<> _(this, &Dest, &Src0); AutoMemorySandboxer<> _(this, &Dest, &Src0);
Context.insert<typename Traits::Insts::Sqrtss>(Dest, Src0); Context.insert<typename Traits::Insts::Sqrtss>(Dest, Src0);
......
...@@ -4455,6 +4455,21 @@ void TargetX86Base<TraitsType>::lowerIntrinsicCall( ...@@ -4455,6 +4455,21 @@ void TargetX86Base<TraitsType>::lowerIntrinsicCall(
_movp(Dest, T); _movp(Dest, T);
return; return;
} }
case Intrinsics::SignMask: {
Operand *SrcReg = legalizeToReg(Instr->getArg(0));
Variable *Dest = Instr->getDest();
Variable *T = makeReg(IceType_i32);
if (SrcReg->getType() == IceType_v4f32 ||
SrcReg->getType() == IceType_v4i32 ||
SrcReg->getType() == IceType_v16i8) {
_movmsk(T, SrcReg);
} else {
// TODO(capn): We could implement v8i16 sign mask using packsswb/pmovmskb
llvm::report_fatal_error("Invalid type for SignMask intrinsic");
}
_mov(Dest, T);
return;
}
default: // UnknownIntrinsic default: // UnknownIntrinsic
Func->setError("Unexpected intrinsic"); Func->setError("Unexpected intrinsic");
return; return;
......
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