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

Unified Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2301303003: [SubZero] Implement load and store for MIPS (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 4 years, 3 months 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
Index: src/IceTargetLoweringMIPS32.cpp
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 3a41373aafe7a4f519320f95f934b99596912e6d..188555f2201b3e152a326418443d1cfa9046e497 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -389,6 +389,11 @@ void TargetMIPS32::translateOm1() {
return;
Func->dump("After stack frame mapping");
+ postLowerLegalization();
+ if (Func->hasError())
+ return;
+ Func->dump("After postLowerLegalization");
+
// Nop insertion
if (getFlags().getShouldDoNopInsertion()) {
Func->doNopInsertion();
@@ -496,13 +501,14 @@ OperandMIPS32Mem *TargetMIPS32::formMemoryOperand(Operand *Operand, Type Ty) {
// OperandMIPS32Mem, so in that case it wouldn't need another level of
// transformation.
if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) {
- return Mem;
+ return llvm::cast<OperandMIPS32Mem>(legalize(Mem));
}
// If we didn't do address mode optimization, then we only have a base/offset
// to work with. MIPS always requires a base register, so just use that to
// hold the operand.
- auto *Base = llvm::cast<Variable>(legalize(Operand, Legal_Reg));
+ auto *Base = llvm::cast<Variable>(
+ legalize(Operand, Legal_Reg | Legal_Rematerializable));
const int32_t Offset = Base->hasStackOffset() ? Base->getStackOffset() : 0;
return OperandMIPS32Mem::create(
Func, Ty, Base,
@@ -516,12 +522,17 @@ void TargetMIPS32::emitVariable(const Variable *Var) const {
const Type FrameSPTy = IceType_i32;
if (Var->hasReg()) {
Str << '$' << getRegName(Var->getRegNum(), Var->getType());
- } else {
- int32_t Offset = Var->getStackOffset();
- Str << Offset;
- Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy);
- Str << ")";
+ return;
+ }
+ if (Var->mustHaveReg()) {
+ llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName() +
+ ") has no register assigned - function " +
+ Func->getFunctionName());
}
+ const int32_t Offset = Var->getStackOffset();
+ Str << Offset;
+ Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy);
+ Str << ")";
}
TargetMIPS32::CallingConv::CallingConv()
@@ -1042,7 +1053,8 @@ Variable *TargetMIPS32::PostLoweringLegalizer::newBaseRegister(
Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum);
if (ShouldSub) {
Variable *OffsetVal =
- Target->legalizeToReg(Target->Ctx->getConstantInt32(-Offset));
+ Target->legalizeToReg(Target->Ctx->getConstantInt32(-Offset),
+ ScratchRegNum);
Target->_sub(ScratchReg, Base, OffsetVal);
} else {
Target->_addiu(ScratchReg, Base, Offset);
@@ -1055,7 +1067,6 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) {
Variable *Dest = MovInstr->getDest();
assert(Dest != nullptr);
const Type DestTy = Dest->getType();
- (void)DestTy;
assert(DestTy != IceType_i64);
Operand *Src = MovInstr->getSrc(0);
@@ -1067,30 +1078,82 @@ void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) {
return;
bool Legalized = false;
- if (Dest->hasReg()) {
- if (auto *Var = llvm::dyn_cast<Variable>(Src)) {
- if (Var->isRematerializable()) {
- // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable).
-
- // ExtraOffset is only needed for frame-pointer based frames as we have
- // to account for spill storage.
- const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg())
- ? Target->getFrameFixedAllocaOffset()
- : 0;
-
- const int32_t Offset = Var->getStackOffset() + ExtraOffset;
- Variable *Base = Target->getPhysicalRegister(Var->getRegNum());
- Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum());
- Target->_mov(Dest, T);
+ if (!Dest->hasReg()) {
+ auto *SrcR = llvm::cast<Variable>(Src);
+ assert(SrcR->hasReg());
+ assert(!SrcR->isRematerializable());
+ const int32_t Offset = Dest->getStackOffset();
+
+ // This is a _mov(Mem(), Variable), i.e., a store.
+ auto *Base = Target->getPhysicalRegister(
+ Target->getFrameOrStackReg());
+
+ OperandMIPS32Mem *Addr =
+ OperandMIPS32Mem::create(Target->Func, DestTy, Base,
+ llvm::cast<ConstantInteger32>(
+ Target->Ctx->getConstantInt32(Offset)));
+
+ // FP arguments are passed in GP reg if first argument is
Jim Stichnoth 2016/09/03 13:47:13 "is is in GP" ==> "is in GP" Also, maybe reflow c
jaydeep.patil 2016/09/04 06:24:30 Done.
+ // is in GP. In this case type of the SrcR is still FP thus
+ // we need to explicitly generate sw instead of swc1.
+ const RegNumT RegNum = SrcR->getRegNum();
+ const bool isSrcGPReg = ((unsigned)RegNum >= RegMIPS32::Reg_A0
+ && (unsigned)RegNum <= RegMIPS32::Reg_A3)
+ || ((unsigned)RegNum >= RegMIPS32::Reg_A0A1
+ && (unsigned)RegNum <= RegMIPS32::Reg_A2A3);
+ if (SrcTy == IceType_f32 && isSrcGPReg == true) {
+ Variable *SrcGPR = Target->makeReg(IceType_i32, RegNum);
+ Target->_sw(SrcGPR, Addr);
+ } else if (SrcTy == IceType_f64 && isSrcGPReg == true) {
+ Variable *SrcGPRHi, *SrcGPRLo;
+ if (RegNum == RegMIPS32::Reg_A0A1) {
+ SrcGPRLo = Target->makeReg(IceType_i32, RegMIPS32::Reg_A0);
+ SrcGPRHi = Target->makeReg(IceType_i32, RegMIPS32::Reg_A1);
+ } else {
+ SrcGPRLo = Target->makeReg(IceType_i32, RegMIPS32::Reg_A2);
+ SrcGPRHi = Target->makeReg(IceType_i32, RegMIPS32::Reg_A3);
+ }
+ OperandMIPS32Mem *AddrHi =
+ OperandMIPS32Mem::create(Target->Func, DestTy, Base,
+ llvm::cast<ConstantInteger32>(
+ Target->Ctx->getConstantInt32(Offset+4)));
+ Target->_sw(SrcGPRLo, Addr);
+ Target->_sw(SrcGPRHi, AddrHi);
+ } else {
+ Target->_sw(SrcR, Addr);
+ }
+
+ Target->Context.insert<InstFakeDef>(Dest);
+ Legalized = true;
+ } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) {
+ if (Var->isRematerializable()) {
+ // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable).
+
+ // ExtraOffset is only needed for frame-pointer based frames as we have
+ // to account for spill storage.
+ const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg())
+ ? Target->getFrameFixedAllocaOffset()
+ : 0;
+
+ const int32_t Offset = Var->getStackOffset() + ExtraOffset;
+ Variable *Base = Target->getPhysicalRegister(Var->getRegNum());
+ Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum());
+ Target->_mov(Dest, T);
+ Legalized = true;
+ } else {
+ if (!Var->hasReg()) {
+ // This is a _mov(Variable, Mem()), i.e., a load.
+ const int32_t Offset = Var->getStackOffset();
+ auto *Base = Target->getPhysicalRegister(
+ Target->getFrameOrStackReg());
+ OperandMIPS32Mem *Addr;
+ Addr = OperandMIPS32Mem::create(Target->Func, DestTy,
+ Base,
+ llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)));
+ Target->_lw(Dest, Addr);
Legalized = true;
- } else if (!Var->hasReg()) {
- UnimplementedError(getFlags());
- return;
}
}
- } else {
- UnimplementedError(getFlags());
- return;
}
if (Legalized) {
@@ -1562,7 +1625,6 @@ void TargetMIPS32::lowerAssign(const InstAssign *Instr) {
Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg);
auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
- // Variable *T_Lo = nullptr, *T_Hi = nullptr;
auto *T_Lo = I32Reg(), *T_Hi = I32Reg();
_mov(T_Lo, Src0Lo);
_mov(DestLo, T_Lo);
@@ -2242,7 +2304,13 @@ void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
}
void TargetMIPS32::lowerLoad(const InstLoad *Instr) {
- UnimplementedLoweringError(this, Instr);
+ // A Load instruction can be treated the same as an Assign instruction, after
+ // the source operand is transformed into an OperandARM32Mem operand.
+ Type Ty = Instr->getDest()->getType();
+ Operand *Src0 = formMemoryOperand(Instr->getSourceAddress(), Ty);
+ Variable *DestLoad = Instr->getDest();
+ auto *Assign = InstAssign::create(Func, DestLoad, Src0);
+ lowerAssign(Assign);
}
void TargetMIPS32::doAddressOptLoad() { UnimplementedError(getFlags()); }
@@ -2436,9 +2504,11 @@ Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) {
if (isVectorType(Ty)) {
UnimplementedError(getFlags());
} else {
- // Mov's Src operand can really only be the flexible second operand type
- // or a register. Users should guarantee that.
- _mov(Reg, Src);
+ if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Src)) {
+ _lw(Reg, Mem);
+ } else {
+ _mov(Reg, Src);
+ }
}
return Reg;
}
@@ -2450,11 +2520,59 @@ Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed,
// to legalize() allow a physical register. Legal_Flex converts
// registers to the right type OperandMIPS32FlexReg as needed.
assert(Allowed & Legal_Reg);
+
+ if (RegNum.hasNoValue()) {
+ if (Variable *Subst = getContext().availabilityGet(From)) {
+ // At this point we know there is a potential substitution available.
+ if (!Subst->isRematerializable() && Subst->mustHaveReg() &&
+ !Subst->hasReg()) {
+ // At this point we know the substitution will have a register.
+ if (From->getType() == Subst->getType()) {
+ // At this point we know the substitution's register is compatible.
+ return Subst;
+ }
+ }
+ }
+ }
+
// Go through the various types of operands:
// OperandMIPS32Mem, Constant, and Variable.
// Given the above assertion, if type of operand is not legal
// (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy
// to a register.
+ if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(From)) {
+ // Base must be in a physical register.
+ Variable *Base = Mem->getBase();
+ ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
+ Variable *RegBase = nullptr;
+ assert(Base);
+
+ RegBase = llvm::cast<Variable>(
+ legalize(Base, Legal_Reg | Legal_Rematerializable));
+
+ if (Offset != nullptr && Offset->getValue() != 0) {
+ static constexpr bool ZeroExt = false;
+ if (!OperandMIPS32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) {
+ llvm::report_fatal_error("Invalid memory offset.");
+ }
+ }
+
+ // Create a new operand if there was a change.
+ if (Base != RegBase) {
+ Mem = OperandMIPS32Mem::create(Func, Ty, RegBase, Offset,
+ Mem->getAddrMode());
+ }
+
+ if (Allowed & Legal_Mem) {
+ From = Mem;
+ } else {
+ Variable *Reg = makeReg(Ty, RegNum);
+ _lw(Reg, Mem);
+ From = Reg;
+ }
+ return From;
+ }
+
if (llvm::isa<Constant>(From)) {
if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) {
(void)C;
@@ -2511,6 +2629,15 @@ Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed,
}
if (auto *Var = llvm::dyn_cast<Variable>(From)) {
+ if (Var->isRematerializable()) {
+ if (Allowed & Legal_Rematerializable) {
+ return From;
+ }
+
+ Variable *T = makeReg(Var->getType(), RegNum);
+ _mov(T, Var);
+ return T;
+ }
// Check if the variable is guaranteed a physical register. This
// can happen either when the variable is pre-colored or when it is
// assigned infinite weight.

Powered by Google App Engine
This is Rietveld 408576698