Commit 5674c915 by Sagar Thakur Committed by Jim Stichnoth

[Subzero][MIPS32] Implement post lower legalizer for MIPS32

BUG=none R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2148593003 . Patch from Sagar Thakur <sagar.thakur@imgtec.com>.
parent f0f80654
...@@ -295,6 +295,11 @@ void TargetMIPS32::translateO2() { ...@@ -295,6 +295,11 @@ void TargetMIPS32::translateO2() {
return; return;
Func->dump("After stack frame mapping"); Func->dump("After stack frame mapping");
postLowerLegalization();
if (Func->hasError())
return;
Func->dump("After postLowerLegalization");
Func->contractEmptyNodes(); Func->contractEmptyNodes();
Func->reorderNodes(); Func->reorderNodes();
...@@ -989,6 +994,92 @@ void TargetMIPS32::addEpilog(CfgNode *Node) { ...@@ -989,6 +994,92 @@ void TargetMIPS32::addEpilog(CfgNode *Node) {
return; return;
} }
Variable *TargetMIPS32::PostLoweringLegalizer::newBaseRegister(
Variable *Base, int32_t Offset, RegNumT ScratchRegNum) {
// Legalize will likely need a lui/ori combination, but if the top bits are
// all 0 from negating the offset and subtracting, we could use that instead.
const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0;
Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum);
if (ShouldSub) {
Variable *OffsetVal =
Target->legalizeToReg(Target->Ctx->getConstantInt32(-Offset));
Target->_sub(ScratchReg, Base, OffsetVal);
} else {
Target->_addiu(ScratchReg, Base, Offset);
}
return ScratchReg;
}
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);
const Type SrcTy = Src->getType();
(void)SrcTy;
assert(SrcTy != IceType_i64);
if (MovInstr->isMultiDest() || MovInstr->isMultiSource())
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);
Legalized = true;
} else if (!Var->hasReg()) {
UnimplementedError(getFlags());
return;
}
}
} else {
UnimplementedError(getFlags());
return;
}
if (Legalized) {
if (MovInstr->isDestRedefined()) {
Target->_set_dest_redefined();
}
MovInstr->setDeleted();
}
}
void TargetMIPS32::postLowerLegalization() {
Func->dump("Before postLowerLegalization");
assert(hasComputedFrame());
for (CfgNode *Node : Func->getNodes()) {
Context.init(Node);
PostLoweringLegalizer Legalizer(this);
while (!Context.atEnd()) {
PostIncrLoweringContext PostIncrement(Context);
Inst *CurInstr = iteratorToInst(Context.getCur());
// TODO(sagar.thakur): Add remaining cases of legalization.
if (auto *MovInstr = llvm::dyn_cast<InstMIPS32Mov>(CurInstr)) {
Legalizer.legalizeMov(MovInstr);
}
}
}
}
Operand *TargetMIPS32::loOperand(Operand *Operand) { Operand *TargetMIPS32::loOperand(Operand *Operand) {
assert(Operand->getType() == IceType_i64); assert(Operand->getType() == IceType_i64);
if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
...@@ -1417,6 +1508,12 @@ void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) { ...@@ -1417,6 +1508,12 @@ void TargetMIPS32::lowerArithmetic(const InstArithmetic *Instr) {
void TargetMIPS32::lowerAssign(const InstAssign *Instr) { void TargetMIPS32::lowerAssign(const InstAssign *Instr) {
Variable *Dest = Instr->getDest(); Variable *Dest = Instr->getDest();
if (Dest->isRematerializable()) {
Context.insert<InstFakeDef>(Dest);
return;
}
Operand *Src0 = Instr->getSrc(0); Operand *Src0 = Instr->getSrc(0);
assert(Dest->getType() == Src0->getType()); assert(Dest->getType() == Src0->getType());
if (Dest->getType() == IceType_i64) { if (Dest->getType() == IceType_i64) {
......
...@@ -461,6 +461,8 @@ public: ...@@ -461,6 +461,8 @@ public:
// the outargs area // the outargs area
void findMaxStackOutArgsSize(); void findMaxStackOutArgsSize();
void postLowerLegalization();
void addProlog(CfgNode *Node) override; void addProlog(CfgNode *Node) override;
void addEpilog(CfgNode *Node) override; void addEpilog(CfgNode *Node) override;
...@@ -559,6 +561,32 @@ protected: ...@@ -559,6 +561,32 @@ protected:
OperandMIPS32Mem *formMemoryOperand(Operand *Ptr, Type Ty); OperandMIPS32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
class PostLoweringLegalizer {
PostLoweringLegalizer() = delete;
PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
public:
explicit PostLoweringLegalizer(TargetMIPS32 *Target)
: Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
Target->getFrameOrStackReg())) {}
/// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
/// if its Source is a Rematerializable variable (this form is used in lieu
/// of lea, which is not available in MIPS.)
///
/// Moves to memory become store instructions, and moves from memory, loads.
void legalizeMov(InstMIPS32Mov *Mov);
private:
/// Creates a new Base register centered around [Base, +/- Offset].
Variable *newBaseRegister(Variable *Base, int32_t Offset,
RegNumT ScratchRegNum);
TargetMIPS32 *const Target;
Variable *const StackOrFrameReg;
};
bool UsesFramePointer = false; bool UsesFramePointer = false;
bool NeedsStackAlignment = false; bool NeedsStackAlignment = false;
bool MaybeLeafFunc = true; bool MaybeLeafFunc = true;
......
...@@ -66,7 +66,12 @@ entry: ...@@ -66,7 +66,12 @@ entry:
; MIPS32-LABEL: fixed_416_align_16 ; MIPS32-LABEL: fixed_416_align_16
; MIPS32-OPT2: addiu sp,sp,-440 ; MIPS32-OPT2: addiu sp,sp,-440
; MIPS32-OPT2: addiu a0,sp,16
; MIPS32-OPTM1: addiu sp,sp,-448 ; MIPS32-OPTM1: addiu sp,sp,-448
; MIPS32-OPTM1: addiu [[REG:.*]],sp,16
; MIPS32-OPTM1: sw [[REG]],{{.*}}
; MIPS32-OPTM1: lw a0,{{.*}}
; MIPS32: jal {{.*}} R_{{.*}} f1
define internal void @fixed_416_align_32(i32 %n) { define internal void @fixed_416_align_32(i32 %n) {
entry: entry:
...@@ -92,7 +97,12 @@ entry: ...@@ -92,7 +97,12 @@ entry:
; MIPS32-LABEL: fixed_416_align_32 ; MIPS32-LABEL: fixed_416_align_32
; MIPS32-OPT2: addiu sp,sp,-440 ; MIPS32-OPT2: addiu sp,sp,-440
; MIPS32-OPT2: addiu a0,sp,16
; MIPS32-OPTM1: addiu sp,sp,-448 ; MIPS32-OPTM1: addiu sp,sp,-448
; MIPS32-OPTM1: addiu [[REG:.*]],sp,16
; MIPS32-OPTM1: sw [[REG]],{{.*}}
; MIPS32-OPTM1: lw a0,{{.*}}
; MIPS32: jal {{.*}} R_{{.*}} f1
; Show that the amount to allocate will be rounded up. ; Show that the amount to allocate will be rounded up.
define internal void @fixed_351_align_16(i32 %n) { define internal void @fixed_351_align_16(i32 %n) {
...@@ -121,7 +131,12 @@ entry: ...@@ -121,7 +131,12 @@ entry:
; MIPS32-LABEL: fixed_351_align_16 ; MIPS32-LABEL: fixed_351_align_16
; MIPS32-OPT2: addiu sp,sp,-376 ; MIPS32-OPT2: addiu sp,sp,-376
; MIPS32-OPT2: addiu a0,sp,16
; MIPS32-OPTM1: addiu sp,sp,-384 ; MIPS32-OPTM1: addiu sp,sp,-384
; MIPS32-OPTM1: addiu [[REG:.*]],sp,16
; MIPS32-OPTM1: sw [[REG]],{{.*}}
; MIPS32-OPTM1: lw a0,{{.*}}
; MIPS32: jal {{.*}} R_{{.*}} f1
define internal void @fixed_351_align_32(i32 %n) { define internal void @fixed_351_align_32(i32 %n) {
entry: entry:
...@@ -147,7 +162,12 @@ entry: ...@@ -147,7 +162,12 @@ entry:
; MIPS32-LABEL: fixed_351_align_32 ; MIPS32-LABEL: fixed_351_align_32
; MIPS32-OPT2: addiu sp,sp,-376 ; MIPS32-OPT2: addiu sp,sp,-376
; MIPS32-OPT2: addiu a0,sp,16
; MIPS32-OPTM1: addiu sp,sp,-384 ; MIPS32-OPTM1: addiu sp,sp,-384
; MIPS32-OPTM1: addiu [[REG:.*]],sp,16
; MIPS32-OPTM1: sw [[REG]],{{.*}}
; MIPS32-OPTM1: lw a0,{{.*}}
; MIPS32: jal {{.*}} R_{{.*}} f1
declare void @f1(i32 %ignored) declare void @f1(i32 %ignored)
......
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