Commit e0b829f8 by John Porto

Subzero. Eliminates the use of Variable64On32 as operands in ARM.

This is in preparation for adding atomic support to the ARM backend. Moreover, the code is becoming increasingly complicated due to the use of Variable64On32 as instruction operands. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076 R=kschimpf@google.com Review URL: https://codereview.chromium.org/1372083002 .
parent 230d4101
...@@ -380,6 +380,28 @@ InstARM32Vcvt::InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src, ...@@ -380,6 +380,28 @@ InstARM32Vcvt::InstARM32Vcvt(Cfg *Func, Variable *Dest, Variable *Src,
addSource(Src); addSource(Src);
} }
InstARM32Mov::InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
CondARM32::Cond Predicate)
: InstARM32Pred(Func, InstARM32::Mov, 2, Dest, Predicate) {
auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
assert(Dest64 == nullptr || Src64 == nullptr);
if (Dest64 != nullptr) {
// this-> is needed below because there is a parameter named Dest.
this->Dest = Dest64->getLo();
DestHi = Dest64->getHi();
}
if (Src64 == nullptr) {
addSource(Src);
} else {
addSource(Src64->getLo());
addSource(Src64->getHi());
}
}
InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1, InstARM32Vcmp::InstARM32Vcmp(Cfg *Func, Variable *Src0, Variable *Src1,
CondARM32::Cond Predicate) CondARM32::Cond Predicate)
: InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) { : InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) {
...@@ -451,19 +473,19 @@ void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const { ...@@ -451,19 +473,19 @@ void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
auto *Dest = llvm::cast<Variable64On32>(getDest()); Variable *DestLo = getDest();
Operand *Src = getSrc(0); Variable *DestHi = getDestHi();
auto *Src = llvm::cast<Variable>(getSrc(0));
assert(Dest->getType() == IceType_i64); assert(DestHi->hasReg());
assert(Dest->getHi()->hasReg()); assert(DestLo->hasReg());
assert(Dest->getLo()->hasReg()); assert(llvm::isa<Variable>(Src) && Src->hasReg());
assert(!llvm::isa<OperandARM32Mem>(Src));
Str << "\t" Str << "\t"
<< "vmov" << getPredicate() << "\t"; << "vmov" << getPredicate() << "\t";
Dest->getLo()->emit(Func); DestLo->emit(Func);
Str << ", "; Str << ", ";
Dest->getHi()->emit(Func); DestHi->emit(Func);
Str << ", "; Str << ", ";
Src->emit(Func); Src->emit(Func);
} }
...@@ -473,20 +495,20 @@ void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const { ...@@ -473,20 +495,20 @@ void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
return; return;
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
Variable *Dest = getDest(); Variable *Dest = getDest();
auto *Src = llvm::cast<Variable64On32>(getSrc(0)); Variable *SrcLo = llvm::cast<Variable>(getSrc(0));
Variable *SrcHi = llvm::cast<Variable>(getSrc(1));
assert(Src->getType() == IceType_i64); assert(SrcHi->hasReg());
assert(Src->getHi()->hasReg()); assert(SrcLo->hasReg());
assert(Src->getLo()->hasReg());
assert(Dest->hasReg()); assert(Dest->hasReg());
Str << "\t" Str << "\t"
<< "vmov" << getPredicate() << "\t"; << "vmov" << getPredicate() << "\t";
Dest->emit(Func); Dest->emit(Func);
Str << ", "; Str << ", ";
Src->getLo()->emit(Func); SrcLo->emit(Func);
Str << ", "; Str << ", ";
Src->getHi()->emit(Func); SrcHi->emit(Func);
} }
namespace { namespace {
...@@ -583,28 +605,20 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const { ...@@ -583,28 +605,20 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const {
void InstARM32Mov::dump(const Cfg *Func) const { void InstARM32Mov::dump(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
assert(getSrcSize() == 1); assert(getSrcSize() == 1 || getSrcSize() == 2);
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
Variable *Dest = getDest(); Variable *Dest = getDest();
if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { Variable *DestHi = getDestHi();
Dest64->getLo()->dump(Func); Dest->dump(Func);
if (DestHi) {
Str << ", "; Str << ", ";
Dest64->getHi()->dump(Func); DestHi->dump(Func);
} else {
Dest->dump(Func);
} }
dumpOpcodePred(Str, " = mov", getDest()->getType()); dumpOpcodePred(Str, " = mov", getDest()->getType());
Str << " "; Str << " ";
Operand *Src = getSrc(0); dumpSources(Func);
if (auto *Src64 = llvm::dyn_cast<Variable64On32>(Src)) {
Src64->getLo()->dump(Func);
Str << ", ";
Src64->getHi()->dump(Func);
} else {
Src->dump(Func);
}
} }
void InstARM32Br::emit(const Cfg *Func) const { void InstARM32Br::emit(const Cfg *Func) const {
......
...@@ -1133,26 +1133,24 @@ public: ...@@ -1133,26 +1133,24 @@ public:
void dump(const Cfg *Func) const override; void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); } static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
bool isMultiDest() const { bool isMultiDest() const { return DestHi != nullptr; }
assert(getDest() != nullptr);
return llvm::isa<Variable64On32>(getDest());
}
bool isMultiSource() const { bool isMultiSource() const {
assert(getSrcSize() == 1); assert(getSrcSize() == 1 || getSrcSize() == 2);
return llvm::isa<Variable64On32>(getSrc(0)); return getSrcSize() == 2;
} }
Variable *getDestHi() const { return DestHi; }
private: private:
InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src, InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
CondARM32::Cond Predicate) CondARM32::Cond Predicate);
: InstARM32Pred(Func, InstARM32::Mov, 1, Dest, Predicate) {
addSource(Src);
}
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;
Variable *DestHi = nullptr;
}; };
class InstARM32Vcmp final : public InstARM32Pred { class InstARM32Vcmp final : public InstARM32Pred {
......
...@@ -441,13 +441,7 @@ void TargetARM32::emitVariable(const Variable *Var) const { ...@@ -441,13 +441,7 @@ void TargetARM32::emitVariable(const Variable *Var) const {
Offset += getStackAdjustment(); Offset += getStackAdjustment();
} }
const Type VarTy = Var->getType(); const Type VarTy = Var->getType();
// In general, no Variable64On32 should be emited in textual asm output. It if (!isLegalVariableStackOffset(VarTy, Offset)) {
// turns out that some lowering sequences Fake-Def/Fake-Use such a variables.
// If they end up being assigned an illegal offset we get a runtime error. We
// liberally allow Variable64On32 to have illegal offsets because offsets
// don't matter in FakeDefs/FakeUses.
if (!llvm::isa<Variable64On32>(Var) &&
!isLegalVariableStackOffset(VarTy, Offset)) {
llvm::report_fatal_error("Illegal stack offset"); llvm::report_fatal_error("Illegal stack offset");
} }
Str << "[" << getRegName(BaseRegNum, VarTy); Str << "[" << getRegName(BaseRegNum, VarTy);
...@@ -684,8 +678,14 @@ void TargetARM32::addProlog(CfgNode *Node) { ...@@ -684,8 +678,14 @@ void TargetARM32::addProlog(CfgNode *Node) {
uint32_t SpillAreaAlignmentBytes = 0; uint32_t SpillAreaAlignmentBytes = 0;
// For now, we don't have target-specific variables that need special // For now, we don't have target-specific variables that need special
// treatment (no stack-slot-linked SpillVariable type). // treatment (no stack-slot-linked SpillVariable type).
std::function<bool(Variable *)> TargetVarHook = std::function<bool(Variable *)> TargetVarHook = [](Variable *Var) {
[](Variable *) { return false; }; static constexpr bool AssignStackSlot = false;
static constexpr bool DontAssignStackSlot = !AssignStackSlot;
if (llvm::isa<Variable64On32>(Var)) {
return DontAssignStackSlot;
}
return AssignStackSlot;
};
// Compute the list of spilled variables and bounds for GlobalsSize, etc. // Compute the list of spilled variables and bounds for GlobalsSize, etc.
getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize,
...@@ -1979,7 +1979,8 @@ void TargetARM32::lowerCall(const InstCall *Instr) { ...@@ -1979,7 +1979,8 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
} }
namespace { namespace {
void forceHiLoInReg(Variable64On32 *Var) { void configureBitcastTemporary(Variable64On32 *Var) {
Var->setMustNotHaveReg();
Var->getHi()->setMustHaveReg(); Var->getHi()->setMustHaveReg();
Var->getLo()->setMustHaveReg(); Var->getLo()->setMustHaveReg();
} }
...@@ -2265,15 +2266,12 @@ void TargetARM32::lowerCast(const InstCast *Inst) { ...@@ -2265,15 +2266,12 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
assert(Src0->getType() == IceType_f64); assert(Src0->getType() == IceType_f64);
auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
T->initHiLo(Func); T->initHiLo(Func);
forceHiLoInReg(T); configureBitcastTemporary(T);
Variable *Src0R = legalizeToReg(Src0); Variable *Src0R = legalizeToReg(Src0);
_mov(T, Src0R); _mov(T, Src0R);
Context.insert(InstFakeDef::create(Func, T->getLo()));
Context.insert(InstFakeDef::create(Func, T->getHi()));
auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); auto *Dest64On32 = llvm::cast<Variable64On32>(Dest);
lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T->getLo())); lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T->getLo()));
lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T->getHi())); lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T->getHi()));
Context.insert(InstFakeUse::create(Func, T));
break; break;
} }
case IceType_f64: { case IceType_f64: {
...@@ -2284,16 +2282,10 @@ void TargetARM32::lowerCast(const InstCast *Inst) { ...@@ -2284,16 +2282,10 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
assert(Src0->getType() == IceType_i64); assert(Src0->getType() == IceType_i64);
auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64)); auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
Src64->initHiLo(Func); Src64->initHiLo(Func);
forceHiLoInReg(Src64); configureBitcastTemporary(Src64);
Variable *T = Src64->getLo(); lowerAssign(InstAssign::create(Func, Src64, Src0));
_mov(T, legalizeToReg(loOperand(Src0))); Variable *T = makeReg(IceType_f64);
T = Src64->getHi();
_mov(T, legalizeToReg(hiOperand(Src0)));
T = makeReg(IceType_f64);
Context.insert(InstFakeDef::create(Func, Src64));
_mov(T, Src64); _mov(T, Src64);
Context.insert(InstFakeUse::create(Func, Src64->getLo()));
Context.insert(InstFakeUse::create(Func, Src64->getHi()));
lowerAssign(InstAssign::create(Func, Dest, T)); lowerAssign(InstAssign::create(Func, Dest, T));
break; break;
} }
......
...@@ -280,13 +280,27 @@ protected: ...@@ -280,13 +280,27 @@ protected:
// an assert around just in case there is some untested code path where Dest // an assert around just in case there is some untested code path where Dest
// is nullptr. // is nullptr.
assert(Dest != nullptr); assert(Dest != nullptr);
Context.insert(InstARM32Mov::create(Func, Dest, Src0, Pred)); auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred);
Context.insert(Instr);
if (Instr->isMultiDest()) {
// If Instr is multi-dest, then Dest must be a Variable64On32. We add a
// fake-def for Instr.DestHi here.
assert(llvm::isa<Variable64On32>(Dest));
Context.insert(InstFakeDef::create(Func, Instr->getDestHi()));
}
} }
void _mov_redefined(Variable *Dest, Operand *Src0, void _mov_redefined(Variable *Dest, Operand *Src0,
CondARM32::Cond Pred = CondARM32::AL) { CondARM32::Cond Pred = CondARM32::AL) {
Inst *NewInst = InstARM32Mov::create(Func, Dest, Src0, Pred); auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred);
NewInst->setDestRedefined(); Instr->setDestRedefined();
Context.insert(NewInst); Context.insert(Instr);
if (Instr->isMultiDest()) {
// If Instr is multi-dest, then Dest must be a Variable64On32. We add a
// fake-def for Instr.DestHi here.
assert(llvm::isa<Variable64On32>(Dest));
Context.insert(InstFakeDef::create(Func, Instr->getDestHi()));
}
} }
/// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with
/// an upper16 relocation). /// an upper16 relocation).
......
...@@ -593,5 +593,5 @@ entry: ...@@ -593,5 +593,5 @@ entry:
; ARM32-LABEL: int64BitcastToDoubleConst ; ARM32-LABEL: int64BitcastToDoubleConst
; ARM32-DAG: movw [[REG0:r[0-9]+]], #57336 ; ARM32-DAG: movw [[REG0:r[0-9]+]], #57336
; ARM32-DAG: movt [[REG0]], #137 ; ARM32-DAG: movt [[REG0]], #137
; ARM32-DAG: movw [[REG1:r[0-9]+]], #0 ; ARM32-DAG: mov [[REG1:r[0-9]+]], #0
; ARM32-DAG: vmov d{{[0-9]+}}, [[REG0]], [[REG1]] ; ARM32-DAG: vmov d{{[0-9]+}}, [[REG0]], [[REG1]]
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