[SubZero] Legalize load, store for MIPS post lower
This patch legalizes load, store instructions post lowering.
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/2411193003 .
Patch from Jaydeep Patil <jaydeep.patil@imgtec.com>.
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 331f1ed..7f501ef 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -1529,7 +1529,17 @@
Target->Ctx->getConstantInt32(-Offset), ScratchRegNum);
Target->_sub(ScratchReg, Base, OffsetVal);
} else {
- Target->_addiu(ScratchReg, Base, Offset);
+ constexpr bool SignExt = true;
+ if (!OperandMIPS32Mem::canHoldOffset(Base->getType(), SignExt, Offset)) {
+ const uint32_t UpperBits = (Offset >> 16) & 0xFFFF;
+ const uint32_t LowerBits = Offset & 0xFFFF;
+ Target->_lui(ScratchReg, Target->Ctx->getConstantInt32(UpperBits));
+ if (LowerBits)
+ Target->_ori(ScratchReg, ScratchReg, LowerBits);
+ Target->_addu(ScratchReg, ScratchReg, Base);
+ } else {
+ Target->_addiu(ScratchReg, Base, Offset);
+ }
}
return ScratchReg;
@@ -1731,6 +1741,35 @@
}
}
+OperandMIPS32Mem *
+TargetMIPS32::PostLoweringLegalizer::legalizeMemOperand(OperandMIPS32Mem *Mem) {
+ if (llvm::isa<ConstantRelocatable>(Mem->getOffset())) {
+ return nullptr;
+ }
+ Variable *Base = Mem->getBase();
+ auto *Ci32 = llvm::cast<ConstantInteger32>(Mem->getOffset());
+ int32_t Offset = Ci32->getValue();
+
+ if (Base->isRematerializable()) {
+ const int32_t ExtraOffset =
+ (Base->getRegNum() == Target->getFrameOrStackReg())
+ ? Target->getFrameFixedAllocaOffset()
+ : 0;
+ Offset += Base->getStackOffset() + ExtraOffset;
+ Base = Target->getPhysicalRegister(Base->getRegNum());
+ }
+
+ constexpr bool SignExt = true;
+ if (!OperandMIPS32Mem::canHoldOffset(Mem->getType(), SignExt, Offset)) {
+ Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg());
+ Offset = 0;
+ }
+
+ return OperandMIPS32Mem::create(
+ Target->Func, Mem->getType(), Base,
+ llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)));
+}
+
void TargetMIPS32::postLowerLegalization() {
Func->dump("Before postLowerLegalization");
assert(hasComputedFrame());
@@ -1740,11 +1779,58 @@
while (!Context.atEnd()) {
PostIncrLoweringContext PostIncrement(Context);
Inst *CurInstr = iteratorToInst(Context.getCur());
-
- // TODO(sagar.thakur): Add remaining cases of legalization.
-
+ const SizeT NumSrcs = CurInstr->getSrcSize();
+ Operand *Src0 = NumSrcs < 1 ? nullptr : CurInstr->getSrc(0);
+ Operand *Src1 = NumSrcs < 2 ? nullptr : CurInstr->getSrc(1);
+ auto *Src0V = llvm::dyn_cast_or_null<Variable>(Src0);
+ auto *Src0M = llvm::dyn_cast_or_null<OperandMIPS32Mem>(Src0);
+ auto *Src1M = llvm::dyn_cast_or_null<OperandMIPS32Mem>(Src1);
+ Variable *Dst = CurInstr->getDest();
if (auto *MovInstr = llvm::dyn_cast<InstMIPS32Mov>(CurInstr)) {
Legalizer.legalizeMov(MovInstr);
+ continue;
+ }
+ if (llvm::isa<InstMIPS32Sw>(CurInstr)) {
+ if (auto *LegalMem = Legalizer.legalizeMemOperand(Src1M)) {
+ _sw(Src0V, LegalMem);
+ CurInstr->setDeleted();
+ }
+ continue;
+ }
+ if (llvm::isa<InstMIPS32Swc1>(CurInstr)) {
+ if (auto *LegalMem = Legalizer.legalizeMemOperand(Src1M)) {
+ _swc1(Src0V, LegalMem);
+ CurInstr->setDeleted();
+ }
+ continue;
+ }
+ if (llvm::isa<InstMIPS32Sdc1>(CurInstr)) {
+ if (auto *LegalMem = Legalizer.legalizeMemOperand(Src1M)) {
+ _sdc1(Src0V, LegalMem);
+ CurInstr->setDeleted();
+ }
+ continue;
+ }
+ if (llvm::isa<InstMIPS32Lw>(CurInstr)) {
+ if (auto *LegalMem = Legalizer.legalizeMemOperand(Src0M)) {
+ _lw(Dst, LegalMem);
+ CurInstr->setDeleted();
+ }
+ continue;
+ }
+ if (llvm::isa<InstMIPS32Lwc1>(CurInstr)) {
+ if (auto *LegalMem = Legalizer.legalizeMemOperand(Src0M)) {
+ _lwc1(Dst, LegalMem);
+ CurInstr->setDeleted();
+ }
+ continue;
+ }
+ if (llvm::isa<InstMIPS32Ldc1>(CurInstr)) {
+ if (auto *LegalMem = Legalizer.legalizeMemOperand(Src0M)) {
+ _ldc1(Dst, LegalMem);
+ CurInstr->setDeleted();
+ }
+ continue;
}
}
}
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 842f266..01f68ca 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -90,6 +90,7 @@
RegNumT getFrameOrStackReg() const override {
return UsesFramePointer ? getFrameReg() : getStackReg();
}
+ RegNumT getReservedTmpReg() const { return RegMIPS32::Reg_AT; }
size_t typeWidthInBytesOnStack(Type Ty) const override {
// Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
// are rounded up to 4 bytes.
@@ -726,6 +727,10 @@
: Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
Target->getFrameOrStackReg())) {}
+ /// Legalizes Mem. if Mem.Base is a rematerializable variable,
+ /// Mem.Offset is fixed up.
+ OperandMIPS32Mem *legalizeMemOperand(OperandMIPS32Mem *Mem);
+
/// 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.)
diff --git a/tests_lit/llvm2ice_tests/mips-legalization.ll b/tests_lit/llvm2ice_tests/mips-legalization.ll
new file mode 100644
index 0000000..cc9414d
--- /dev/null
+++ b/tests_lit/llvm2ice_tests/mips-legalization.ll
@@ -0,0 +1,84 @@
+; This file checks support for legalization in MIPS.
+
+; REQUIRES: allow_dump
+
+; RUN: %if --need=target_MIPS32 \
+; RUN: --command %p2i --filetype=asm --assemble --disassemble \
+; RUN: --target mips32 -i %s --args -O2 \
+; RUN: | %if --need=target_MIPS32 \
+; RUN: --command FileCheck --check-prefix MIPS32 %s
+
+define internal i32 @legalization(i32 %a, i32 %b, i32 %c, i32 %d,
+ i32 %e, i32 %f) {
+entry:
+ %a.addr = alloca i8, i32 4, align 4
+ %b.addr = alloca i8, i32 4, align 4
+ %c.addr = alloca i8, i32 4, align 4
+ %d.addr = alloca i8, i32 4, align 4
+ %e.addr = alloca i8, i32 4, align 4
+ %f.addr = alloca i8, i32 4, align 4
+ %r1 = alloca i8, i32 4, align 4
+ %r2 = alloca i8, i32 4, align 4
+ %r3 = alloca i8, i32 4, align 4
+ %a.addr.bc = bitcast i8* %a.addr to i32*
+ store i32 %a, i32* %a.addr.bc, align 1
+ %b.addr.bc = bitcast i8* %b.addr to i32*
+ store i32 %b, i32* %b.addr.bc, align 1
+ %c.addr.bc = bitcast i8* %c.addr to i32*
+ store i32 %c, i32* %c.addr.bc, align 1
+ %d.addr.bc = bitcast i8* %d.addr to i32*
+ store i32 %d, i32* %d.addr.bc, align 1
+ %e.addr.bc = bitcast i8* %e.addr to i32*
+ store i32 %e, i32* %e.addr.bc, align 1
+ %f.addr.bc = bitcast i8* %f.addr to i32*
+ store i32 %f, i32* %f.addr.bc, align 1
+ %a.addr.bc1 = bitcast i8* %a.addr to i32*
+ %0 = load i32, i32* %a.addr.bc1, align 1
+ %f.addr.bc2 = bitcast i8* %f.addr to i32*
+ %1 = load i32, i32* %f.addr.bc2, align 1
+ %add = add i32 %0, %1
+ %r1.bc = bitcast i8* %r1 to i32*
+ store i32 %add, i32* %r1.bc, align 1
+ %b.addr.bc3 = bitcast i8* %b.addr to i32*
+ %2 = load i32, i32* %b.addr.bc3, align 1
+ %e.addr.bc4 = bitcast i8* %e.addr to i32*
+ %3 = load i32, i32* %e.addr.bc4, align 1
+ %add1 = add i32 %2, %3
+ %r2.bc = bitcast i8* %r2 to i32*
+ store i32 %add1, i32* %r2.bc, align 1
+ %r1.bc5 = bitcast i8* %r1 to i32*
+ %4 = load i32, i32* %r1.bc5, align 1
+ %r2.bc6 = bitcast i8* %r2 to i32*
+ %5 = load i32, i32* %r2.bc6, align 1
+ %add2 = add i32 %4, %5
+ %r3.bc = bitcast i8* %r3 to i32*
+ store i32 %add2, i32* %r3.bc, align 1
+ %r3.bc7 = bitcast i8* %r3 to i32*
+ %6 = load i32, i32* %r3.bc7, align 1
+ ret i32 %6
+}
+; MIPS32-LABEL: legalization
+; MIPS32: addiu sp,sp,-48
+; MIPS32: lw [[ARG_E:.*]],64(sp)
+; MIPS32: lw [[ARG_F:.*]],68(sp)
+; MIPS32: sw a0,0(sp)
+; MIPS32: sw a1,4(sp)
+; MIPS32: sw a2,8(sp)
+; MIPS32: sw a3,12(sp)
+; MIPS32: sw [[ARG_E]],16(sp)
+; MIPS32: sw [[ARG_F]],20(sp)
+; MIPS32: lw [[TMP_A:.*]],0(sp)
+; MIPS32: lw [[TMP_F:.*]],20(sp)
+; MIPS32: addu [[ADD1:.*]],[[TMP_A]],[[TMP_F]]
+; MIPS32: sw [[ADD1]],24(sp)
+; MIPS32: lw [[TMP_B:.*]],4(sp)
+; MIPS32: lw [[TMP_E:.*]],16(sp)
+; MIPS32: addu [[ADD2:.*]],[[TMP_B]],[[TMP_E]]
+; MIPS32: sw [[ADD2]],28(sp)
+; MIPS32: lw [[TMP_ADD1:.*]],24(sp)
+; MIPS32: lw [[TMP_ADD2:.*]],28(sp)
+; MIPS32: addu [[ADD3:.*]],[[TMP_ADD1]],[[TMP_ADD2]]
+; MIPS32: sw [[ADD3]],32(sp)
+; MIPS32: lw v0,32(sp)
+; MIPS32: addiu sp,sp,48
+; MIPS32: jr ra