Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Unified Diff: src/IceInstARM32.cpp

Issue 1481133002: Subzero. ARM32. Show FP lowering some love. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Handles comments; git pull; fixes lit tests. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceInstARM32.def » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceInstARM32.cpp
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index 5e79128aafd7ebac93e223c93e3a268cbe8bdb8c..78caab06f85bbb9d7934fd11e0f34d4ec6d06249 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -185,6 +185,22 @@ void InstARM32::emitThreeAddrFP(const char *Opcode, const InstARM32 *Inst,
Inst->getSrc(1)->emit(Func);
}
+void InstARM32::emitFourAddrFP(const char *Opcode, const InstARM32 *Inst,
+ const Cfg *Func) {
+ if (!BuildDefs::dump())
+ return;
+ Ostream &Str = Func->getContext()->getStrEmit();
+ assert(Inst->getSrcSize() == 3);
+ assert(Inst->getSrc(0) == Inst->getDest());
+ Str << "\t" << Opcode << getVecWidthString(Inst->getDest()->getType())
+ << "\t";
+ Inst->getDest()->emit(Func);
+ Str << ", ";
+ Inst->getSrc(1)->emit(Func);
+ Str << ", ";
+ Inst->getSrc(2)->emit(Func);
+}
+
void InstARM32Pred::emitFourAddr(const char *Opcode, const InstARM32Pred *Inst,
const Cfg *Func) {
if (!BuildDefs::dump())
@@ -571,18 +587,43 @@ IceString InstARM32Label::getName(const Cfg *Func) const {
return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
}
+namespace {
+// Requirements for Push/Pop:
+// 1) All the Variables have the same type;
+// 2) All the variables have registers assigned to them.
+void validatePushOrPopRegisterListOrDie(const VarList &RegList) {
+ Type PreviousTy = IceType_void;
+ for (Variable *Reg : RegList) {
+ if (PreviousTy != IceType_void && Reg->getType() != PreviousTy) {
+ llvm::report_fatal_error("Type mismatch when popping/pushing "
+ "registers.");
+ }
+
+ if (!Reg->hasReg()) {
+ llvm::report_fatal_error("Push/pop operand does not have a register "
+ "assigned to it.");
+ }
+
+ PreviousTy = Reg->getType();
+ }
+}
+} // end of anonymous namespace
+
InstARM32Pop::InstARM32Pop(Cfg *Func, const VarList &Dests)
: InstARM32(Func, InstARM32::Pop, 0, nullptr), Dests(Dests) {
// Track modifications to Dests separately via FakeDefs. Also, a pop
// instruction affects the stack pointer and so it should not be allowed to
// be automatically dead-code eliminated. This is automatic since we leave
// the Dest as nullptr.
+ validatePushOrPopRegisterListOrDie(Dests);
}
InstARM32Push::InstARM32Push(Cfg *Func, const VarList &Srcs)
: InstARM32(Func, InstARM32::Push, Srcs.size(), nullptr) {
- for (Variable *Source : Srcs)
+ validatePushOrPopRegisterListOrDie(Srcs);
+ for (Variable *Source : Srcs) {
addSource(Source);
+ }
}
InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source)
@@ -736,8 +777,10 @@ template <> const char *InstARM32Udiv::Opcode = "udiv";
// FP
template <> const char *InstARM32Vadd::Opcode = "vadd";
template <> const char *InstARM32Vdiv::Opcode = "vdiv";
-template <> const char *InstARM32Vmul::Opcode = "vmul";
template <> const char *InstARM32Veor::Opcode = "veor";
+template <> const char *InstARM32Vmla::Opcode = "vmla";
+template <> const char *InstARM32Vmls::Opcode = "vmls";
+template <> const char *InstARM32Vmul::Opcode = "vmul";
template <> const char *InstARM32Vsub::Opcode = "vsub";
// Four-addr ops
template <> const char *InstARM32Mla::Opcode = "mla";
@@ -1216,51 +1259,74 @@ template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func);
}
+namespace {
+
+bool isAssignedConsecutiveRegisters(Variable *Before, Variable *After) {
+ assert(Before->hasReg());
+ assert(After->hasReg());
+ return Before->getRegNum() + 1 == After->getRegNum();
+}
+
+} // end of anonymous namespace
+
void InstARM32Pop::emit(const Cfg *Func) const {
- // TODO(jpp): Improve FP register save/restore.
if (!BuildDefs::dump())
return;
- SizeT IntegerCount = 0;
- for (const Operand *Op : Dests) {
- if (isScalarIntegerType(Op->getType())) {
- ++IntegerCount;
- }
+
+ const SizeT DestSize = Dests.size();
+ if (DestSize == 0) {
+ assert(false && "Empty pop list");
+ return;
}
+
Ostream &Str = Func->getContext()->getStrEmit();
- bool NeedNewline = false;
- if (IntegerCount != 0) {
+
+ Variable *Reg = Dests[0];
+ if (isScalarIntegerType(Reg->getType())) {
+ // GPR push.
Str << "\t"
- << "pop"
- << "\t{";
- bool PrintComma = false;
- for (const Operand *Op : Dests) {
- if (isScalarIntegerType(Op->getType())) {
- if (PrintComma)
- Str << ", ";
- Op->emit(Func);
- PrintComma = true;
- }
+ "pop"
+ "\t{";
+ Reg->emit(Func);
+ for (SizeT i = 1; i < DestSize; ++i) {
+ Str << ", ";
+ Reg = Dests[i];
+ Reg->emit(Func);
}
Str << "}";
- NeedNewline = true;
+ return;
}
- for (const Operand *Op : Dests) {
- if (isScalarIntegerType(Op->getType()))
- continue;
- if (NeedNewline) {
- Str << "\n";
+ // VFP "s" reg push.
+ SizeT End = DestSize - 1;
+ SizeT Start = DestSize - 1;
+ Reg = Dests[DestSize - 1];
+ Str << "\t"
+ "vpop"
+ "\t{";
+ for (SizeT i = 2; i <= DestSize; ++i) {
+ Variable *PreviousReg = Dests[DestSize - i];
+ if (!isAssignedConsecutiveRegisters(PreviousReg, Reg)) {
+ Dests[Start]->emit(Func);
+ for (SizeT j = Start + 1; j <= End; ++j) {
+ Str << ", ";
+ Dests[j]->emit(Func);
+ }
startNextInst(Func);
- NeedNewline = false;
+ Str << "}\n\t"
+ "vpop"
+ "\t{";
+ End = DestSize - i;
}
- Str << "\t"
- << "vpop"
- << "\t{";
- Op->emit(Func);
- Str << "}";
- NeedNewline = true;
+ Reg = PreviousReg;
+ Start = DestSize - i;
+ }
+ Dests[Start]->emit(Func);
+ for (SizeT j = Start + 1; j <= End; ++j) {
+ Str << ", ";
+ Dests[j]->emit(Func);
}
- assert(NeedNewline); // caller will add the newline
+ Str << "}";
}
void InstARM32Pop::emitIAS(const Cfg *Func) const {
@@ -1310,56 +1376,55 @@ void InstARM32Pop::dump(const Cfg *Func) const {
}
void InstARM32Push::emit(const Cfg *Func) const {
- // TODO(jpp): Improve FP register save/restore.
if (!BuildDefs::dump())
return;
- SizeT IntegerCount = 0;
- for (SizeT i = 0; i < getSrcSize(); ++i) {
- if (isScalarIntegerType(getSrc(i)->getType())) {
- ++IntegerCount;
- }
+
+ // Push can't be emitted if there are no registers to save. This should never
+ // happen, but if it does, we don't need to bring Subzero down -- we just skip
+ // emitting the push instruction (and maybe emit a nop?) The assert() is here
+ // so that we can detect this error during development.
+ const SizeT SrcSize = getSrcSize();
+ if (SrcSize == 0) {
+ assert(false && "Empty push list");
+ return;
}
+
Ostream &Str = Func->getContext()->getStrEmit();
- bool NeedNewline = false;
- for (SizeT i = getSrcSize(); i > 0; --i) {
- Operand *Op = getSrc(i - 1);
- if (isScalarIntegerType(Op->getType()))
- continue;
- if (NeedNewline) {
- Str << "\n";
- startNextInst(Func);
- NeedNewline = false;
- }
+
+ Variable *Reg = llvm::cast<Variable>(getSrc(0));
+ if (isScalarIntegerType(Reg->getType())) {
+ // GPR push.
Str << "\t"
- << "vpush"
- << "\t{";
- Op->emit(Func);
+ "push"
+ "\t{";
+ Reg->emit(Func);
+ for (SizeT i = 1; i < SrcSize; ++i) {
+ Str << ", ";
+ getSrc(i)->emit(Func);
+ }
Str << "}";
- NeedNewline = true;
+ return;
}
- if (IntegerCount != 0) {
- if (NeedNewline) {
- Str << "\n";
+
+ // VFP "s" reg push.
+ Str << "\t"
+ "vpush"
+ "\t{";
+ Reg->emit(Func);
+ for (SizeT i = 1; i < SrcSize; ++i) {
+ Variable *NextReg = llvm::cast<Variable>(getSrc(i));
+ if (isAssignedConsecutiveRegisters(Reg, NextReg)) {
+ Str << ", ";
+ } else {
startNextInst(Func);
- NeedNewline = false;
- }
- Str << "\t"
- << "push"
- << "\t{";
- bool PrintComma = false;
- for (SizeT i = 0; i < getSrcSize(); ++i) {
- Operand *Op = getSrc(i);
- if (isScalarIntegerType(Op->getType())) {
- if (PrintComma)
- Str << ", ";
- Op->emit(Func);
- PrintComma = true;
- }
+ Str << "}\n\t"
+ "vpush"
+ "\t{";
}
- Str << "}";
- NeedNewline = true;
+ Reg = NextReg;
+ Reg->emit(Func);
}
- assert(NeedNewline); // caller will add the newline
+ Str << "}";
}
void InstARM32Push::emitIAS(const Cfg *Func) const {
@@ -1925,8 +1990,10 @@ template class InstARM32ThreeAddrGPR<InstARM32::Udiv>;
template class InstARM32ThreeAddrFP<InstARM32::Vadd>;
template class InstARM32ThreeAddrFP<InstARM32::Vdiv>;
-template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
template class InstARM32ThreeAddrFP<InstARM32::Veor>;
+template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
+template class InstARM32ThreeAddrFP<InstARM32::Vmla>;
+template class InstARM32ThreeAddrFP<InstARM32::Vmls>;
template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
template class InstARM32LoadBase<InstARM32::Ldr>;
« no previous file with comments | « src/IceInstARM32.h ('k') | src/IceInstARM32.def » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698