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,
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,
CondARM32::Cond Predicate)
: InstARM32Pred(Func, InstARM32::Vcmp, 2, nullptr, Predicate) {
......@@ -451,19 +473,19 @@ void InstARM32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
auto *Dest = llvm::cast<Variable64On32>(getDest());
Operand *Src = getSrc(0);
Variable *DestLo = getDest();
Variable *DestHi = getDestHi();
auto *Src = llvm::cast<Variable>(getSrc(0));
assert(Dest->getType() == IceType_i64);
assert(Dest->getHi()->hasReg());
assert(Dest->getLo()->hasReg());
assert(!llvm::isa<OperandARM32Mem>(Src));
assert(DestHi->hasReg());
assert(DestLo->hasReg());
assert(llvm::isa<Variable>(Src) && Src->hasReg());
Str << "\t"
<< "vmov" << getPredicate() << "\t";
Dest->getLo()->emit(Func);
DestLo->emit(Func);
Str << ", ";
Dest->getHi()->emit(Func);
DestHi->emit(Func);
Str << ", ";
Src->emit(Func);
}
......@@ -473,20 +495,20 @@ void InstARM32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
return;
Ostream &Str = Func->getContext()->getStrEmit();
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(Src->getHi()->hasReg());
assert(Src->getLo()->hasReg());
assert(SrcHi->hasReg());
assert(SrcLo->hasReg());
assert(Dest->hasReg());
Str << "\t"
<< "vmov" << getPredicate() << "\t";
Dest->emit(Func);
Str << ", ";
Src->getLo()->emit(Func);
SrcLo->emit(Func);
Str << ", ";
Src->getHi()->emit(Func);
SrcHi->emit(Func);
}
namespace {
......@@ -583,28 +605,20 @@ void InstARM32Mov::emitIAS(const Cfg *Func) const {
void InstARM32Mov::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
assert(getSrcSize() == 1);
assert(getSrcSize() == 1 || getSrcSize() == 2);
Ostream &Str = Func->getContext()->getStrDump();
Variable *Dest = getDest();
if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) {
Dest64->getLo()->dump(Func);
Variable *DestHi = getDestHi();
Dest->dump(Func);
if (DestHi) {
Str << ", ";
Dest64->getHi()->dump(Func);
} else {
Dest->dump(Func);
DestHi->dump(Func);
}
dumpOpcodePred(Str, " = mov", getDest()->getType());
Str << " ";
Operand *Src = getSrc(0);
if (auto *Src64 = llvm::dyn_cast<Variable64On32>(Src)) {
Src64->getLo()->dump(Func);
Str << ", ";
Src64->getHi()->dump(Func);
} else {
Src->dump(Func);
}
dumpSources(Func);
}
void InstARM32Br::emit(const Cfg *Func) const {
......
......@@ -1133,26 +1133,24 @@ public:
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
bool isMultiDest() const {
assert(getDest() != nullptr);
return llvm::isa<Variable64On32>(getDest());
}
bool isMultiDest() const { return DestHi != nullptr; }
bool isMultiSource() const {
assert(getSrcSize() == 1);
return llvm::isa<Variable64On32>(getSrc(0));
assert(getSrcSize() == 1 || getSrcSize() == 2);
return getSrcSize() == 2;
}
Variable *getDestHi() const { return DestHi; }
private:
InstARM32Mov(Cfg *Func, Variable *Dest, Operand *Src,
CondARM32::Cond Predicate)
: InstARM32Pred(Func, InstARM32::Mov, 1, Dest, Predicate) {
addSource(Src);
}
CondARM32::Cond Predicate);
void emitMultiDestSingleSource(const Cfg *Func) const;
void emitSingleDestMultiSource(const Cfg *Func) const;
void emitSingleDestSingleSource(const Cfg *Func) const;
Variable *DestHi = nullptr;
};
class InstARM32Vcmp final : public InstARM32Pred {
......
......@@ -441,13 +441,7 @@ void TargetARM32::emitVariable(const Variable *Var) const {
Offset += getStackAdjustment();
}
const Type VarTy = Var->getType();
// In general, no Variable64On32 should be emited in textual asm output. It
// 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)) {
if (!isLegalVariableStackOffset(VarTy, Offset)) {
llvm::report_fatal_error("Illegal stack offset");
}
Str << "[" << getRegName(BaseRegNum, VarTy);
......@@ -684,8 +678,14 @@ void TargetARM32::addProlog(CfgNode *Node) {
uint32_t SpillAreaAlignmentBytes = 0;
// For now, we don't have target-specific variables that need special
// treatment (no stack-slot-linked SpillVariable type).
std::function<bool(Variable *)> TargetVarHook =
[](Variable *) { return false; };
std::function<bool(Variable *)> TargetVarHook = [](Variable *Var) {
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.
getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize,
......@@ -1979,7 +1979,8 @@ void TargetARM32::lowerCall(const InstCall *Instr) {
}
namespace {
void forceHiLoInReg(Variable64On32 *Var) {
void configureBitcastTemporary(Variable64On32 *Var) {
Var->setMustNotHaveReg();
Var->getHi()->setMustHaveReg();
Var->getLo()->setMustHaveReg();
}
......@@ -2265,15 +2266,12 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
assert(Src0->getType() == IceType_f64);
auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
T->initHiLo(Func);
forceHiLoInReg(T);
configureBitcastTemporary(T);
Variable *Src0R = legalizeToReg(Src0);
_mov(T, Src0R);
Context.insert(InstFakeDef::create(Func, T->getLo()));
Context.insert(InstFakeDef::create(Func, T->getHi()));
auto *Dest64On32 = llvm::cast<Variable64On32>(Dest);
lowerAssign(InstAssign::create(Func, Dest64On32->getLo(), T->getLo()));
lowerAssign(InstAssign::create(Func, Dest64On32->getHi(), T->getHi()));
Context.insert(InstFakeUse::create(Func, T));
break;
}
case IceType_f64: {
......@@ -2284,16 +2282,10 @@ void TargetARM32::lowerCast(const InstCast *Inst) {
assert(Src0->getType() == IceType_i64);
auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
Src64->initHiLo(Func);
forceHiLoInReg(Src64);
Variable *T = Src64->getLo();
_mov(T, legalizeToReg(loOperand(Src0)));
T = Src64->getHi();
_mov(T, legalizeToReg(hiOperand(Src0)));
T = makeReg(IceType_f64);
Context.insert(InstFakeDef::create(Func, Src64));
configureBitcastTemporary(Src64);
lowerAssign(InstAssign::create(Func, Src64, Src0));
Variable *T = makeReg(IceType_f64);
_mov(T, Src64);
Context.insert(InstFakeUse::create(Func, Src64->getLo()));
Context.insert(InstFakeUse::create(Func, Src64->getHi()));
lowerAssign(InstAssign::create(Func, Dest, T));
break;
}
......
......@@ -280,13 +280,27 @@ protected:
// an assert around just in case there is some untested code path where Dest
// is 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,
CondARM32::Cond Pred = CondARM32::AL) {
Inst *NewInst = InstARM32Mov::create(Func, Dest, Src0, Pred);
NewInst->setDestRedefined();
Context.insert(NewInst);
auto *Instr = InstARM32Mov::create(Func, Dest, Src0, Pred);
Instr->setDestRedefined();
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
/// an upper16 relocation).
......
......@@ -593,5 +593,5 @@ entry:
; ARM32-LABEL: int64BitcastToDoubleConst
; ARM32-DAG: movw [[REG0:r[0-9]+]], #57336
; 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]]
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