Commit f3bc5cf7 by Mohit Bhakkad Committed by Jim Stichnoth

- This patch implements lowerstore for i32, i64 types for mips32 arch.

- InstMIPS32Memory class is added to represent memory related instructions(load/store). I will add remaining load/store instructions if you are okay with this patch. - Changed uncond_br.ll test as it was failing due to hardcoded label no. expected in output. R=jpp@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/2005823002 . Patch from Mohit Bhakkad <mohit.bhakkad@imgtec.com>.
parent e160ed92
......@@ -103,6 +103,7 @@ template <> const char *InstMIPS32Sub::Opcode = "sub";
template <> const char *InstMIPS32Sub_d::Opcode = "sub.d";
template <> const char *InstMIPS32Sub_s::Opcode = "sub.s";
template <> const char *InstMIPS32Subu::Opcode = "subu";
template <> const char *InstMIPS32Sw::Opcode = "sw";
template <> const char *InstMIPS32Xor::Opcode = "xor";
template <> const char *InstMIPS32Xori::Opcode = "xori";
......@@ -244,8 +245,12 @@ void InstMIPS32::dump(const Cfg *Func) const {
void OperandMIPS32Mem::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
llvm_unreachable("Not yet implemented");
(void)Func;
Ostream &Str = Func->getContext()->getStrEmit();
ConstantInteger32 *Offset = getOffset();
Offset->emit(Func);
Str << "(";
getBase()->emit(Func);
Str << ")";
}
void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
......
......@@ -165,6 +165,7 @@ public:
Sub_d,
Sub_s,
Subu,
Sw,
Xor,
Xori
};
......@@ -459,6 +460,58 @@ private:
static const char *Opcode;
};
// InstMIPS32Memory represents instructions which loads/stores data on memory
// Its format is "OPCODE GPR, OFFSET(BASE GPR)"
template <InstMIPS32::InstKindMIPS32 K>
class InstMIPS32Memory : public InstMIPS32 {
InstMIPS32Memory() = delete;
InstMIPS32Memory(const InstMIPS32Memory &) = delete;
InstMIPS32Memory &operator=(const InstMIPS32Memory &) = delete;
public:
static InstMIPS32Memory *create(Cfg *Func, Variable *Value,
OperandMIPS32Mem *Mem) {
return new (Func->allocate<InstMIPS32Memory>())
InstMIPS32Memory(Func, Value, Mem);
}
void emit(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 2);
Str << "\t" << Opcode << "\t";
getSrc(0)->emit(Func);
Str << ", ";
getSrc(1)->emit(Func);
}
void emitIAS(const Cfg *Func) const override {
(void)Func;
llvm_unreachable("Not yet implemented");
}
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
Str << "\t" << Opcode << "\t";
Str << " ";
getSrc(1)->dump(Func);
Str << ", ";
getSrc(0)->dump(Func);
}
static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
private:
InstMIPS32Memory(Cfg *Func, Variable *Value, OperandMIPS32Mem *Mem)
: InstMIPS32(Func, K, 2, nullptr) {
addSource(Value);
addSource(Mem);
}
static const char *Opcode;
};
// InstMIPS32Label represents an intra-block label that is the target of an
// intra-block branch. The offset between the label and the branch must be fit
// in the instruction immediate (considered "near").
......@@ -690,6 +743,7 @@ using InstMIPS32Sub = InstMIPS32ThreeAddrGPR<InstMIPS32::Sub>;
using InstMIPS32Sub_d = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_d>;
using InstMIPS32Sub_s = InstMIPS32ThreeAddrFPR<InstMIPS32::Sub_s>;
using InstMIPS32Subu = InstMIPS32ThreeAddrGPR<InstMIPS32::Subu>;
using InstMIPS32Sw = InstMIPS32Memory<InstMIPS32::Sw>;
using InstMIPS32Ori = InstMIPS32Imm16<InstMIPS32::Ori>;
using InstMIPS32Xor = InstMIPS32ThreeAddrGPR<InstMIPS32::Xor>;
using InstMIPS32Xori = InstMIPS32Imm16<InstMIPS32::Xori>;
......
......@@ -372,6 +372,23 @@ Variable *TargetMIPS32::makeReg(Type Type, RegNumT RegNum) {
return Reg;
}
OperandMIPS32Mem *TargetMIPS32::formMemoryOperand(Operand *Operand, Type Ty) {
// It may be the case that address mode optimization already creates an
// OperandMIPS32Mem, so in that case it wouldn't need another level of
// transformation.
if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) {
return 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));
return OperandMIPS32Mem::create(
Func, Ty, Base,
llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)));
}
void TargetMIPS32::emitVariable(const Variable *Var) const {
if (!BuildDefs::dump())
return;
......@@ -1427,7 +1444,21 @@ void TargetMIPS32::lowerShuffleVector(const InstShuffleVector *Instr) {
}
void TargetMIPS32::lowerStore(const InstStore *Instr) {
UnimplementedLoweringError(this, Instr);
Operand *Value = Instr->getData();
Operand *Addr = Instr->getAddr();
OperandMIPS32Mem *NewAddr = formMemoryOperand(Addr, Value->getType());
Type Ty = NewAddr->getType();
if (Ty == IceType_i64) {
Value = legalizeUndef(Value);
Variable *ValueHi = legalizeToReg(hiOperand(Value));
Variable *ValueLo = legalizeToReg(loOperand(Value));
_sw(ValueHi, llvm::cast<OperandMIPS32Mem>(hiOperand(NewAddr)));
_sw(ValueLo, llvm::cast<OperandMIPS32Mem>(loOperand(NewAddr)));
} else {
Variable *ValueR = legalizeToReg(Value);
_sw(ValueR, NewAddr);
}
}
void TargetMIPS32::doAddressOptStore() { UnimplementedError(getFlags()); }
......
......@@ -117,8 +117,10 @@ public:
void emitVariable(const Variable *Var) const override;
void emit(const ConstantInteger32 *C) const final {
(void)C;
llvm::report_fatal_error("Not yet implemented");
if (!BuildDefs::dump())
return;
Ostream &Str = Ctx->getStrEmit();
Str << C->getValue();
}
void emit(const ConstantInteger64 *C) const final {
(void)C;
......@@ -341,6 +343,10 @@ public:
Context.insert<InstMIPS32Subu>(Dest, Src0, Src1);
}
void _sw(Variable *Value, OperandMIPS32Mem *Mem) {
Context.insert<InstMIPS32Sw>(Value, Mem);
}
void _xor(Variable *Dest, Variable *Src0, Variable *Src1) {
Context.insert<InstMIPS32Xor>(Dest, Src0, Src1);
}
......@@ -440,6 +446,8 @@ protected:
const SmallBitVector &ExcludeRegisters,
uint64_t Salt) const override;
OperandMIPS32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
bool UsesFramePointer = false;
bool NeedsStackAlignment = false;
static SmallBitVector TypeToRegisterSet[RCMIPS32_NUM];
......
......@@ -4,6 +4,13 @@
; RUN: %p2i -i %s --args --verbose inst -threads=0 | FileCheck %s
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble \
; RUN: --disassemble --target mips32 -i %s --args -O2 --skip-unimplemented \
; RUN: -allow-externally-defined-symbols \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix MIPS32 %s
define internal void @store_i64(i32 %addr_arg) {
entry:
%__1 = inttoptr i32 %addr_arg to i64*
......@@ -15,6 +22,11 @@ entry:
; CHECK-NEXT: store i64 1, i64* %addr_arg, align 1
; CHECK-NEXT: ret void
}
; MIPS32-LABEL: store_i64
; MIPS32: li
; MIPS32: li
; MIPS32: sw
; MIPS32: sw
define internal void @store_i32(i32 %addr_arg) {
entry:
......@@ -27,6 +39,9 @@ entry:
; CHECK-NEXT: store i32 1, i32* %addr_arg, align 1
; CHECK-NEXT: ret void
}
; MIPS32-LABEL: store_i32
; MIPS32: li
; MIPS32: sw
define internal void @store_i16(i32 %addr_arg) {
entry:
......@@ -39,6 +54,9 @@ entry:
; CHECK-NEXT: store i16 1, i16* %addr_arg, align 1
; CHECK-NEXT: ret void
}
; MIPS32-LABEL: store_i16
; MIPS32: li
; MIPS32: sw
define internal void @store_i8(i32 %addr_arg) {
entry:
......@@ -51,3 +69,6 @@ entry:
; CHECK-NEXT: store i8 1, i8* %addr_arg, align 1
; CHECK-NEXT: ret void
}
; MIPS32-LABEL: store_i8
; MIPS32: li
; MIPS32: sw
\ No newline at end of file
......@@ -23,8 +23,8 @@ target:
}
; MIPS32-LABEL: uncond1
; MIPS32: b 8 <.Luncond1$target>
; MIPS32: b {{[0-9]+}} <.Luncond1$target>
; MIPS32: <.Luncond1$target>:
; MIPS32: li
; MIPS32: addu
; MIPS32: b 8 <.Luncond1$target>
; MIPS32: b {{[0-9]+}} <.Luncond1$target>
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