| Index: src/IceInstARM32.cpp
|
| diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
|
| index d53d019a5c45dd95817bca0f3213f5ec0fbecdd2..e2498febe9ea46dc5a1dd8f0fe2fb8d483bbe785 100644
|
| --- a/src/IceInstARM32.cpp
|
| +++ b/src/IceInstARM32.cpp
|
| @@ -835,10 +835,48 @@ template <> void InstARM32Vshl::emitIAS(const Cfg *Func) const {
|
| switch (Sign) {
|
| case InstARM32::FS_None: // defaults to unsigned.
|
| case InstARM32::FS_Unsigned:
|
| - Asm->vshlqu(ElmtTy, Dest, getSrc(0), getSrc(1));
|
| + if (const auto *Imm6 = llvm::dyn_cast<ConstantInteger32>(getSrc(1))) {
|
| + Asm->vshlqc(ElmtTy, Dest, getSrc(0), Imm6);
|
| + } else {
|
| + Asm->vshlqu(ElmtTy, Dest, getSrc(0), getSrc(1));
|
| + }
|
| break;
|
| case InstARM32::FS_Signed:
|
| - Asm->vshlqi(ElmtTy, Dest, getSrc(0), getSrc(1));
|
| + if (const auto *Imm6 = llvm::dyn_cast<ConstantInteger32>(getSrc(1))) {
|
| + Asm->vshlqc(ElmtTy, Dest, getSrc(0), Imm6);
|
| + } else {
|
| + Asm->vshlqi(ElmtTy, Dest, getSrc(0), getSrc(1));
|
| + }
|
| + break;
|
| + }
|
| + } break;
|
| + }
|
| +}
|
| +
|
| +template <> void InstARM32Vshr::emitIAS(const Cfg *Func) const {
|
| + auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
|
| + const Variable *Dest = getDest();
|
| + const Type DestTy = Dest->getType();
|
| + switch (DestTy) {
|
| + default:
|
| + llvm::report_fatal_error("Vshr not defined on type " +
|
| + typeStdString(Dest->getType()));
|
| + case IceType_v4i1:
|
| + case IceType_v8i1:
|
| + case IceType_v16i1:
|
| + case IceType_v16i8:
|
| + case IceType_v8i16:
|
| + case IceType_v4i32: {
|
| + const Type ElmtTy = typeElementType(DestTy);
|
| + const auto *Imm6 = llvm::cast<ConstantInteger32>(getSrc(1));
|
| + assert(Sign != InstARM32::FS_None);
|
| + switch (Sign) {
|
| + case InstARM32::FS_None: // defaults to unsigned.
|
| + case InstARM32::FS_Unsigned:
|
| + Asm->vshrquc(ElmtTy, Dest, getSrc(0), Imm6);
|
| + break;
|
| + case InstARM32::FS_Signed:
|
| + Asm->vshrqic(ElmtTy, Dest, getSrc(0), Imm6);
|
| break;
|
| }
|
| } break;
|
| @@ -1466,6 +1504,7 @@ template <> const char *InstARM32Vmul::Opcode = "vmul";
|
| template <> const char *InstARM32Vorr::Opcode = "vorr";
|
| template <> const char *InstARM32UnaryopFP<InstARM32::Vneg>::Opcode = "vneg";
|
| template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshl>::Opcode = "vshl";
|
| +template <> const char *InstARM32ThreeAddrFP<InstARM32::Vshr>::Opcode = "vshr";
|
| template <> const char *InstARM32Vsub::Opcode = "vsub";
|
| // Four-addr ops
|
| template <> const char *InstARM32Mla::Opcode = "mla";
|
| @@ -2452,6 +2491,14 @@ const char *vcvtVariantSuffix(const InstARM32Vcvt::VcvtVariant Variant) {
|
| return ".f64.f32";
|
| case InstARM32Vcvt::D2s:
|
| return ".f32.f64";
|
| + case InstARM32Vcvt::Vs2si:
|
| + return ".s32.f32";
|
| + case InstARM32Vcvt::Vs2ui:
|
| + return ".u32.f32";
|
| + case InstARM32Vcvt::Vsi2s:
|
| + return ".f32.s32";
|
| + case InstARM32Vcvt::Vui2s:
|
| + return ".f32.u32";
|
| }
|
| llvm::report_fatal_error("Invalid VcvtVariant enum.");
|
| }
|
| @@ -2503,6 +2550,18 @@ void InstARM32Vcvt::emitIAS(const Cfg *Func) const {
|
| case D2s:
|
| Asm->vcvtsd(getDest(), getSrc(0), getPredicate());
|
| break;
|
| + case Vs2si:
|
| + Asm->vcvtqsi(getDest(), getSrc(0));
|
| + break;
|
| + case Vs2ui:
|
| + Asm->vcvtqsu(getDest(), getSrc(0));
|
| + break;
|
| + case Vsi2s:
|
| + Asm->vcvtqis(getDest(), getSrc(0));
|
| + break;
|
| + case Vui2s:
|
| + Asm->vcvtqus(getDest(), getSrc(0));
|
| + break;
|
| }
|
| assert(!Asm->needsTextFixup());
|
| }
|
| @@ -2913,6 +2972,7 @@ template class InstARM32FourAddrFP<InstARM32::Vmls>;
|
| template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
|
| template class InstARM32UnaryopSignAwareFP<InstARM32::Vneg>;
|
| template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshl>;
|
| +template class InstARM32ThreeAddrSignAwareFP<InstARM32::Vshr>;
|
| template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
|
|
|
| template class InstARM32LoadBase<InstARM32::Ldr>;
|
|
|