emitIAS for cvtt?.*2.*
BUG=none
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/640603002
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index e2d39c3..fd1f80d 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -230,8 +230,8 @@
}
InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source,
- bool Trunc)
- : InstX8632(Func, InstX8632::Cvt, 1, Dest), Trunc(Trunc) {
+ CvtVariant Variant)
+ : InstX8632(Func, InstX8632::Cvt, 1, Dest), Variant(Variant) {
addSource(Source);
}
@@ -647,6 +647,35 @@
emitIASBytes(Str, Asm, StartPosition);
}
+template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t),
+ SReg_t (*srcEnc)(int32_t)>
+void emitIASCastRegOp(
+ const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src,
+ const x86::AssemblerX86::CastEmitterRegOp<DReg_t, SReg_t> Emitter) {
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+ intptr_t StartPosition = Asm->GetPosition();
+ assert(Dest->hasReg());
+ DReg_t DestReg = destEnc(Dest->getRegNum());
+ if (const Variable *SrcVar = llvm::dyn_cast<Variable>(Src)) {
+ if (SrcVar->hasReg()) {
+ SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
+ (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg);
+ } else {
+ x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget())
+ ->stackVarToAsmOperand(SrcVar);
+ (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr);
+ }
+ } else if (const OperandX8632Mem *Mem =
+ llvm::dyn_cast<OperandX8632Mem>(Src)) {
+ x86::Address SrcAddr = Mem->toAsmAddress(Asm);
+ (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcAddr);
+ } else {
+ llvm_unreachable("Unexpected operand type");
+ }
+ Ostream &Str = Func->getContext()->getStrEmit();
+ emitIASBytes(Str, Asm, StartPosition);
+}
+
void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest,
const Operand *Src,
const x86::AssemblerX86::XmmEmitterMovOps Emitter) {
@@ -1407,7 +1436,7 @@
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1);
Str << "\tcvt";
- if (Trunc)
+ if (isTruncating())
Str << "t";
Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
<< TypeX8632Attributes[getDest()->getType()].CvtString << "\t";
@@ -1417,11 +1446,70 @@
Str << "\n";
}
+void InstX8632Cvt::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 1);
+ const Variable *Dest = getDest();
+ const Operand *Src = getSrc(0);
+ Type DestTy = Dest->getType();
+ Type SrcTy = Src->getType();
+ switch (Variant) {
+ case Si2ss: {
+ assert(isScalarIntegerType(SrcTy));
+ assert(typeWidthInBytes(SrcTy) <= 4);
+ assert(isScalarFloatingType(DestTy));
+ static const x86::AssemblerX86::CastEmitterRegOp<
+ RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = {
+ &x86::AssemblerX86::cvtsi2ss, &x86::AssemblerX86::cvtsi2ss};
+ emitIASCastRegOp<RegX8632::XmmRegister, RegX8632::GPRRegister,
+ RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>(
+ Func, DestTy, Dest, Src, Emitter);
+ return;
+ }
+ case Tss2si: {
+ assert(isScalarFloatingType(SrcTy));
+ assert(isScalarIntegerType(DestTy));
+ assert(typeWidthInBytes(DestTy) <= 4);
+ static const x86::AssemblerX86::CastEmitterRegOp<
+ RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = {
+ &x86::AssemblerX86::cvttss2si, &x86::AssemblerX86::cvttss2si};
+ emitIASCastRegOp<RegX8632::GPRRegister, RegX8632::XmmRegister,
+ RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>(
+ Func, SrcTy, Dest, Src, Emitter);
+ return;
+ }
+ case Float2float: {
+ assert(isScalarFloatingType(SrcTy));
+ assert(isScalarFloatingType(DestTy));
+ assert(DestTy != SrcTy);
+ static const x86::AssemblerX86::XmmEmitterRegOp Emitter = {
+ &x86::AssemblerX86::cvtfloat2float, &x86::AssemblerX86::cvtfloat2float};
+ emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
+ return;
+ }
+ case Dq2ps: {
+ assert(isVectorIntegerType(SrcTy));
+ assert(isVectorFloatingType(DestTy));
+ static const x86::AssemblerX86::XmmEmitterRegOp Emitter = {
+ &x86::AssemblerX86::cvtdq2ps, &x86::AssemblerX86::cvtdq2ps};
+ emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
+ return;
+ }
+ case Tps2dq: {
+ assert(isVectorFloatingType(SrcTy));
+ assert(isVectorIntegerType(DestTy));
+ static const x86::AssemblerX86::XmmEmitterRegOp Emitter = {
+ &x86::AssemblerX86::cvttps2dq, &x86::AssemblerX86::cvttps2dq};
+ emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
+ return;
+ }
+ }
+}
+
void InstX8632Cvt::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
dumpDest(Func);
Str << " = cvt";
- if (Trunc)
+ if (isTruncating())
Str << "t";
Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
<< TypeX8632Attributes[getDest()->getType()].CvtString << " ";
diff --git a/src/IceInstX8632.h b/src/IceInstX8632.h
index eb133c2..abce706 100644
--- a/src/IceInstX8632.h
+++ b/src/IceInstX8632.h
@@ -1109,18 +1109,21 @@
// operand needs to be done separately.
class InstX8632Cvt : public InstX8632 {
public:
+ enum CvtVariant { Si2ss, Tss2si, Float2float, Dq2ps, Tps2dq };
static InstX8632Cvt *create(Cfg *Func, Variable *Dest, Operand *Source,
- bool Trunc) {
+ CvtVariant Variant) {
return new (Func->allocate<InstX8632Cvt>())
- InstX8632Cvt(Func, Dest, Source, Trunc);
+ InstX8632Cvt(Func, Dest, Source, Variant);
}
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 *Inst) { return isClassof(Inst, Cvt); }
+ bool isTruncating() const { return Variant == Tss2si || Variant == Tps2dq; }
private:
- bool Trunc;
- InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, bool Trunc);
+ CvtVariant Variant;
+ InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, CvtVariant Variant);
InstX8632Cvt(const InstX8632Cvt &) = delete;
InstX8632Cvt &operator=(const InstX8632Cvt &) = delete;
~InstX8632Cvt() override {}
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index 343113c..eb41b84 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -2058,7 +2058,7 @@
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
// t1 = cvt Src0RM; Dest = t1
Variable *T = makeReg(Dest->getType());
- _cvt(T, Src0RM);
+ _cvt(T, Src0RM, InstX8632Cvt::Float2float);
_mov(Dest, T);
break;
}
@@ -2068,7 +2068,7 @@
Inst->getSrc(0)->getType() == IceType_v4f32);
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Variable *T = makeReg(Dest->getType());
- _cvtt(T, Src0RM);
+ _cvt(T, Src0RM, InstX8632Cvt::Tps2dq);
_movp(Dest, T);
} else if (Dest->getType() == IceType_i64) {
// Use a helper for converting floating-point values to 64-bit
@@ -2091,7 +2091,7 @@
// t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type
Variable *T_1 = makeReg(IceType_i32);
Variable *T_2 = makeReg(Dest->getType());
- _cvtt(T_1, Src0RM);
+ _cvt(T_1, Src0RM, InstX8632Cvt::Tss2si);
_mov(T_2, T_1); // T_1 and T_2 may have different integer types
if (Dest->getType() == IceType_i1)
_and(T_2, Ctx->getConstantInt32(IceType_i1, 1));
@@ -2127,7 +2127,7 @@
// t1.i32 = cvt Src0RM; t2.dest_type = t1; Dest = t2.dest_type
Variable *T_1 = makeReg(IceType_i32);
Variable *T_2 = makeReg(Dest->getType());
- _cvtt(T_1, Src0RM);
+ _cvt(T_1, Src0RM, InstX8632Cvt::Tss2si);
_mov(T_2, T_1); // T_1 and T_2 may have different integer types
if (Dest->getType() == IceType_i1)
_and(T_2, Ctx->getConstantInt32(IceType_i1, 1));
@@ -2140,7 +2140,7 @@
Inst->getSrc(0)->getType() == IceType_v4i32);
Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem);
Variable *T = makeReg(Dest->getType());
- _cvt(T, Src0RM);
+ _cvt(T, Src0RM, InstX8632Cvt::Dq2ps);
_movp(Dest, T);
} else if (Inst->getSrc(0)->getType() == IceType_i64) {
// Use a helper for x86-32.
@@ -2163,7 +2163,7 @@
_mov(T_1, Src0RM);
else
_movsx(T_1, Src0RM);
- _cvt(T_2, T_1);
+ _cvt(T_2, T_1, InstX8632Cvt::Si2ss);
_mov(Dest, T_2);
}
break;
@@ -2202,7 +2202,7 @@
_mov(T_1, Src0RM);
else
_movzx(T_1, Src0RM);
- _cvt(T_2, T_1);
+ _cvt(T_2, T_1, InstX8632Cvt::Si2ss);
_mov(Dest, T_2);
}
break;
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index 271d4a2..82a8208 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -256,13 +256,8 @@
Context.insert(InstFakeDef::create(Func, Edx));
Context.insert(InstFakeDef::create(Func, Eax));
}
- void _cvt(Variable *Dest, Operand *Src0) {
- const bool Trunc = false;
- Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Trunc));
- }
- void _cvtt(Variable *Dest, Operand *Src0) {
- const bool Trunc = true;
- Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Trunc));
+ void _cvt(Variable *Dest, Operand *Src0, InstX8632Cvt::CvtVariant Variant) {
+ Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Variant));
}
void _div(Variable *Dest, Operand *Src0, Operand *Src1) {
Context.insert(InstX8632Div::create(Func, Dest, Src0, Src1));
diff --git a/src/assembler_ia32.cpp b/src/assembler_ia32.cpp
index 6bcbb9a..bc59ca8 100644
--- a/src/assembler_ia32.cpp
+++ b/src/assembler_ia32.cpp
@@ -948,21 +948,6 @@
EmitXmmRegisterOperand(dst, dst);
}
-void AssemblerX86::cvtps2pd(XmmRegister dst, XmmRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0x0F);
- EmitUint8(0x5A);
- EmitXmmRegisterOperand(dst, src);
-}
-
-void AssemblerX86::cvtpd2ps(XmmRegister dst, XmmRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0x66);
- EmitUint8(0x0F);
- EmitUint8(0x5A);
- EmitXmmRegisterOperand(dst, src);
-}
-
void AssemblerX86::shufpd(XmmRegister dst, XmmRegister src,
const Immediate &imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
@@ -974,76 +959,89 @@
EmitUint8(imm.value());
}
-void AssemblerX86::cvtsi2ss(XmmRegister dst, GPRRegister src) {
+void AssemblerX86::cvtdq2ps(Type /* Ignore */, XmmRegister dst,
+ XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF3);
EmitUint8(0x0F);
- EmitUint8(0x2A);
- EmitOperand(dst, Operand(src));
-}
-
-void AssemblerX86::cvtsi2sd(XmmRegister dst, GPRRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF2);
- EmitUint8(0x0F);
- EmitUint8(0x2A);
- EmitOperand(dst, Operand(src));
-}
-
-void AssemblerX86::cvtss2si(GPRRegister dst, XmmRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF3);
- EmitUint8(0x0F);
- EmitUint8(0x2D);
+ EmitUint8(0x5B);
EmitXmmRegisterOperand(dst, src);
}
-void AssemblerX86::cvtss2sd(XmmRegister dst, XmmRegister src) {
+void AssemblerX86::cvtdq2ps(Type /* Ignore */, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0x0F);
+ EmitUint8(0x5B);
+ EmitOperand(dst, src);
+}
+
+void AssemblerX86::cvttps2dq(Type /* Ignore */, XmmRegister dst,
+ XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF3);
EmitUint8(0x0F);
+ EmitUint8(0x5B);
+ EmitXmmRegisterOperand(dst, src);
+}
+
+void AssemblerX86::cvttps2dq(Type /* Ignore */, XmmRegister dst,
+ const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0xF3);
+ EmitUint8(0x0F);
+ EmitUint8(0x5B);
+ EmitOperand(dst, src);
+}
+
+void AssemblerX86::cvtsi2ss(Type DestTy, XmmRegister dst, GPRRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(isFloat32Asserting32Or64(DestTy) ? 0xF3 : 0xF2);
+ EmitUint8(0x0F);
+ EmitUint8(0x2A);
+ EmitRegisterOperand(dst, src);
+}
+
+void AssemblerX86::cvtsi2ss(Type DestTy, XmmRegister dst, const Address &src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(isFloat32Asserting32Or64(DestTy) ? 0xF3 : 0xF2);
+ EmitUint8(0x0F);
+ EmitUint8(0x2A);
+ EmitOperand(dst, src);
+}
+
+void AssemblerX86::cvtfloat2float(Type SrcTy, XmmRegister dst,
+ XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ // ss2sd or sd2ss
+ EmitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
+ EmitUint8(0x0F);
EmitUint8(0x5A);
EmitXmmRegisterOperand(dst, src);
}
-void AssemblerX86::cvtsd2si(GPRRegister dst, XmmRegister src) {
+void AssemblerX86::cvtfloat2float(Type SrcTy, XmmRegister dst,
+ const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF2);
- EmitUint8(0x0F);
- EmitUint8(0x2D);
- EmitXmmRegisterOperand(dst, src);
-}
-
-void AssemblerX86::cvttss2si(GPRRegister dst, XmmRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF3);
- EmitUint8(0x0F);
- EmitUint8(0x2C);
- EmitXmmRegisterOperand(dst, src);
-}
-
-void AssemblerX86::cvttsd2si(GPRRegister dst, XmmRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF2);
- EmitUint8(0x0F);
- EmitUint8(0x2C);
- EmitXmmRegisterOperand(dst, src);
-}
-
-void AssemblerX86::cvtsd2ss(XmmRegister dst, XmmRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF2);
+ EmitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x5A);
+ EmitOperand(dst, src);
+}
+
+void AssemblerX86::cvttss2si(Type SrcTy, GPRRegister dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
+ EmitUint8(0x0F);
+ EmitUint8(0x2C);
EmitXmmRegisterOperand(dst, src);
}
-void AssemblerX86::cvtdq2pd(XmmRegister dst, XmmRegister src) {
+void AssemblerX86::cvttss2si(Type SrcTy, GPRRegister dst, const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF3);
+ EmitUint8(isFloat32Asserting32Or64(SrcTy) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
- EmitUint8(0xE6);
- EmitXmmRegisterOperand(dst, src);
+ EmitUint8(0x2C);
+ EmitOperand(dst, src);
}
void AssemblerX86::ucomiss(Type Ty, XmmRegister a, XmmRegister b) {
diff --git a/src/assembler_ia32.h b/src/assembler_ia32.h
index 0080f33..22ecb6e 100644
--- a/src/assembler_ia32.h
+++ b/src/assembler_ia32.h
@@ -397,6 +397,15 @@
TypedEmitXmmImm XmmImm;
};
+ // Cross Xmm/GPR cast instructions.
+ template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp {
+ typedef void (AssemblerX86::*TypedEmitRegs)(Type, DReg_t, SReg_t);
+ typedef void (AssemblerX86::*TypedEmitAddr)(Type, DReg_t, const Address &);
+
+ TypedEmitRegs RegReg;
+ TypedEmitAddr RegAddr;
+ };
+
/*
* Emit Machine Instructions.
*/
@@ -537,23 +546,22 @@
void minpd(XmmRegister dst, XmmRegister src);
void maxpd(XmmRegister dst, XmmRegister src);
void sqrtpd(XmmRegister dst);
- void cvtps2pd(XmmRegister dst, XmmRegister src);
- void cvtpd2ps(XmmRegister dst, XmmRegister src);
void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask);
- void cvtsi2ss(XmmRegister dst, GPRRegister src);
- void cvtsi2sd(XmmRegister dst, GPRRegister src);
+ void cvtdq2ps(Type, XmmRegister dst, XmmRegister src);
+ void cvtdq2ps(Type, XmmRegister dst, const Address &src);
- void cvtss2si(GPRRegister dst, XmmRegister src);
- void cvtss2sd(XmmRegister dst, XmmRegister src);
+ void cvttps2dq(Type, XmmRegister dst, XmmRegister src);
+ void cvttps2dq(Type, XmmRegister dst, const Address &src);
- void cvtsd2si(GPRRegister dst, XmmRegister src);
- void cvtsd2ss(XmmRegister dst, XmmRegister src);
+ void cvtsi2ss(Type DestTy, XmmRegister dst, GPRRegister src);
+ void cvtsi2ss(Type DestTy, XmmRegister dst, const Address &src);
- void cvttss2si(GPRRegister dst, XmmRegister src);
- void cvttsd2si(GPRRegister dst, XmmRegister src);
+ void cvtfloat2float(Type SrcTy, XmmRegister dst, XmmRegister src);
+ void cvtfloat2float(Type SrcTy, XmmRegister dst, const Address &src);
- void cvtdq2pd(XmmRegister dst, XmmRegister src);
+ void cvttss2si(Type SrcTy, GPRRegister dst, XmmRegister src);
+ void cvttss2si(Type SrcTy, GPRRegister dst, const Address &src);
void ucomiss(Type Ty, XmmRegister a, XmmRegister b);
void ucomiss(Type Ty, XmmRegister a, const Address &b);