Commit c31e2ed7 by John Porto

Implements int2fp, fp2int, and fp2fp conversions for ARM32.

64-bit ints (and vectors) are future work. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076 R=kschimpf@google.com, stichnot@chromium.org Review URL: https://codereview.chromium.org/1330933002 .
parent 6ef79494
...@@ -377,6 +377,13 @@ InstARM32Umull::InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, ...@@ -377,6 +377,13 @@ InstARM32Umull::InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi,
addSource(Src1); addSource(Src1);
} }
InstARM32Vcvt::InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src,
VcvtVariant Variant, CondARM32::Cond Predicate)
: InstARM32Pred(Func, InstARM32::Vcvt, 1, Dest, Predicate),
Variant(Variant) {
addSource(Src);
}
// ======================== Dump routines ======================== // // ======================== Dump routines ======================== //
// Two-addr ops // Two-addr ops
...@@ -909,6 +916,63 @@ void InstARM32Umull::dump(const Cfg *Func) const { ...@@ -909,6 +916,63 @@ void InstARM32Umull::dump(const Cfg *Func) const {
dumpSources(Func); dumpSources(Func);
} }
namespace {
const char *vcvtVariantSuffix(const InstARM32Vcvt::VcvtVariant Variant) {
switch (Variant) {
case InstARM32Vcvt::S2si:
return ".s32.f32";
case InstARM32Vcvt::S2ui:
return ".u32.f32";
case InstARM32Vcvt::Si2s:
return ".f32.s32";
case InstARM32Vcvt::Ui2s:
return ".f32.u32";
case InstARM32Vcvt::D2si:
return ".s32.f64";
case InstARM32Vcvt::D2ui:
return ".u32.f64";
case InstARM32Vcvt::Si2d:
return ".f64.s32";
case InstARM32Vcvt::Ui2d:
return ".f64.u32";
case InstARM32Vcvt::S2d:
return ".f64.f32";
case InstARM32Vcvt::D2s:
return ".f32.f64";
}
llvm::report_fatal_error("Invalid VcvtVariant enum.");
}
} // end of anonymous namespace
void InstARM32Vcvt::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1);
assert(getDest()->hasReg());
Str << "\t"
<< "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << "\t";
getDest()->emit(Func);
Str << ", ";
getSrc(0)->emit(Func);
}
void InstARM32Vcvt::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 1);
(void)Func;
llvm_unreachable("Not yet implemented");
}
void InstARM32Vcvt::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
dumpDest(Func);
Str << " = "
<< "vcvt" << getPredicate() << vcvtVariantSuffix(Variant) << " ";
dumpSources(Func);
}
void OperandARM32Mem::emit(const Cfg *Func) const { void OperandARM32Mem::emit(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
......
...@@ -322,6 +322,7 @@ public: ...@@ -322,6 +322,7 @@ public:
Umull, Umull,
Uxt, Uxt,
Vadd, Vadd,
Vcvt,
Vdiv, Vdiv,
Vldr, Vldr,
Vmov, Vmov,
...@@ -1093,6 +1094,31 @@ private: ...@@ -1093,6 +1094,31 @@ private:
Variable *DestHi; Variable *DestHi;
}; };
/// Handles fp2int, int2fp, and fp2fp conversions.
class InstARM32Vcvt final : public InstARM32Pred {
InstARM32Vcvt() = delete;
InstARM32Vcvt(const InstARM32Vcvt &) = delete;
InstARM32Vcvt &operator=(const InstARM32Vcvt &) = delete;
public:
enum VcvtVariant { S2si, S2ui, Si2s, Ui2s, D2si, D2ui, Si2d, Ui2d, S2d, D2s };
static InstARM32Vcvt *create(Cfg *Func, Variable *Dest, Variable *Src,
VcvtVariant Variant, CondARM32::Cond Predicate) {
return new (Func->allocate<InstARM32Vcvt>())
InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
}
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, Vcvt); }
private:
InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, VcvtVariant Variant,
CondARM32::Cond Predicate);
const VcvtVariant Variant;
};
// Declare partial template specializations of emit() methods that // Declare partial template specializations of emit() methods that
// already have default implementations. Without this, there is the // already have default implementations. Without this, there is the
// possibility of ODR violations and link errors. // possibility of ODR violations and link errors.
......
...@@ -34,14 +34,17 @@ namespace Ice { ...@@ -34,14 +34,17 @@ namespace Ice {
namespace { namespace {
void UnimplementedError(const ClFlags &Flags) { // UnimplementedError is defined as a macro so that we can get actual line
if (!Flags.getSkipUnimplemented()) { // numbers.
// Use llvm_unreachable instead of report_fatal_error, which gives better #define UnimplementedError(Flags) \
// stack traces. do { \
llvm_unreachable("Not yet implemented"); if (!static_cast<const ClFlags &>(Flags).getSkipUnimplemented()) { \
abort(); /* Use llvm_unreachable instead of report_fatal_error, which gives \
} better stack traces. */ \
} llvm_unreachable("Not yet implemented"); \
abort(); \
} \
} while (0)
// The following table summarizes the logic for lowering the icmp instruction // The following table summarizes the logic for lowering the icmp instruction
// for i32 and narrower types. Each icmp condition has a clear mapping to an // for i32 and narrower types. Each icmp condition has a clear mapping to an
...@@ -2075,25 +2078,97 @@ void TargetARM32::lowerCast(const InstCast *Inst) { ...@@ -2075,25 +2078,97 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
break; break;
} }
case InstCast::Fptrunc: case InstCast::Fptrunc:
UnimplementedError(Func->getContext()->getFlags());
break;
case InstCast::Fpext: { case InstCast::Fpext: {
UnimplementedError(Func->getContext()->getFlags()); // fptrunc: dest.f32 = fptrunc src0.fp64
// fpext: dest.f64 = fptrunc src0.fp32
const bool IsTrunc = CastKind == InstCast::Fptrunc;
if (isVectorType(Dest->getType())) {
UnimplementedError(Func->getContext()->getFlags());
break;
}
assert(Dest->getType() == (IsTrunc ? IceType_f32 : IceType_f64));
assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32));
Variable *Src0R = legalizeToReg(Src0);
Variable *T = makeReg(Dest->getType());
_vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d);
_mov(Dest, T);
break; break;
} }
case InstCast::Fptosi: case InstCast::Fptosi:
UnimplementedError(Func->getContext()->getFlags()); case InstCast::Fptoui: {
// Add a fake def to keep liveness consistent in the meantime. // fptosi:
Context.insert(InstFakeDef::create(Func, Dest)); // t1.fp = vcvt src0.fp
break; // t2.i32 = vmov t1.fp
case InstCast::Fptoui: // dest.int = conv t2.i32 @ Truncates the result if needed.
UnimplementedError(Func->getContext()->getFlags()); // fptoui:
// t1.fp = vcvt src0.fp
// t2.u32 = vmov t1.fp
// dest.uint = conv t2.u32 @ Truncates the result if needed.
if (isVectorType(Dest->getType())) {
UnimplementedError(Func->getContext()->getFlags());
break;
} else if (Dest->getType() == IceType_i64) {
UnimplementedError(Func->getContext()->getFlags());
break;
}
const bool DestIsSigned = CastKind == InstCast::Fptosi;
Variable *Src0R = legalizeToReg(Src0);
Variable *T_fp = makeReg(IceType_f32);
if (isFloat32Asserting32Or64(Src0->getType())) {
_vcvt(T_fp, Src0R,
DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui);
} else {
_vcvt(T_fp, Src0R,
DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui);
}
Variable *T = makeReg(IceType_i32);
_vmov(T, T_fp);
if (Dest->getType() != IceType_i32) {
Variable *T_1 = makeReg(Dest->getType());
lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T));
T = T_1;
}
_mov(Dest, T);
break; break;
}
case InstCast::Sitofp: case InstCast::Sitofp:
UnimplementedError(Func->getContext()->getFlags());
break;
case InstCast::Uitofp: { case InstCast::Uitofp: {
UnimplementedError(Func->getContext()->getFlags()); // sitofp:
// t1.i32 = sext src.int @ sign-extends src0 if needed.
// t2.fp32 = vmov t1.i32
// t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64
// uitofp:
// t1.i32 = zext src.int @ zero-extends src0 if needed.
// t2.fp32 = vmov t1.i32
// t3.fp = vcvt.{fp}.s32 @ fp is either f32 or f64
if (isVectorType(Dest->getType())) {
UnimplementedError(Func->getContext()->getFlags());
break;
} else if (Src0->getType() == IceType_i64) {
UnimplementedError(Func->getContext()->getFlags());
break;
}
const bool SourceIsSigned = CastKind == InstCast::Sitofp;
if (Src0->getType() != IceType_i32) {
Variable *Src0R_32 = makeReg(IceType_i32);
lowerCast(InstCast::create(Func, SourceIsSigned ? InstCast::Sext
: InstCast::Zext,
Src0R_32, Src0));
Src0 = Src0R_32;
}
Variable *Src0R = legalizeToReg(Src0);
Variable *Src0R_f32 = makeReg(IceType_f32);
_vmov(Src0R_f32, Src0R);
Src0R = Src0R_f32;
Variable *T = makeReg(Dest->getType());
if (isFloat32Asserting32Or64(Dest->getType())) {
_vcvt(T, Src0R,
SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s);
} else {
_vcvt(T, Src0R,
SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d);
}
_mov(Dest, T);
break; break;
} }
case InstCast::Bitcast: { case InstCast::Bitcast: {
......
...@@ -389,6 +389,10 @@ protected: ...@@ -389,6 +389,10 @@ protected:
void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) { void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert(InstARM32Vadd::create(Func, Dest, Src0, Src1)); Context.insert(InstARM32Vadd::create(Func, Dest, Src0, Src1));
} }
void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant,
CondARM32::Cond Pred = CondARM32::AL) {
Context.insert(InstARM32Vcvt::create(Func, Dest, Src, Variant, Pred));
}
void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1)); Context.insert(InstARM32Vdiv::create(Func, Dest, Src0, Src1));
} }
......
...@@ -6,6 +6,10 @@ ...@@ -6,6 +6,10 @@
; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s
; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 | FileCheck %s ; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 | FileCheck %s
; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
; RUN: --target arm32 -i %s --args -Om1 --skip-unimplemented \
; RUN: | %if --need=target_ARM32 --command FileCheck %s --check-prefix=ARM32
define internal float @fptrunc(double %a) { define internal float @fptrunc(double %a) {
entry: entry:
%conv = fptrunc double %a to float %conv = fptrunc double %a to float
...@@ -14,6 +18,8 @@ entry: ...@@ -14,6 +18,8 @@ entry:
; CHECK-LABEL: fptrunc ; CHECK-LABEL: fptrunc
; CHECK: cvtsd2ss ; CHECK: cvtsd2ss
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: fptrunc
; ARM32: vcvt.f32.f64 {{s[0-9]+}}, {{d[0-9]+}}
define internal double @fpext(float %a) { define internal double @fpext(float %a) {
entry: entry:
...@@ -23,6 +29,8 @@ entry: ...@@ -23,6 +29,8 @@ entry:
; CHECK-LABEL: fpext ; CHECK-LABEL: fpext
; CHECK: cvtss2sd ; CHECK: cvtss2sd
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: fpext
; ARM32: vcvt.f64.f32 {{d[0-9]+}}, {{s[0-9]+}}
define internal i64 @doubleToSigned64(double %a) { define internal i64 @doubleToSigned64(double %a) {
entry: entry:
...@@ -31,6 +39,8 @@ entry: ...@@ -31,6 +39,8 @@ entry:
} }
; CHECK-LABEL: doubleToSigned64 ; CHECK-LABEL: doubleToSigned64
; CHECK: call {{.*}} R_{{.*}} __Sz_fptosi_f64_i64 ; CHECK: call {{.*}} R_{{.*}} __Sz_fptosi_f64_i64
; ARM32-LABEL: doubleToSigned64
; TODO(jpp): implement this test.
define internal i64 @floatToSigned64(float %a) { define internal i64 @floatToSigned64(float %a) {
entry: entry:
...@@ -39,6 +49,8 @@ entry: ...@@ -39,6 +49,8 @@ entry:
} }
; CHECK-LABEL: floatToSigned64 ; CHECK-LABEL: floatToSigned64
; CHECK: call {{.*}} R_{{.*}} __Sz_fptosi_f32_i64 ; CHECK: call {{.*}} R_{{.*}} __Sz_fptosi_f32_i64
; ARM32-LABEL: floatToSigned64
; TODO(jpp): implement this test.
define internal i64 @doubleToUnsigned64(double %a) { define internal i64 @doubleToUnsigned64(double %a) {
entry: entry:
...@@ -47,6 +59,8 @@ entry: ...@@ -47,6 +59,8 @@ entry:
} }
; CHECK-LABEL: doubleToUnsigned64 ; CHECK-LABEL: doubleToUnsigned64
; CHECK: call {{.*}} R_{{.*}} __Sz_fptoui_f64_i64 ; CHECK: call {{.*}} R_{{.*}} __Sz_fptoui_f64_i64
; ARM32-LABEL: doubleToUnsigned64
; TODO(jpp): implement this test.
define internal i64 @floatToUnsigned64(float %a) { define internal i64 @floatToUnsigned64(float %a) {
entry: entry:
...@@ -55,6 +69,8 @@ entry: ...@@ -55,6 +69,8 @@ entry:
} }
; CHECK-LABEL: floatToUnsigned64 ; CHECK-LABEL: floatToUnsigned64
; CHECK: call {{.*}} R_{{.*}} __Sz_fptoui_f32_i64 ; CHECK: call {{.*}} R_{{.*}} __Sz_fptoui_f32_i64
; ARM32-LABEL: floatToUnsigned64
; TODO(jpp): implement this test.
define internal i32 @doubleToSigned32(double %a) { define internal i32 @doubleToSigned32(double %a) {
entry: entry:
...@@ -63,6 +79,9 @@ entry: ...@@ -63,6 +79,9 @@ entry:
} }
; CHECK-LABEL: doubleToSigned32 ; CHECK-LABEL: doubleToSigned32
; CHECK: cvttsd2si ; CHECK: cvttsd2si
; ARM32-LABEL: doubleToSigned32
; ARM32-DAG: vcvt.s32.f64 [[REG:s[0-9]*]], {{d[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
define internal i32 @doubleToSigned32Const() { define internal i32 @doubleToSigned32Const() {
entry: entry:
...@@ -71,6 +90,12 @@ entry: ...@@ -71,6 +90,12 @@ entry:
} }
; CHECK-LABEL: doubleToSigned32Const ; CHECK-LABEL: doubleToSigned32Const
; CHECK: cvttsd2si ; CHECK: cvttsd2si
; ARM32-LABEL: doubleToSigned32Const
; ARM32-DAG: movw [[ADDR:r[0-9]+]], #:lower16:.L$
; ARM32-DAG: movt [[ADDR]], #:upper16:.L$
; ARM32-DAG: vldr [[DREG:d[0-9]+]], {{\[}}[[ADDR]], #0{{\]}}
; ARM32-DAG: vcvt.s32.f64 [[REG:s[0-9]+]], [[DREG]]
; ARM32-DAF: vmov {{r[0-9]+}}, [[REG]]
define internal i32 @floatToSigned32(float %a) { define internal i32 @floatToSigned32(float %a) {
entry: entry:
...@@ -79,6 +104,9 @@ entry: ...@@ -79,6 +104,9 @@ entry:
} }
; CHECK-LABEL: floatToSigned32 ; CHECK-LABEL: floatToSigned32
; CHECK: cvttss2si ; CHECK: cvttss2si
; ARM32-LABEL: floatToSigned32
; ARM32-DAG: vcvt.s32.f32 [[REG:s[0-9]+]], {{s[0-9]+}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
define internal i32 @doubleToUnsigned32(double %a) { define internal i32 @doubleToUnsigned32(double %a) {
entry: entry:
...@@ -87,6 +115,9 @@ entry: ...@@ -87,6 +115,9 @@ entry:
} }
; CHECK-LABEL: doubleToUnsigned32 ; CHECK-LABEL: doubleToUnsigned32
; CHECK: call {{.*}} R_{{.*}} __Sz_fptoui_f64_i32 ; CHECK: call {{.*}} R_{{.*}} __Sz_fptoui_f64_i32
; ARM32-LABEL: doubleToUnsigned32
; ARM32-DAG: vcvt.u32.f64 [[REG:s[0-9]+]], {{d[0-9]+}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
define internal i32 @floatToUnsigned32(float %a) { define internal i32 @floatToUnsigned32(float %a) {
entry: entry:
...@@ -95,6 +126,9 @@ entry: ...@@ -95,6 +126,9 @@ entry:
} }
; CHECK-LABEL: floatToUnsigned32 ; CHECK-LABEL: floatToUnsigned32
; CHECK: call {{.*}} R_{{.*}} __Sz_fptoui_f32_i32 ; CHECK: call {{.*}} R_{{.*}} __Sz_fptoui_f32_i32
; ARM32-LABEL: floatToUnsigned32
; ARM32-DAG: vcvt.u32.f32 [[REG:s[0-9]+]], {{s[0-9]+}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
define internal i32 @doubleToSigned16(double %a) { define internal i32 @doubleToSigned16(double %a) {
entry: entry:
...@@ -105,6 +139,10 @@ entry: ...@@ -105,6 +139,10 @@ entry:
; CHECK-LABEL: doubleToSigned16 ; CHECK-LABEL: doubleToSigned16
; CHECK: cvttsd2si ; CHECK: cvttsd2si
; CHECK: movsx ; CHECK: movsx
; ARM32-LABEL: doubleToSigned16
; ARM32-DAG: vcvt.s32.f64 [[REG:s[0-9]*]], {{d[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
; ARM32: sxth
define internal i32 @floatToSigned16(float %a) { define internal i32 @floatToSigned16(float %a) {
entry: entry:
...@@ -115,6 +153,10 @@ entry: ...@@ -115,6 +153,10 @@ entry:
; CHECK-LABEL: floatToSigned16 ; CHECK-LABEL: floatToSigned16
; CHECK: cvttss2si ; CHECK: cvttss2si
; CHECK: movsx ; CHECK: movsx
; ARM32-LABEL: floatToSigned16
; ARM32-DAG: vcvt.s32.f32 [[REG:s[0-9]*]], {{s[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
; ARM32: sxth
define internal i32 @doubleToUnsigned16(double %a) { define internal i32 @doubleToUnsigned16(double %a) {
entry: entry:
...@@ -125,6 +167,10 @@ entry: ...@@ -125,6 +167,10 @@ entry:
; CHECK-LABEL: doubleToUnsigned16 ; CHECK-LABEL: doubleToUnsigned16
; CHECK: cvttsd2si ; CHECK: cvttsd2si
; CHECK: movzx ; CHECK: movzx
; ARM32-LABEL: doubleToUnsigned16
; ARM32-DAG: vcvt.u32.f64 [[REG:s[0-9]*]], {{d[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
; ARM32: uxth
define internal i32 @floatToUnsigned16(float %a) { define internal i32 @floatToUnsigned16(float %a) {
entry: entry:
...@@ -135,6 +181,10 @@ entry: ...@@ -135,6 +181,10 @@ entry:
; CHECK-LABEL: floatToUnsigned16 ; CHECK-LABEL: floatToUnsigned16
; CHECK: cvttss2si ; CHECK: cvttss2si
; CHECK: movzx ; CHECK: movzx
; ARM32-LABEL: floatToUnsigned16
; ARM32-DAG: vcvt.u32.f32 [[REG:s[0-9]*]], {{s[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
; ARM32: uxth
define internal i32 @doubleToSigned8(double %a) { define internal i32 @doubleToSigned8(double %a) {
entry: entry:
...@@ -145,6 +195,10 @@ entry: ...@@ -145,6 +195,10 @@ entry:
; CHECK-LABEL: doubleToSigned8 ; CHECK-LABEL: doubleToSigned8
; CHECK: cvttsd2si ; CHECK: cvttsd2si
; CHECK: movsx ; CHECK: movsx
; ARM32-LABEL: doubleToSigned8
; ARM32-DAG: vcvt.s32.f64 [[REG:s[0-9]*]], {{d[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
; ARM32: sxtb
define internal i32 @floatToSigned8(float %a) { define internal i32 @floatToSigned8(float %a) {
entry: entry:
...@@ -155,6 +209,10 @@ entry: ...@@ -155,6 +209,10 @@ entry:
; CHECK-LABEL: floatToSigned8 ; CHECK-LABEL: floatToSigned8
; CHECK: cvttss2si ; CHECK: cvttss2si
; CHECK: movsx ; CHECK: movsx
; ARM32-LABEL: floatToSigned8
; ARM32-DAG: vcvt.s32.f32 [[REG:s[0-9]*]], {{s[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
; ARM32: sxtb
define internal i32 @doubleToUnsigned8(double %a) { define internal i32 @doubleToUnsigned8(double %a) {
entry: entry:
...@@ -165,6 +223,10 @@ entry: ...@@ -165,6 +223,10 @@ entry:
; CHECK-LABEL: doubleToUnsigned8 ; CHECK-LABEL: doubleToUnsigned8
; CHECK: cvttsd2si ; CHECK: cvttsd2si
; CHECK: movzx ; CHECK: movzx
; ARM32-LABEL: doubleToUnsigned8
; ARM32-DAG: vcvt.u32.f64 [[REG:s[0-9]*]], {{d[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
; ARM32: uxtb
define internal i32 @floatToUnsigned8(float %a) { define internal i32 @floatToUnsigned8(float %a) {
entry: entry:
...@@ -175,6 +237,10 @@ entry: ...@@ -175,6 +237,10 @@ entry:
; CHECK-LABEL: floatToUnsigned8 ; CHECK-LABEL: floatToUnsigned8
; CHECK: cvttss2si ; CHECK: cvttss2si
; CHECK: movzx ; CHECK: movzx
; ARM32-LABEL: floatToUnsigned8
; ARM32-DAG: vcvt.u32.f32 [[REG:s[0-9]*]], {{s[0-9]*}}
; ARM32-DAG: vmov {{r[0-9]+}}, [[REG]]
; ARM32: uxtb
define internal i32 @doubleToUnsigned1(double %a) { define internal i32 @doubleToUnsigned1(double %a) {
entry: entry:
...@@ -185,6 +251,12 @@ entry: ...@@ -185,6 +251,12 @@ entry:
; CHECK-LABEL: doubleToUnsigned1 ; CHECK-LABEL: doubleToUnsigned1
; CHECK: cvttsd2si ; CHECK: cvttsd2si
; CHECK: and eax,0x1 ; CHECK: and eax,0x1
; ARM32-LABEL: doubleToUnsigned1
; ARM32-DAG: vcvt.u32.f64 [[REG:s[0-9]*]], {{d[0-9]*}}
; ARM32-DAG: vmov [[RES:r[0-9]+]], [[REG]]
; ARM32-DAG: and {{r[0-9]+}}, [[RES]], #1
; ARM32-NOT: uxth
; ARM32-NOT: uxtb
define internal i32 @floatToUnsigned1(float %a) { define internal i32 @floatToUnsigned1(float %a) {
entry: entry:
...@@ -195,6 +267,12 @@ entry: ...@@ -195,6 +267,12 @@ entry:
; CHECK-LABEL: floatToUnsigned1 ; CHECK-LABEL: floatToUnsigned1
; CHECK: cvttss2si ; CHECK: cvttss2si
; CHECK: and eax,0x1 ; CHECK: and eax,0x1
; ARM32-LABEL: floatToUnsigned1
; ARM32-DAG: vcvt.u32.f32 [[REG:s[0-9]*]], {{s[0-9]*}}
; ARM32-DAG: vmov [[RES:r[0-9]+]], [[REG]]
; ARM32-DAG: and {{r[0-9]+}}, [[RES]], #1
; ARM32-NOT: uxth
; ARM32-NOT: uxtb
define internal double @signed64ToDouble(i64 %a) { define internal double @signed64ToDouble(i64 %a) {
entry: entry:
...@@ -204,6 +282,8 @@ entry: ...@@ -204,6 +282,8 @@ entry:
; CHECK-LABEL: signed64ToDouble ; CHECK-LABEL: signed64ToDouble
; CHECK: call {{.*}} R_{{.*}} __Sz_sitofp_i64_f64 ; CHECK: call {{.*}} R_{{.*}} __Sz_sitofp_i64_f64
; CHECK: fstp QWORD ; CHECK: fstp QWORD
; ARM32-LABEL: signed64ToDouble
; TODO(jpp): implement this test.
define internal float @signed64ToFloat(i64 %a) { define internal float @signed64ToFloat(i64 %a) {
entry: entry:
...@@ -213,6 +293,8 @@ entry: ...@@ -213,6 +293,8 @@ entry:
; CHECK-LABEL: signed64ToFloat ; CHECK-LABEL: signed64ToFloat
; CHECK: call {{.*}} R_{{.*}} __Sz_sitofp_i64_f32 ; CHECK: call {{.*}} R_{{.*}} __Sz_sitofp_i64_f32
; CHECK: fstp DWORD ; CHECK: fstp DWORD
; ARM32-LABEL: signed64ToFloat
; TODO(jpp): implement this test.
define internal double @unsigned64ToDouble(i64 %a) { define internal double @unsigned64ToDouble(i64 %a) {
entry: entry:
...@@ -222,6 +304,8 @@ entry: ...@@ -222,6 +304,8 @@ entry:
; CHECK-LABEL: unsigned64ToDouble ; CHECK-LABEL: unsigned64ToDouble
; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i64_f64 ; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i64_f64
; CHECK: fstp ; CHECK: fstp
; ARM32-LABEL: unsigned64ToDouble
; TODO(jpp): implement this test.
define internal float @unsigned64ToFloat(i64 %a) { define internal float @unsigned64ToFloat(i64 %a) {
entry: entry:
...@@ -231,17 +315,21 @@ entry: ...@@ -231,17 +315,21 @@ entry:
; CHECK-LABEL: unsigned64ToFloat ; CHECK-LABEL: unsigned64ToFloat
; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i64_f32 ; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i64_f32
; CHECK: fstp ; CHECK: fstp
; ARM32-LABEL: unsigned64ToFloat
; TODO(jpp): implement this test.
define internal double @unsigned64ToDoubleConst() { define internal double @unsigned64ToDoubleConst() {
entry: entry:
%conv = uitofp i64 12345678901234 to double %conv = uitofp i64 12345678901234 to double
ret double %conv ret double %conv
} }
; CHECK-LABEL: unsigned64ToDouble ; CHECK-LABEL: unsigned64ToDoubleConst
; CHECK: mov DWORD PTR [esp+0x4],0xb3a ; CHECK: mov DWORD PTR [esp+0x4],0xb3a
; CHECK: mov DWORD PTR [esp],0x73ce2ff2 ; CHECK: mov DWORD PTR [esp],0x73ce2ff2
; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i64_f64 ; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i64_f64
; CHECK: fstp ; CHECK: fstp
; ARM32-LABEL: unsigned64ToDoubleConst
; TODO(jpp): implement this test.
define internal double @signed32ToDouble(i32 %a) { define internal double @signed32ToDouble(i32 %a) {
entry: entry:
...@@ -251,6 +339,9 @@ entry: ...@@ -251,6 +339,9 @@ entry:
; CHECK-LABEL: signed32ToDouble ; CHECK-LABEL: signed32ToDouble
; CHECK: cvtsi2sd ; CHECK: cvtsi2sd
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: signed32ToDouble
; ARM32-DAG: vmov [[SRC:s[0-9]+]], {{r[0-9]+}}
; ARM32-DAG: vcvt.f64.s32 {{d[0-9]+}}, [[SRC]]
define internal double @signed32ToDoubleConst() { define internal double @signed32ToDoubleConst() {
entry: entry:
...@@ -260,6 +351,10 @@ entry: ...@@ -260,6 +351,10 @@ entry:
; CHECK-LABEL: signed32ToDoubleConst ; CHECK-LABEL: signed32ToDoubleConst
; CHECK: cvtsi2sd {{.*[^1]}} ; CHECK: cvtsi2sd {{.*[^1]}}
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: signed32ToDoubleConst
; ARM32-DAG: movw [[CONST:r[0-9]+]], #123
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[CONST]]
; ARM32-DAG: vcvt.f64.s32 {{d[0-9]+}}, [[SRC]]
define internal float @signed32ToFloat(i32 %a) { define internal float @signed32ToFloat(i32 %a) {
entry: entry:
...@@ -269,6 +364,9 @@ entry: ...@@ -269,6 +364,9 @@ entry:
; CHECK-LABEL: signed32ToFloat ; CHECK-LABEL: signed32ToFloat
; CHECK: cvtsi2ss ; CHECK: cvtsi2ss
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: signed32ToFloat
; ARM32-DAG: vmov [[SRC:s[0-9]+]], {{r[0-9]+}}
; ARM32-DAG: vcvt.f32.s32 {{s[0-9]+}}, [[SRC]]
define internal double @unsigned32ToDouble(i32 %a) { define internal double @unsigned32ToDouble(i32 %a) {
entry: entry:
...@@ -278,6 +376,9 @@ entry: ...@@ -278,6 +376,9 @@ entry:
; CHECK-LABEL: unsigned32ToDouble ; CHECK-LABEL: unsigned32ToDouble
; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i32_f64 ; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i32_f64
; CHECK: fstp QWORD ; CHECK: fstp QWORD
; ARM32-LABEL: unsigned32ToDouble
; ARM32-DAG: vmov [[SRC:s[0-9]+]], {{r[0-9]+}}
; ARM32-DAG: vcvt.f64.u32 {{d[0-9]+}}, [[SRC]]
define internal float @unsigned32ToFloat(i32 %a) { define internal float @unsigned32ToFloat(i32 %a) {
entry: entry:
...@@ -287,6 +388,9 @@ entry: ...@@ -287,6 +388,9 @@ entry:
; CHECK-LABEL: unsigned32ToFloat ; CHECK-LABEL: unsigned32ToFloat
; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i32_f32 ; CHECK: call {{.*}} R_{{.*}} __Sz_uitofp_i32_f32
; CHECK: fstp DWORD ; CHECK: fstp DWORD
; ARM32-LABEL: unsigned32ToFloat
; ARM32-DAG: vmov [[SRC:s[0-9]+]], {{r[0-9]+}}
; ARM32-DAG: vcvt.f32.u32 {{s[0-9]+}}, [[SRC]]
define internal double @signed16ToDouble(i32 %a) { define internal double @signed16ToDouble(i32 %a) {
entry: entry:
...@@ -297,6 +401,10 @@ entry: ...@@ -297,6 +401,10 @@ entry:
; CHECK-LABEL: signed16ToDouble ; CHECK-LABEL: signed16ToDouble
; CHECK: cvtsi2sd ; CHECK: cvtsi2sd
; CHECK: fld QWORD ; CHECK: fld QWORD
; ARM32-LABEL: signed16ToDouble
; ARM32-DAG: sxth [[INT:r[0-9]+]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f64.s32 {{d[0-9]+}}, [[SRC]]
define internal float @signed16ToFloat(i32 %a) { define internal float @signed16ToFloat(i32 %a) {
entry: entry:
...@@ -307,6 +415,10 @@ entry: ...@@ -307,6 +415,10 @@ entry:
; CHECK-LABEL: signed16ToFloat ; CHECK-LABEL: signed16ToFloat
; CHECK: cvtsi2ss ; CHECK: cvtsi2ss
; CHECK: fld DWORD ; CHECK: fld DWORD
; ARM32-LABEL: signed16ToFloat
; ARM32-DAG: sxth [[INT:r[0-9]+]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f32.s32 {{s[0-9]+}}, [[SRC]]
define internal double @unsigned16ToDouble(i32 %a) { define internal double @unsigned16ToDouble(i32 %a) {
entry: entry:
...@@ -317,6 +429,10 @@ entry: ...@@ -317,6 +429,10 @@ entry:
; CHECK-LABEL: unsigned16ToDouble ; CHECK-LABEL: unsigned16ToDouble
; CHECK: cvtsi2sd ; CHECK: cvtsi2sd
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: unsigned16ToDouble
; ARM32-DAG: uxth [[INT:r[0-9]+]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f64.u32 {{d[0-9]+}}, [[SRC]]
define internal double @unsigned16ToDoubleConst() { define internal double @unsigned16ToDoubleConst() {
entry: entry:
...@@ -326,6 +442,11 @@ entry: ...@@ -326,6 +442,11 @@ entry:
; CHECK-LABEL: unsigned16ToDoubleConst ; CHECK-LABEL: unsigned16ToDoubleConst
; CHECK: cvtsi2sd ; CHECK: cvtsi2sd
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: unsigned16ToDoubleConst
; ARM32-DAG: movw [[INT:r[0-9]+]], #12345
; ARM32-DAG: uxth [[INT]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f64.u32 {{d[0-9]+}}, [[SRC]]
define internal float @unsigned16ToFloat(i32 %a) { define internal float @unsigned16ToFloat(i32 %a) {
entry: entry:
...@@ -336,6 +457,10 @@ entry: ...@@ -336,6 +457,10 @@ entry:
; CHECK-LABEL: unsigned16ToFloat ; CHECK-LABEL: unsigned16ToFloat
; CHECK: cvtsi2ss ; CHECK: cvtsi2ss
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: unsigned16ToFloat
; ARM32-DAG: uxth [[INT:r[0-9]+]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f32.u32 {{s[0-9]+}}, [[SRC]]
define internal double @signed8ToDouble(i32 %a) { define internal double @signed8ToDouble(i32 %a) {
entry: entry:
...@@ -346,6 +471,10 @@ entry: ...@@ -346,6 +471,10 @@ entry:
; CHECK-LABEL: signed8ToDouble ; CHECK-LABEL: signed8ToDouble
; CHECK: cvtsi2sd ; CHECK: cvtsi2sd
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: signed8ToDouble
; ARM32-DAG: sxtb [[INT:r[0-9]+]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f64.s32 {{d[0-9]+}}, [[SRC]]
define internal float @signed8ToFloat(i32 %a) { define internal float @signed8ToFloat(i32 %a) {
entry: entry:
...@@ -356,6 +485,10 @@ entry: ...@@ -356,6 +485,10 @@ entry:
; CHECK-LABEL: signed8ToFloat ; CHECK-LABEL: signed8ToFloat
; CHECK: cvtsi2ss ; CHECK: cvtsi2ss
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: signed8ToFloat
; ARM32-DAG: sxtb [[INT:r[0-9]+]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f32.s32 {{s[0-9]+}}, [[SRC]]
define internal double @unsigned8ToDouble(i32 %a) { define internal double @unsigned8ToDouble(i32 %a) {
entry: entry:
...@@ -366,6 +499,10 @@ entry: ...@@ -366,6 +499,10 @@ entry:
; CHECK-LABEL: unsigned8ToDouble ; CHECK-LABEL: unsigned8ToDouble
; CHECK: cvtsi2sd ; CHECK: cvtsi2sd
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: unsigned8ToDouble
; ARM32-DAG: uxtb [[INT:r[0-9]+]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f64.u32 {{d[0-9]+}}, [[SRC]]
define internal float @unsigned8ToFloat(i32 %a) { define internal float @unsigned8ToFloat(i32 %a) {
entry: entry:
...@@ -376,6 +513,10 @@ entry: ...@@ -376,6 +513,10 @@ entry:
; CHECK-LABEL: unsigned8ToFloat ; CHECK-LABEL: unsigned8ToFloat
; CHECK: cvtsi2ss ; CHECK: cvtsi2ss
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: unsigned8ToFloat
; ARM32-DAG: uxtb [[INT:r[0-9]+]]
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f32.u32 {{s[0-9]+}}, [[SRC]]
define internal double @unsigned1ToDouble(i32 %a) { define internal double @unsigned1ToDouble(i32 %a) {
entry: entry:
...@@ -386,6 +527,10 @@ entry: ...@@ -386,6 +527,10 @@ entry:
; CHECK-LABEL: unsigned1ToDouble ; CHECK-LABEL: unsigned1ToDouble
; CHECK: cvtsi2sd ; CHECK: cvtsi2sd
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: unsigned1ToDouble
; ARM32-DAG: and [[INT:r[0-9]+]], {{r[0-9]+}}, #1
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f64.u32 {{d[0-9]+}}, [[SRC]]
define internal float @unsigned1ToFloat(i32 %a) { define internal float @unsigned1ToFloat(i32 %a) {
entry: entry:
...@@ -396,6 +541,10 @@ entry: ...@@ -396,6 +541,10 @@ entry:
; CHECK-LABEL: unsigned1ToFloat ; CHECK-LABEL: unsigned1ToFloat
; CHECK: cvtsi2ss ; CHECK: cvtsi2ss
; CHECK: fld ; CHECK: fld
; ARM32-LABEL: unsigned1ToFloat
; ARM32-DAG: and [[INT:r[0-9]+]], {{r[0-9]+}}, #1
; ARM32-DAG: vmov [[SRC:s[0-9]+]], [[INT]]
; ARM32-DAG: vcvt.f32.u32 {{s[0-9]+}}, [[SRC]]
define internal float @int32BitcastToFloat(i32 %a) { define internal float @int32BitcastToFloat(i32 %a) {
entry: entry:
...@@ -404,6 +553,8 @@ entry: ...@@ -404,6 +553,8 @@ entry:
} }
; CHECK-LABEL: int32BitcastToFloat ; CHECK-LABEL: int32BitcastToFloat
; CHECK: mov ; CHECK: mov
; ARM32-LABEL: int32BitcastToFloat
; TODO(jpp): implement this test.
define internal float @int32BitcastToFloatConst() { define internal float @int32BitcastToFloatConst() {
entry: entry:
...@@ -412,6 +563,8 @@ entry: ...@@ -412,6 +563,8 @@ entry:
} }
; CHECK-LABEL: int32BitcastToFloatConst ; CHECK-LABEL: int32BitcastToFloatConst
; CHECK: mov ; CHECK: mov
; ARM32-LABEL: int32BitcastToFloatConst
; TODO(jpp): implement this test.
define internal double @int64BitcastToDouble(i64 %a) { define internal double @int64BitcastToDouble(i64 %a) {
entry: entry:
...@@ -420,6 +573,8 @@ entry: ...@@ -420,6 +573,8 @@ entry:
} }
; CHECK-LABEL: int64BitcastToDouble ; CHECK-LABEL: int64BitcastToDouble
; CHECK: mov ; CHECK: mov
; ARM32-LABEL: int64BitcastToDouble
; TODO(jpp): implement this test.
define internal double @int64BitcastToDoubleConst() { define internal double @int64BitcastToDoubleConst() {
entry: entry:
...@@ -428,3 +583,6 @@ entry: ...@@ -428,3 +583,6 @@ entry:
} }
; CHECK-LABEL: int64BitcastToDoubleConst ; CHECK-LABEL: int64BitcastToDoubleConst
; CHECK: mov ; CHECK: mov
; ARM32-LABEL: int64BitcastToDoubleConst
; TODO(jpp): implement this test.
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