summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/Mips/MipsFastISel.cpp100
-rw-r--r--test/CodeGen/Mips/Fast-ISel/loadstore2.ll83
2 files changed, 176 insertions, 7 deletions
diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp
index 9a60aa7b9f..375d9b2055 100644
--- a/lib/Target/Mips/MipsFastISel.cpp
+++ b/lib/Target/Mips/MipsFastISel.cpp
@@ -69,8 +69,11 @@ public:
bool ComputeAddress(const Value *Obj, Address &Addr);
private:
+ bool EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
+ unsigned Alignment = 0);
bool EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
unsigned Alignment = 0);
+ bool SelectLoad(const Instruction *I);
bool SelectRet(const Instruction *I);
bool SelectStore(const Instruction *I);
@@ -105,6 +108,11 @@ private:
return EmitInst(Opc).addReg(SrcReg).addReg(MemReg).addImm(MemOffset);
}
+ MachineInstrBuilder EmitInstLoad(unsigned Opc, unsigned DstReg,
+ unsigned MemReg, int64_t MemOffset) {
+ return EmitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset);
+ }
+
#include "MipsGenFastISel.inc"
};
@@ -126,6 +134,8 @@ bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
// We will extend this in a later patch:
// If this is a type than can be sign or zero-extended to a basic operation
// go ahead and accept it now.
+ if (VT == MVT::i8 || VT == MVT::i16)
+ return true;
return false;
}
@@ -142,6 +152,45 @@ bool MipsFastISel::ComputeAddress(const Value *Obj, Address &Addr) {
return Addr.Base.Reg != 0;
}
+bool MipsFastISel::EmitLoad(MVT VT, unsigned &ResultReg, Address &Addr,
+ unsigned Alignment) {
+ //
+ // more cases will be handled here in following patches.
+ //
+ unsigned Opc;
+ switch (VT.SimpleTy) {
+ case MVT::i32: {
+ ResultReg = createResultReg(&Mips::GPR32RegClass);
+ Opc = Mips::LW;
+ break;
+ }
+ case MVT::i16: {
+ ResultReg = createResultReg(&Mips::GPR32RegClass);
+ Opc = Mips::LHu;
+ break;
+ }
+ case MVT::i8: {
+ ResultReg = createResultReg(&Mips::GPR32RegClass);
+ Opc = Mips::LBu;
+ break;
+ }
+ case MVT::f32: {
+ ResultReg = createResultReg(&Mips::FGR32RegClass);
+ Opc = Mips::LWC1;
+ break;
+ }
+ case MVT::f64: {
+ ResultReg = createResultReg(&Mips::AFGR64RegClass);
+ Opc = Mips::LDC1;
+ break;
+ }
+ default:
+ return false;
+ }
+ EmitInstLoad(Opc, ResultReg, Addr.Base.Reg, Addr.Offset);
+ return true;
+}
+
// Materialize a constant into a register, and return the register
// number (or zero if we failed to handle it).
unsigned MipsFastISel::TargetMaterializeConstant(const Constant *C) {
@@ -167,14 +216,49 @@ bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
//
// more cases will be handled here in following patches.
//
- if (VT == MVT::i32)
- EmitInstStore(Mips::SW, SrcReg, Addr.Base.Reg, Addr.Offset);
- else if (VT == MVT::f32)
- EmitInstStore(Mips::SWC1, SrcReg, Addr.Base.Reg, Addr.Offset);
- else if (VT == MVT::f64)
- EmitInstStore(Mips::SDC1, SrcReg, Addr.Base.Reg, Addr.Offset);
- else
+ unsigned Opc;
+ switch (VT.SimpleTy) {
+ case MVT::i8:
+ Opc = Mips::SB;
+ break;
+ case MVT::i16:
+ Opc = Mips::SH;
+ break;
+ case MVT::i32:
+ Opc = Mips::SW;
+ break;
+ case MVT::f32:
+ Opc = Mips::SWC1;
+ break;
+ case MVT::f64:
+ Opc = Mips::SDC1;
+ break;
+ default:
+ return false;
+ }
+ EmitInstStore(Opc, SrcReg, Addr.Base.Reg, Addr.Offset);
+ return true;
+}
+
+bool MipsFastISel::SelectLoad(const Instruction *I) {
+ // Atomic loads need special handling.
+ if (cast<LoadInst>(I)->isAtomic())
+ return false;
+
+ // Verify we have a legal type before going any further.
+ MVT VT;
+ if (!isLoadTypeLegal(I->getType(), VT))
+ return false;
+
+ // See if we can handle this address.
+ Address Addr;
+ if (!ComputeAddress(I->getOperand(0), Addr))
+ return false;
+
+ unsigned ResultReg;
+ if (!EmitLoad(VT, ResultReg, Addr, cast<LoadInst>(I)->getAlignment()))
return false;
+ UpdateValueMap(I, ResultReg);
return true;
}
@@ -224,6 +308,8 @@ bool MipsFastISel::TargetSelectInstruction(const Instruction *I) {
switch (I->getOpcode()) {
default:
break;
+ case Instruction::Load:
+ return SelectLoad(I);
case Instruction::Store:
return SelectStore(I);
case Instruction::Ret:
diff --git a/test/CodeGen/Mips/Fast-ISel/loadstore2.ll b/test/CodeGen/Mips/Fast-ISel/loadstore2.ll
new file mode 100644
index 0000000000..f113a0eb1d
--- /dev/null
+++ b/test/CodeGen/Mips/Fast-ISel/loadstore2.ll
@@ -0,0 +1,83 @@
+; ModuleID = 'loadstore2.c'
+target datalayout = "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"
+target triple = "mips--linux-gnu"
+
+@c2 = common global i8 0, align 1
+@c1 = common global i8 0, align 1
+; RUN: llc -march=mipsel -relocation-model=pic -O0 -mips-fast-isel -fast-isel-abort -mcpu=mips32r2 \
+; RUN: < %s | FileCheck %s
+
+@s2 = common global i16 0, align 2
+@s1 = common global i16 0, align 2
+@i2 = common global i32 0, align 4
+@i1 = common global i32 0, align 4
+@f2 = common global float 0.000000e+00, align 4
+@f1 = common global float 0.000000e+00, align 4
+@d2 = common global double 0.000000e+00, align 8
+@d1 = common global double 0.000000e+00, align 8
+
+; Function Attrs: nounwind
+define void @cfoo() #0 {
+entry:
+ %0 = load i8* @c2, align 1
+ store i8 %0, i8* @c1, align 1
+; CHECK-LABEL: cfoo:
+; CHECK: lbu $[[REGc:[0-9]+]], 0(${{[0-9]+}})
+; CHECK: sb $[[REGc]], 0(${{[0-9]+}})
+
+
+ ret void
+}
+
+; Function Attrs: nounwind
+define void @sfoo() #0 {
+entry:
+ %0 = load i16* @s2, align 2
+ store i16 %0, i16* @s1, align 2
+; CHECK-LABEL: sfoo:
+; CHECK: lhu $[[REGs:[0-9]+]], 0(${{[0-9]+}})
+; CHECK: sh $[[REGs]], 0(${{[0-9]+}})
+
+ ret void
+}
+
+; Function Attrs: nounwind
+define void @ifoo() #0 {
+entry:
+ %0 = load i32* @i2, align 4
+ store i32 %0, i32* @i1, align 4
+; CHECK-LABEL: ifoo:
+; CHECK: lw $[[REGi:[0-9]+]], 0(${{[0-9]+}})
+; CHECK: sw $[[REGi]], 0(${{[0-9]+}})
+
+ ret void
+}
+
+; Function Attrs: nounwind
+define void @ffoo() #0 {
+entry:
+ %0 = load float* @f2, align 4
+ store float %0, float* @f1, align 4
+; CHECK-LABEL: ffoo:
+; CHECK: lwc1 $f[[REGf:[0-9]+]], 0(${{[0-9]+}})
+; CHECK: swc1 $f[[REGf]], 0(${{[0-9]+}})
+
+
+ ret void
+}
+
+; Function Attrs: nounwind
+define void @dfoo() #0 {
+entry:
+ %0 = load double* @d2, align 8
+ store double %0, double* @d1, align 8
+; CHECK-LABEL: dfoo:
+; CHECK: ldc1 $f[[REGd:[0-9]+]], 0(${{[0-9]+}})
+; CHECK: sdc1 $f[[REGd]], 0(${{[0-9]+}})
+; CHECK: .end dfoo
+ ret void
+}
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+