Commit 282d7afd by Karl Schimpf

Clean up assembling MOV instructions in the integrated ARM assembler.

Flattens out MOV's emitIAS methods making it easier to see valid types for source/destination of the move. BUG=None R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1665323002 .
parent 18cce427
...@@ -1254,138 +1254,131 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -1254,138 +1254,131 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
Src0->emit(Func); Src0->emit(Func);
} }
void InstARM32Mov::emitIASScalarVFPMove(const Cfg *Func) const { void InstARM32Mov::emit(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); if (!BuildDefs::dump())
Operand *Src0 = getSrc(0);
Variable *Dest = getDest();
switch (Dest->getType()) {
default:
assert(false && "Do not know how to emit scalar FP move for type.");
break;
case IceType_f32:
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
Asm->vmovss(Dest, Var, getPredicate());
return;
} else if (const auto *FpImm =
llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovs(Dest, FpImm, getPredicate());
return;
}
assert(!Asm->needsTextFixup());
return;
case IceType_f64:
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
Asm->vmovdd(Dest, Var, getPredicate());
return; return;
} else if (const auto *FpImm = assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) { if (isMultiDest()) {
Asm->vmovd(Dest, FpImm, getPredicate()); emitMultiDestSingleSource(Func);
return; return;
} }
assert(!Asm->needsTextFixup());
if (isMultiSource()) {
emitSingleDestMultiSource(Func);
return; return;
} }
// TODO(kschimpf) Handle register to register move.
Asm->setNeedsTextFixup(); emitSingleDestSingleSource(Func);
return;
} }
void InstARM32Mov::emitIASCoreVFPMove(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();
Operand *Src0 = getSrc(0); Operand *Src0 = getSrc(0);
if (!llvm::isa<Variable>(Src0)) if (!Dest->hasReg()) {
// TODO(kschimpf) Handle moving constants into registers. llvm::report_fatal_error("mov can't store.");
return Asm->setNeedsTextFixup(); }
if (isMemoryAccess(Src0)) {
llvm::report_fatal_error("mov can't load.");
}
// Move register to register. assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
Variable *Dest = getDest(); if (isMultiDest()) {
// TODO(kschimpf) Consider merging methods emitIAS.. methods into Asm->vmovrrd(Dest, getDestHi(), Src0, getPredicate());
// a single case statement. return;
switch (Dest->getType()) { }
if (isMultiSource()) {
Asm->vmovdrr(Dest, Src0, getSrc(1), getPredicate());
return;
}
const Type DestTy = Dest->getType();
const Type SrcTy = Src0->getType();
switch (DestTy) {
default:
break; // Error
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32:
switch (SrcTy) {
default: default:
// TODO(kschimpf): Fill this out more. break; // Error
return Asm->setNeedsTextFixup();
case IceType_i1: case IceType_i1:
case IceType_i8: case IceType_i8:
case IceType_i16: case IceType_i16:
case IceType_i32: case IceType_i32:
assert(Src0->getType() == IceType_f32 && "Expected int to float move"); case IceType_i64:
Asm->mov(Dest, Src0, getPredicate());
return;
case IceType_f32:
Asm->vmovrs(Dest, Src0, getPredicate()); Asm->vmovrs(Dest, Src0, getPredicate());
return; return;
}
break; // Error
case IceType_i64: case IceType_i64:
assert(false && "i64 to float moves not handled here!"); if (isScalarIntegerType(SrcTy)) {
Asm->mov(Dest, Src0, getPredicate());
return;
}
if (SrcTy == IceType_f64) {
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
Asm->vmovdd(Dest, Var, getPredicate());
return; return;
}
if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovd(Dest, FpImm, getPredicate());
return;
}
}
break; // Error
case IceType_f32: case IceType_f32:
switch (Src0->getType()) { switch (SrcTy) {
default: default:
assert(false && "Expected float to int move"); break; // Error
return;
case IceType_i1: case IceType_i1:
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, getPredicate());
case IceType_f32:
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
Asm->vmovss(Dest, Var, getPredicate());
return;
} }
if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovs(Dest, FpImm, getPredicate());
return;
} }
} break; // Error
void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
Variable *Dest = getDest();
Operand *Src0 = getSrc(0);
if (!Dest->hasReg()) {
llvm::report_fatal_error("mov can't store.");
}
if (isMemoryAccess(Src0)) {
llvm::report_fatal_error("mov can't load.");
} }
break; // Error
if (isMoveBetweenCoreAndVFPRegisters(Dest, Src0)) case IceType_f64:
return emitIASCoreVFPMove(Func); if (SrcTy == IceType_f64) {
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
const Type DestTy = Dest->getType(); Asm->vmovdd(Dest, Var, getPredicate());
if (isScalarFloatingType(DestTy))
return emitIASScalarVFPMove(Func);
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
if (isVectorType(DestTy))
return Asm->setNeedsTextFixup();
return Asm->mov(Dest, Src0, getPredicate());
}
void InstARM32Mov::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
if (isMultiDest()) {
emitMultiDestSingleSource(Func);
return; return;
} }
if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
if (isMultiSource()) { Asm->vmovd(Dest, FpImm, getPredicate());
emitSingleDestMultiSource(Func);
return; return;
} }
}
emitSingleDestSingleSource(Func); break; // Error
} case IceType_v4i1:
case IceType_v8i1:
void InstARM32Mov::emitIAS(const Cfg *Func) const { case IceType_v16i1:
// TODO(kschimpf) Flatten this to a switch statement of dest type. That is, case IceType_v16i8:
// combine code of emitIASSingleDestSingleSource, emitIASCoreVFPMove, case IceType_v8i16:
// emitIASScalarVFPMove, emitDoubleToI64Move, and emitI64ToDoubleMove. case IceType_v4i32:
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); case IceType_v4f32:
assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); // TODO(kschimpf): Add vector moves.
if (isMultiDest())
Asm->vmovrrd(getDest(), getDestHi(), getSrc(0), getPredicate());
else if (isMultiSource())
Asm->vmovdrr(getDest(), getSrc(0), getSrc(1), getPredicate());
else
emitIASSingleDestSingleSource(Func);
if (Asm->needsTextFixup())
emitUsingTextFixup(Func); emitUsingTextFixup(Func);
return;
}
llvm::report_fatal_error("Mov: don't know how to move " +
typeIceString(SrcTy) + " to " +
typeIceString(DestTy));
} }
void InstARM32Mov::dump(const Cfg *Func) const { void InstARM32Mov::dump(const Cfg *Func) const {
......
...@@ -1342,15 +1342,10 @@ public: ...@@ -1342,15 +1342,10 @@ public:
private: private:
InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src, InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
CondARM32::Cond Predicate); CondARM32::Cond Predicate);
void emitMultiDestSingleSource(const Cfg *Func) const; void emitMultiDestSingleSource(const Cfg *Func) const;
void emitSingleDestMultiSource(const Cfg *Func) const; void emitSingleDestMultiSource(const Cfg *Func) const;
void emitSingleDestSingleSource(const Cfg *Func) const; void emitSingleDestSingleSource(const Cfg *Func) const;
void emitIASSingleDestSingleSource(const Cfg *Func) const;
void emitIASScalarVFPMove(const Cfg *Func) const;
void emitIASCoreVFPMove(const Cfg *Func) const;
Variable *DestHi = nullptr; Variable *DestHi = nullptr;
}; };
......
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