Commit 4af72130 by Karl Schimpf

Add move vector to the integrated ARM assembler.

Implements a vector move as a vector orr on the corresponding Q registers. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=eholk@chromium.org Review URL: https://codereview.chromium.org/1694533002 .
parent dc61925c
...@@ -35,6 +35,8 @@ public: ...@@ -35,6 +35,8 @@ public:
}; };
static bool isDefined(Cond C) { return C != kNone; } static bool isDefined(Cond C) { return C != kNone; }
static bool isUnconditional(Cond C) { return !isDefined(C) || C == AL; }
}; };
} // end of namespace Ice } // end of namespace Ice
......
...@@ -1436,11 +1436,15 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -1436,11 +1436,15 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
// assembler might be tempted to assume we want a vector vmov{c}, and that // assembler might be tempted to assume we want a vector vmov{c}, and that
// is disallowed because ARM. // is disallowed because ARM.
const char *WidthString = !CoreVFPMove ? getVecWidthString(Ty) : ""; const char *WidthString = !CoreVFPMove ? getVecWidthString(Ty) : "";
CondARM32::Cond Cond = getPredicate();
if (IsVector)
assert(CondARM32::isUnconditional(Cond) &&
"Moves on vectors must be unconditional!");
Str << "\t" << Opcode; Str << "\t" << Opcode;
if (IsVMove) { if (IsVMove) {
Str << getPredicate() << WidthString; Str << Cond << WidthString;
} else { } else {
Str << WidthString << getPredicate(); Str << WidthString << Cond;
} }
Str << "\t"; Str << "\t";
Dest->emit(Func); Dest->emit(Func);
...@@ -1467,8 +1471,9 @@ void InstARM32Mov::emit(const Cfg *Func) const { ...@@ -1467,8 +1471,9 @@ void InstARM32Mov::emit(const Cfg *Func) const {
void InstARM32Mov::emitIAS(const Cfg *Func) const { void InstARM32Mov::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Variable *Dest = getDest(); const Variable *Dest = getDest();
Operand *Src0 = getSrc(0); Operand *Src0 = getSrc(0);
const CondARM32::Cond Cond = getPredicate();
if (!Dest->hasReg()) { if (!Dest->hasReg()) {
llvm::report_fatal_error("mov can't store."); llvm::report_fatal_error("mov can't store.");
} }
...@@ -1478,11 +1483,11 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const { ...@@ -1478,11 +1483,11 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const {
assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
if (isMultiDest()) { if (isMultiDest()) {
Asm->vmovrrd(Dest, getDestHi(), Src0, getPredicate()); Asm->vmovrrd(Dest, getDestHi(), Src0, Cond);
return; return;
} }
if (isMultiSource()) { if (isMultiSource()) {
Asm->vmovdrr(Dest, Src0, getSrc(1), getPredicate()); Asm->vmovdrr(Dest, Src0, getSrc(1), Cond);
return; return;
} }
...@@ -1503,25 +1508,25 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const { ...@@ -1503,25 +1508,25 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const {
case IceType_i16: case IceType_i16:
case IceType_i32: case IceType_i32:
case IceType_i64: case IceType_i64:
Asm->mov(Dest, Src0, getPredicate()); Asm->mov(Dest, Src0, Cond);
return; return;
case IceType_f32: case IceType_f32:
Asm->vmovrs(Dest, Src0, getPredicate()); Asm->vmovrs(Dest, Src0, Cond);
return; return;
} }
break; // Error break; // Error
case IceType_i64: case IceType_i64:
if (isScalarIntegerType(SrcTy)) { if (isScalarIntegerType(SrcTy)) {
Asm->mov(Dest, Src0, getPredicate()); Asm->mov(Dest, Src0, Cond);
return; return;
} }
if (SrcTy == IceType_f64) { if (SrcTy == IceType_f64) {
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
Asm->vmovdd(Dest, Var, getPredicate()); Asm->vmovdd(Dest, Var, Cond);
return; return;
} }
if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovd(Dest, FpImm, getPredicate()); Asm->vmovd(Dest, FpImm, Cond);
return; return;
} }
} }
...@@ -1534,14 +1539,14 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const { ...@@ -1534,14 +1539,14 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const {
case IceType_i8: case IceType_i8:
case IceType_i16: case IceType_i16:
case IceType_i32: case IceType_i32:
return Asm->vmovsr(Dest, Src0, getPredicate()); return Asm->vmovsr(Dest, Src0, Cond);
case IceType_f32: case IceType_f32:
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
Asm->vmovss(Dest, Var, getPredicate()); Asm->vmovss(Dest, Var, Cond);
return; return;
} }
if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovs(Dest, FpImm, getPredicate()); Asm->vmovs(Dest, FpImm, Cond);
return; return;
} }
break; // Error break; // Error
...@@ -1550,11 +1555,11 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const { ...@@ -1550,11 +1555,11 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const {
case IceType_f64: case IceType_f64:
if (SrcTy == IceType_f64) { if (SrcTy == IceType_f64) {
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
Asm->vmovdd(Dest, Var, getPredicate()); Asm->vmovdd(Dest, Var, Cond);
return; return;
} }
if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovd(Dest, FpImm, getPredicate()); Asm->vmovd(Dest, FpImm, Cond);
return; return;
} }
} }
...@@ -1566,8 +1571,10 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const { ...@@ -1566,8 +1571,10 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const {
case IceType_v8i16: case IceType_v8i16:
case IceType_v4i32: case IceType_v4i32:
case IceType_v4f32: case IceType_v4f32:
// TODO(kschimpf): Add vector moves. assert(CondARM32::isUnconditional(Cond) &&
emitUsingTextFixup(Func); "Moves on <4 x f32> must be unconditional!");
assert(SrcTy == DestTy && "Mov on different vector types");
Asm->vorrq(Dest, Src0, Src0);
return; return;
} }
llvm::report_fatal_error("Mov: don't know how to move " + llvm::report_fatal_error("Mov: don't know how to move " +
......
; Test that we handle a vector move.
; NOTE: We use -O2 to force a vector move for the return value.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 \
; RUN: | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 \
; RUN: | FileCheck %s --check-prefix=DIS
define internal <4 x float> @testMoveVector(<4 x i32> %a) {
; ASM-LABEL: testMoveVector:
; DIS-LABEL:{{.+}} <testMoveVector>:
; IASM-LABEL: testMoveVector:
entry:
%0 = sitofp <4 x i32> %a to <4 x float>
ret <4 x float> %0
; ASM: vmov.f32 q0, q1
; DIS: 3c: eef03a40
; IASM-NOT: vmov.f32 q0, q1
}
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