Commit 1d0690bc by Jaydeep Patil Committed by Jim Stichnoth

[SubZero] Implement load and store for MIPS

This patch implements lowerLoad and extends existing lowerStore for byte, short and floating-point types. The patch also modifies PostLoweringLegalizer for conversion of mov to load or store. R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2301303003 . Patch from Jaydeep Patil <jaydeep.patil@imgtec.com>.
parent a0b720de
...@@ -649,10 +649,8 @@ void InstMIPS32Mov::dump(const Cfg *Func) const { ...@@ -649,10 +649,8 @@ void InstMIPS32Mov::dump(const Cfg *Func) const {
Str << ", "; Str << ", ";
DestHi->dump(Func); DestHi->dump(Func);
} }
dumpOpcode(Str, " = mov", getDest()->getType()); dumpOpcode(Str, " = mov", getDest()->getType());
Str << " "; Str << " ";
dumpSources(Func); dumpSources(Func);
} }
...@@ -711,9 +709,7 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -711,9 +709,7 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
const char *ActualOpcode = nullptr; const char *ActualOpcode = nullptr;
const bool DestIsReg = Dest->hasReg(); const bool DestIsReg = Dest->hasReg();
const bool DestIsMem = !Dest->hasReg();
const bool SrcIsReg = (SrcV && SrcV->hasReg()); const bool SrcIsReg = (SrcV && SrcV->hasReg());
const bool SrcIsMem = !(SrcV && SrcV->hasReg());
// reg to reg // reg to reg
if (DestIsReg && SrcIsReg) { if (DestIsReg && SrcIsReg) {
...@@ -729,8 +725,8 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -729,8 +725,8 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
case IceType_i16: case IceType_i16:
case IceType_i32: case IceType_i32:
Str << "\t" Str << "\t"
"move" << "move"
"\t"; << "\t";
getDest()->emit(Func); getDest()->emit(Func);
Str << ", "; Str << ", ";
getSrc(0)->emit(Func); getSrc(0)->emit(Func);
...@@ -748,64 +744,7 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -748,64 +744,7 @@ void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
return; return;
} }
// reg to stack llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
if (DestIsMem && SrcIsReg) {
switch (Dest->getType()) {
case IceType_f32:
ActualOpcode = "swc1";
break;
case IceType_f64:
ActualOpcode = "sdc1";
break;
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32:
ActualOpcode = "sw";
break;
default:
UnimplementedError(getFlags());
return;
}
assert(ActualOpcode);
Str << "\t" << ActualOpcode << "\t";
getSrc(0)->emit(Func);
Str << ", ";
getDest()->emit(Func);
return;
}
// stack to reg
if (DestIsReg && SrcIsMem) {
switch (Dest->getType()) {
case IceType_f32:
ActualOpcode = "lwc1";
break;
case IceType_f64:
ActualOpcode = "ldc1";
break;
case IceType_i1:
case IceType_i8:
case IceType_i16:
case IceType_i32:
ActualOpcode = "lw";
break;
default:
UnimplementedError(getFlags());
return;
}
assert(ActualOpcode);
Str << "\t" << ActualOpcode << "\t";
getDest()->emit(Func);
Str << ", ";
getSrc(0)->emit(Func);
return;
}
// stack to stack
llvm::report_fatal_error("mov cant copy stack to stack.");
} }
template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const { template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
......
...@@ -110,8 +110,21 @@ public: ...@@ -110,8 +110,21 @@ public:
static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset); static bool canHoldOffset(Type Ty, bool SignExt, int32_t Offset);
void dump(const Cfg *Func, Ostream &Str) const override { void dump(const Cfg *Func, Ostream &Str) const override {
(void)Func; if (!BuildDefs::dump())
(void)Str; return;
Str << "[";
if (Func)
getBase()->dump(Func);
else
getBase()->dump(Str);
Str << ", ";
getOffset()->dump(Func, Str);
Str << "] AddrMode==";
if (getAddrMode() == Offset) {
Str << "Offset";
} else {
Str << "Unknown";
}
} }
private: private:
...@@ -515,8 +528,37 @@ public: ...@@ -515,8 +528,37 @@ public:
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1); const Type Ty = getDest()->getType();
Str << "\t" << Opcode << "\t"; switch (Ty) {
case IceType_i1:
case IceType_i8:
Str << "\t"
<< "lb"
<< "\t";
break;
case IceType_i16:
Str << "\t"
<< "lh"
<< "\t";
break;
case IceType_i32:
Str << "\t"
<< "lw"
<< "\t";
break;
case IceType_f32:
Str << "\t"
<< "lwc1"
<< "\t";
break;
case IceType_f64:
Str << "\t"
<< "ldc1"
<< "\t";
break;
default:
llvm_unreachable("InstMIPS32Load unknown type");
}
getDest()->emit(Func); getDest()->emit(Func);
Str << ", "; Str << ", ";
emitRelocOp(Str, Reloc); emitRelocOp(Str, Reloc);
...@@ -532,13 +574,12 @@ public: ...@@ -532,13 +574,12 @@ public:
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
Str << "\t" << Opcode << "\t"; dumpOpcode(Str, Opcode, getDest()->getType());
Str << " ";
getDest()->dump(Func); getDest()->dump(Func);
Str << ", "; Str << ", ";
emitRelocOp(Str, Reloc); emitRelocOp(Str, Reloc);
Str << (Reloc ? "(" : "");
getSrc(0)->dump(Func); getSrc(0)->dump(Func);
Str << (Reloc ? ")" : "");
} }
static bool classof(const Inst *Inst) { return isClassof(Inst, K); } static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
...@@ -572,7 +613,37 @@ public: ...@@ -572,7 +613,37 @@ public:
return; return;
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 2); assert(getSrcSize() == 2);
Str << "\t" << Opcode << "\t"; const Type Ty = getSrc(0)->getType();
switch (Ty) {
case IceType_i1:
case IceType_i8:
Str << "\t"
<< "sb"
<< "\t";
break;
case IceType_i16:
Str << "\t"
<< "sh"
<< "\t";
break;
case IceType_i32:
Str << "\t"
<< "sw"
<< "\t";
break;
case IceType_f32:
Str << "\t"
<< "swc1"
<< "\t";
break;
case IceType_f64:
Str << "\t"
<< "sdc1"
<< "\t";
break;
default:
llvm_unreachable("InstMIPS32Store unknown type");
}
getSrc(0)->emit(Func); getSrc(0)->emit(Func);
Str << ", "; Str << ", ";
emitRelocOp(Str, Reloc); emitRelocOp(Str, Reloc);
...@@ -581,20 +652,19 @@ public: ...@@ -581,20 +652,19 @@ public:
void emitIAS(const Cfg *Func) const override { void emitIAS(const Cfg *Func) const override {
(void)Func; (void)Func;
llvm_unreachable("Not yet implemented"); llvm_unreachable("InstMIPS32Store: Not yet implemented");
} }
void dump(const Cfg *Func) const override { void dump(const Cfg *Func) const override {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
Str << "\t" << Opcode << "\t"; dumpOpcode(Str, Opcode, getSrc(0)->getType());
Str << " ";
getSrc(0)->dump(Func); getSrc(0)->dump(Func);
Str << ", "; Str << ", ";
emitRelocOp(Str, Reloc); emitRelocOp(Str, Reloc);
Str << (Reloc ? "(" : "");
getSrc(1)->dump(Func); getSrc(1)->dump(Func);
Str << (Reloc ? ")" : "");
} }
static bool classof(const Inst *Inst) { return isClassof(Inst, K); } static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
...@@ -775,11 +845,12 @@ public: ...@@ -775,11 +845,12 @@ public:
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
dumpOpcode(Str, Opcode, getDest()->getType());
Str << " "; Str << " ";
Str << "\t" << Opcode << "\t";
dumpDest(Func); dumpDest(Func);
Str << ", "; Str << ", ";
dumpSources(Func); dumpSources(Func);
Str << ", ";
if (Signed) if (Signed)
Str << (int32_t)Imm; Str << (int32_t)Imm;
else else
......
...@@ -101,9 +101,7 @@ public: ...@@ -101,9 +101,7 @@ public:
PrologEmitsFixedAllocas = true; PrologEmitsFixedAllocas = true;
} }
int32_t getFrameFixedAllocaOffset() const override { int32_t getFrameFixedAllocaOffset() const override {
// TODO(sehr): Implement fixed stack layout. return FixedAllocaSizeBytes - (SpillAreaSizeBytes - MaxOutArgsSizeBytes);
llvm::report_fatal_error("Not yet implemented");
return 0;
} }
uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; } uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
...@@ -448,6 +446,7 @@ public: ...@@ -448,6 +446,7 @@ public:
Legal_Reg = 1 << 0, // physical register, not stack location Legal_Reg = 1 << 0, // physical register, not stack location
Legal_Imm = 1 << 1, Legal_Imm = 1 << 1,
Legal_Mem = 1 << 2, Legal_Mem = 1 << 2,
Legal_Rematerializable = 1 << 3,
Legal_Default = ~Legal_None Legal_Default = ~Legal_None
}; };
typedef uint32_t LegalMask; typedef uint32_t LegalMask;
......
...@@ -6,6 +6,13 @@ ...@@ -6,6 +6,13 @@
; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s ; RUN: %p2i --filetype=obj --disassemble -i %s --args -O2 | FileCheck %s
; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 | FileCheck %s ; RUN: %p2i --filetype=obj --disassemble -i %s --args -Om1 | FileCheck %s
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble \
; RUN: --disassemble --target mips32 -i %s --args -Om1 --skip-unimplemented \
; RUN: -allow-externally-defined-symbols \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix MIPS32 %s
define internal float @loadFloat(i32 %a) { define internal float @loadFloat(i32 %a) {
entry: entry:
%__1 = inttoptr i32 %a to float* %__1 = inttoptr i32 %a to float*
...@@ -16,6 +23,9 @@ entry: ...@@ -16,6 +23,9 @@ entry:
; CHECK: movss ; CHECK: movss
; CHECK: fld ; CHECK: fld
; MIPS32-LABEL: loadFloat
; MIPS32: lwc1 $f{{.*}},0{{.*}}
define internal double @loadDouble(i32 %a) { define internal double @loadDouble(i32 %a) {
entry: entry:
%__1 = inttoptr i32 %a to double* %__1 = inttoptr i32 %a to double*
...@@ -26,6 +36,9 @@ entry: ...@@ -26,6 +36,9 @@ entry:
; CHECK: movsd ; CHECK: movsd
; CHECK: fld ; CHECK: fld
; MIPS32-LABEL: loadDouble
; MIPS32: ldc1 $f{{.*}},0{{.*}}
define internal void @storeFloat(i32 %a, float %value) { define internal void @storeFloat(i32 %a, float %value) {
entry: entry:
%__2 = inttoptr i32 %a to float* %__2 = inttoptr i32 %a to float*
...@@ -36,6 +49,9 @@ entry: ...@@ -36,6 +49,9 @@ entry:
; CHECK: movss ; CHECK: movss
; CHECK: movss ; CHECK: movss
; MIPS32-LABEL: storeFloat
; MIPS32: swc1 $f{{.*}},0{{.*}}
define internal void @storeDouble(i32 %a, double %value) { define internal void @storeDouble(i32 %a, double %value) {
entry: entry:
%__2 = inttoptr i32 %a to double* %__2 = inttoptr i32 %a to double*
...@@ -46,6 +62,10 @@ entry: ...@@ -46,6 +62,10 @@ entry:
; CHECK: movsd ; CHECK: movsd
; CHECK: movsd ; CHECK: movsd
; MIPS32-LABEL: storeDouble
; MIPS32: ldc1 $f{{.*}},4{{.*}}
; MIPS32: sdc1 $f{{.*}},0{{.*}}
define internal void @storeFloatConst(i32 %a) { define internal void @storeFloatConst(i32 %a) {
entry: entry:
%a.asptr = inttoptr i32 %a to float* %a.asptr = inttoptr i32 %a to float*
...@@ -56,6 +76,11 @@ entry: ...@@ -56,6 +76,11 @@ entry:
; CHECK: movss ; CHECK: movss
; CHECK: movss ; CHECK: movss
; MIPS32-LABEL: storeFloatConst
; MIPS32: lui {{.*}},{{.*}}
; MIPS32: lwc1 $f{{.*}},{{.*}}
; MIPS32: swc1 $f{{.*}},0{{.*}}
define internal void @storeDoubleConst(i32 %a) { define internal void @storeDoubleConst(i32 %a) {
entry: entry:
%a.asptr = inttoptr i32 %a to double* %a.asptr = inttoptr i32 %a to double*
...@@ -65,3 +90,8 @@ entry: ...@@ -65,3 +90,8 @@ entry:
; CHECK-LABEL: storeDoubleConst ; CHECK-LABEL: storeDoubleConst
; CHECK: movsd ; CHECK: movsd
; CHECK: movsd ; CHECK: movsd
; MIPS32-LABEL: storeDoubleConst
; MIPS32: lui {{.*}},{{.*}}
; MIPS32: ldc1 $f{{.*}},{{.*}}
; MIPS32: sdc1 $f{{.*}},0{{.*}}
...@@ -4,6 +4,13 @@ ...@@ -4,6 +4,13 @@
; RUN: %p2i -i %s --args --verbose inst -threads=0 | FileCheck %s ; 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 -Om1 --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 @load_i64(i32 %addr_arg) { define internal void @load_i64(i32 %addr_arg) {
entry: entry:
%__1 = inttoptr i32 %addr_arg to i64* %__1 = inttoptr i32 %addr_arg to i64*
...@@ -16,6 +23,10 @@ entry: ...@@ -16,6 +23,10 @@ entry:
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
} }
; MIPS32-LABEL: load_i64
; MIPS32: lw {{.*}},0({{.*}})
; MIPS32-NEXT: lw {{.*}},4({{.*}})
define internal void @load_i32(i32 %addr_arg) { define internal void @load_i32(i32 %addr_arg) {
entry: entry:
%__1 = inttoptr i32 %addr_arg to i32* %__1 = inttoptr i32 %addr_arg to i32*
...@@ -28,6 +39,9 @@ entry: ...@@ -28,6 +39,9 @@ entry:
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
} }
; MIPS32-LABEL: load_i32
; MIPS32: lw {{.*}},0({{.*}})
define internal void @load_i16(i32 %addr_arg) { define internal void @load_i16(i32 %addr_arg) {
entry: entry:
%__1 = inttoptr i32 %addr_arg to i16* %__1 = inttoptr i32 %addr_arg to i16*
...@@ -40,6 +54,9 @@ entry: ...@@ -40,6 +54,9 @@ entry:
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
} }
; MIPS32-LABEL: load_i16
; MIPS32: lh {{.*}},0({{.*}})
define internal void @load_i8(i32 %addr_arg) { define internal void @load_i8(i32 %addr_arg) {
entry: entry:
%__1 = inttoptr i32 %addr_arg to i8* %__1 = inttoptr i32 %addr_arg to i8*
...@@ -51,3 +68,6 @@ entry: ...@@ -51,3 +68,6 @@ entry:
; CHECK-NEXT: %iv = load i8, i8* %addr_arg, align 1 ; CHECK-NEXT: %iv = load i8, i8* %addr_arg, align 1
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
} }
; MIPS32-LABEL: load_i8
; MIPS32: lb {{.*}},0({{.*}})
...@@ -56,7 +56,7 @@ entry: ...@@ -56,7 +56,7 @@ entry:
} }
; MIPS32-LABEL: store_i16 ; MIPS32-LABEL: store_i16
; MIPS32: li ; MIPS32: li
; MIPS32: sw ; MIPS32: sh
define internal void @store_i8(i32 %addr_arg) { define internal void @store_i8(i32 %addr_arg) {
entry: entry:
...@@ -71,4 +71,34 @@ entry: ...@@ -71,4 +71,34 @@ entry:
} }
; MIPS32-LABEL: store_i8 ; MIPS32-LABEL: store_i8
; MIPS32: li ; MIPS32: li
; MIPS32: sw ; MIPS32: sb
\ No newline at end of file
define internal void @store_f32(float* %faddr_arg) {
entry:
store float 1.000000e+00, float* %faddr_arg, align 4
ret void
; CHECK: Initial CFG
; CHECK: entry:
; CHECK-NEXT: store float 1.000000e+00, float* %faddr_arg, align 4
; CHECK-NEXT: ret void
}
; MIPS32-LABEL: store_f32
; MIPS32: lui
; MIPS32: lwc1
; MIPS32: swc1
define internal void @store_f64(double* %daddr_arg) {
entry:
store double 1.000000e+00, double* %daddr_arg, align 8
ret void
; CHECK: Initial CFG
; CHECK: entry:
; CHECK-NEXT: store double 1.000000e+00, double* %daddr_arg, align 8
; CHECK-NEXT: ret void
}
; MIPS32-LABEL: store_f64
; MIPS32: lui
; MIPS32: ldc1
; MIPS32: sdc1
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