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; return;
case IceType_f64: assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) { if (isMultiDest()) {
Asm->vmovdd(Dest, Var, getPredicate()); emitMultiDestSingleSource(Func);
return;
} else if (const auto *FpImm =
llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovd(Dest, FpImm, getPredicate());
return;
}
assert(!Asm->needsTextFixup());
return; return;
} }
// TODO(kschimpf) Handle register to register move.
Asm->setNeedsTextFixup();
return;
}
void InstARM32Mov::emitIASCoreVFPMove(const Cfg *Func) const { if (isMultiSource()) {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); emitSingleDestMultiSource(Func);
Operand *Src0 = getSrc(0);
if (!llvm::isa<Variable>(Src0))
// TODO(kschimpf) Handle moving constants into registers.
return Asm->setNeedsTextFixup();
// Move register to register.
Variable *Dest = getDest();
// TODO(kschimpf) Consider merging methods emitIAS.. methods into
// a single case statement.
switch (Dest->getType()) {
default:
// TODO(kschimpf): Fill this out more.
return Asm->setNeedsTextFixup();
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32:
assert(Src0->getType() == IceType_f32 && "Expected int to float move");
Asm->vmovrs(Dest, Src0, getPredicate());
return;
case IceType_i64:
assert(false && "i64 to float moves not handled here!");
return; return;
case IceType_f32:
switch (Src0->getType()) {
default:
assert(false && "Expected float to int move");
return;
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32:
return Asm->vmovsr(Dest, Src0, getPredicate());
}
} }
emitSingleDestSingleSource(Func);
} }
void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const { void InstARM32Mov::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Variable *Dest = getDest(); Variable *Dest = getDest();
Operand *Src0 = getSrc(0); Operand *Src0 = getSrc(0);
if (!Dest->hasReg()) { if (!Dest->hasReg()) {
llvm::report_fatal_error("mov can't store."); llvm::report_fatal_error("mov can't store.");
} }
if (isMemoryAccess(Src0)) { if (isMemoryAccess(Src0)) {
llvm::report_fatal_error("mov can't load."); llvm::report_fatal_error("mov can't load.");
} }
if (isMoveBetweenCoreAndVFPRegisters(Dest, Src0))
return emitIASCoreVFPMove(Func);
const Type DestTy = Dest->getType();
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."); assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type.");
if (isMultiDest()) { if (isMultiDest()) {
emitMultiDestSingleSource(Func); Asm->vmovrrd(Dest, getDestHi(), Src0, getPredicate());
return; return;
} }
if (isMultiSource()) { if (isMultiSource()) {
emitSingleDestMultiSource(Func); Asm->vmovdrr(Dest, Src0, getSrc(1), getPredicate());
return; return;
} }
emitSingleDestSingleSource(Func); const Type DestTy = Dest->getType();
} const Type SrcTy = Src0->getType();
switch (DestTy) {
void InstARM32Mov::emitIAS(const Cfg *Func) const { default:
// TODO(kschimpf) Flatten this to a switch statement of dest type. That is, break; // Error
// combine code of emitIASSingleDestSingleSource, emitIASCoreVFPMove, case IceType_i1:
// emitIASScalarVFPMove, emitDoubleToI64Move, and emitI64ToDoubleMove. case IceType_i8:
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); case IceType_i16:
assert(!(isMultiDest() && isMultiSource()) && "Invalid vmov type."); case IceType_i32:
if (isMultiDest()) switch (SrcTy) {
Asm->vmovrrd(getDest(), getDestHi(), getSrc(0), getPredicate()); default:
else if (isMultiSource()) break; // Error
Asm->vmovdrr(getDest(), getSrc(0), getSrc(1), getPredicate()); case IceType_i1:
else case IceType_i8:
emitIASSingleDestSingleSource(Func); case IceType_i16:
if (Asm->needsTextFixup()) case IceType_i32:
case IceType_i64:
Asm->mov(Dest, Src0, getPredicate());
return;
case IceType_f32:
Asm->vmovrs(Dest, Src0, getPredicate());
return;
}
break; // Error
case IceType_i64:
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;
}
if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovd(Dest, FpImm, getPredicate());
return;
}
}
break; // Error
case IceType_f32:
switch (SrcTy) {
default:
break; // Error
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32:
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
}
break; // Error
case IceType_f64:
if (SrcTy == IceType_f64) {
if (const auto *Var = llvm::dyn_cast<Variable>(Src0)) {
Asm->vmovdd(Dest, Var, getPredicate());
return;
}
if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
Asm->vmovd(Dest, FpImm, getPredicate());
return;
}
}
break; // Error
case IceType_v4i1:
case IceType_v8i1:
case IceType_v16i1:
case IceType_v16i8:
case IceType_v8i16:
case IceType_v4i32:
case IceType_v4f32:
// TODO(kschimpf): Add vector moves.
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