[MIPS GlobalISel] Select float and double load and store
authorPetar Avramovic <Petar.Avramovic@rt-rk.com>
Wed, 10 Jul 2019 12:55:21 +0000 (12:55 +0000)
committerPetar Avramovic <Petar.Avramovic@rt-rk.com>
Wed, 10 Jul 2019 12:55:21 +0000 (12:55 +0000)
Select float and double load and store for MIPS32.

Differential Revision: https://reviews.llvm.org/D64419

llvm-svn: 365626

llvm/lib/Target/Mips/MipsInstructionSelector.cpp
llvm/test/CodeGen/Mips/GlobalISel/instruction-select/load.mir [new file with mode: 0644]
llvm/test/CodeGen/Mips/GlobalISel/instruction-select/store.mir [new file with mode: 0644]
llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/load.ll
llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll

index 8e597dc..b7a9955 100644 (file)
@@ -139,30 +139,49 @@ bool MipsInstructionSelector::materialize32BitImm(Register DestReg, APInt Imm,
 }
 
 /// Returning Opc indicates that we failed to select MIPS instruction opcode.
-static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes) {
-  if (Opc == TargetOpcode::G_STORE)
-    switch (MemSizeInBytes) {
-    case 4:
-      return Mips::SW;
-    case 2:
-      return Mips::SH;
-    case 1:
-      return Mips::SB;
-    default:
-      return Opc;
-    }
-  else
-    // Unspecified extending load is selected into zeroExtending load.
+static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes,
+                                      unsigned RegBank, bool isFP64) {
+  bool isStore = Opc == TargetOpcode::G_STORE;
+  if (RegBank == Mips::GPRBRegBankID) {
+    if (isStore)
+      switch (MemSizeInBytes) {
+      case 4:
+        return Mips::SW;
+      case 2:
+        return Mips::SH;
+      case 1:
+        return Mips::SB;
+      default:
+        return Opc;
+      }
+    else
+      // Unspecified extending load is selected into zeroExtending load.
+      switch (MemSizeInBytes) {
+      case 4:
+        return Mips::LW;
+      case 2:
+        return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
+      case 1:
+        return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
+      default:
+        return Opc;
+      }
+  }
+
+  if (RegBank == Mips::FPRBRegBankID) {
     switch (MemSizeInBytes) {
     case 4:
-      return Mips::LW;
-    case 2:
-      return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LH : Mips::LHu;
-    case 1:
-      return Opc == TargetOpcode::G_SEXTLOAD ? Mips::LB : Mips::LBu;
+      return isStore ? Mips::SWC1 : Mips::LWC1;
+    case 8:
+      if (isFP64)
+        return isStore ? Mips::SDC164 : Mips::LDC164;
+      else
+        return isStore ? Mips::SDC1 : Mips::LDC1;
     default:
       return Opc;
     }
+  }
+  return Opc;
 }
 
 bool MipsInstructionSelector::select(MachineInstr &I,
@@ -262,11 +281,14 @@ bool MipsInstructionSelector::select(MachineInstr &I,
     const unsigned OpSize = MRI.getType(DestReg).getSizeInBits();
     const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize();
 
-    if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32)
+    if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32)
+      return false;
+
+    if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64)
       return false;
 
-    const unsigned NewOpc =
-        selectLoadStoreOpCode(I.getOpcode(), OpMemSizeInBytes);
+    const unsigned NewOpc = selectLoadStoreOpCode(
+        I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit());
     if (NewOpc == I.getOpcode())
       return false;
 
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/load.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/load.mir
new file mode 100644 (file)
index 0000000..ff9c1d5
--- /dev/null
@@ -0,0 +1,94 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP32
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP64
+--- |
+
+  define void @load_i32(i32* %ptr) {entry: ret void}
+  define void @load_float(float* %ptr) {entry: ret void}
+  define void @load_double(double* %ptr) {entry: ret void}
+
+...
+---
+name:            load_i32
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0
+
+    ; MIPS32FP32-LABEL: name: load_i32
+    ; MIPS32FP32: liveins: $a0
+    ; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32FP32: [[LW:%[0-9]+]]:gpr32 = LW [[COPY]], 0 :: (load 4 from %ir.ptr)
+    ; MIPS32FP32: $v0 = COPY [[LW]]
+    ; MIPS32FP32: RetRA implicit $v0
+    ; MIPS32FP64-LABEL: name: load_i32
+    ; MIPS32FP64: liveins: $a0
+    ; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32FP64: [[LW:%[0-9]+]]:gpr32 = LW [[COPY]], 0 :: (load 4 from %ir.ptr)
+    ; MIPS32FP64: $v0 = COPY [[LW]]
+    ; MIPS32FP64: RetRA implicit $v0
+    %0:gprb(p0) = COPY $a0
+    %1:gprb(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr)
+    $v0 = COPY %1(s32)
+    RetRA implicit $v0
+
+...
+---
+name:            load_float
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0
+
+    ; MIPS32FP32-LABEL: name: load_float
+    ; MIPS32FP32: liveins: $a0
+    ; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32FP32: [[LWC1_:%[0-9]+]]:fgr32 = LWC1 [[COPY]], 0 :: (load 4 from %ir.ptr)
+    ; MIPS32FP32: $f0 = COPY [[LWC1_]]
+    ; MIPS32FP32: RetRA implicit $f0
+    ; MIPS32FP64-LABEL: name: load_float
+    ; MIPS32FP64: liveins: $a0
+    ; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32FP64: [[LWC1_:%[0-9]+]]:fgr32 = LWC1 [[COPY]], 0 :: (load 4 from %ir.ptr)
+    ; MIPS32FP64: $f0 = COPY [[LWC1_]]
+    ; MIPS32FP64: RetRA implicit $f0
+    %0:gprb(p0) = COPY $a0
+    %1:fprb(s32) = G_LOAD %0(p0) :: (load 4 from %ir.ptr)
+    $f0 = COPY %1(s32)
+    RetRA implicit $f0
+
+...
+---
+name:            load_double
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0
+
+    ; MIPS32FP32-LABEL: name: load_double
+    ; MIPS32FP32: liveins: $a0
+    ; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32FP32: [[LDC1_:%[0-9]+]]:afgr64 = LDC1 [[COPY]], 0 :: (load 8 from %ir.ptr)
+    ; MIPS32FP32: $d0 = COPY [[LDC1_]]
+    ; MIPS32FP32: RetRA implicit $d0
+    ; MIPS32FP64-LABEL: name: load_double
+    ; MIPS32FP64: liveins: $a0
+    ; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32FP64: [[LDC164_:%[0-9]+]]:fgr64 = LDC164 [[COPY]], 0 :: (load 8 from %ir.ptr)
+    ; MIPS32FP64: $d0 = COPY [[LDC164_]]
+    ; MIPS32FP64: RetRA implicit $d0
+    %0:gprb(p0) = COPY $a0
+    %1:fprb(s64) = G_LOAD %0(p0) :: (load 8 from %ir.ptr)
+    $d0 = COPY %1(s64)
+    RetRA implicit $d0
+
+...
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/store.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/store.mir
new file mode 100644 (file)
index 0000000..aa4e652
--- /dev/null
@@ -0,0 +1,94 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP32
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32FP64
+--- |
+
+  define void @store_i32(i32* %ptr) { entry: ret void }
+  define void @store_float(float* %ptr) { entry: ret void }
+  define void @store_double(double* %ptr) { entry: ret void }
+
+...
+---
+name:            store_i32
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1
+
+    ; MIPS32FP32-LABEL: name: store_i32
+    ; MIPS32FP32: liveins: $a0, $a1
+    ; MIPS32FP32: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+    ; MIPS32FP32: SW [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr)
+    ; MIPS32FP32: RetRA
+    ; MIPS32FP64-LABEL: name: store_i32
+    ; MIPS32FP64: liveins: $a0, $a1
+    ; MIPS32FP64: [[COPY:%[0-9]+]]:gpr32 = COPY $a0
+    ; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+    ; MIPS32FP64: SW [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr)
+    ; MIPS32FP64: RetRA
+    %0:gprb(s32) = COPY $a0
+    %1:gprb(p0) = COPY $a1
+    G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr)
+    RetRA
+
+...
+---
+name:            store_float
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a1, $f12
+
+    ; MIPS32FP32-LABEL: name: store_float
+    ; MIPS32FP32: liveins: $a1, $f12
+    ; MIPS32FP32: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+    ; MIPS32FP32: SWC1 [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr)
+    ; MIPS32FP32: RetRA
+    ; MIPS32FP64-LABEL: name: store_float
+    ; MIPS32FP64: liveins: $a1, $f12
+    ; MIPS32FP64: [[COPY:%[0-9]+]]:fgr32 = COPY $f12
+    ; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1
+    ; MIPS32FP64: SWC1 [[COPY]], [[COPY1]], 0 :: (store 4 into %ir.ptr)
+    ; MIPS32FP64: RetRA
+    %0:fprb(s32) = COPY $f12
+    %1:gprb(p0) = COPY $a1
+    G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr)
+    RetRA
+
+...
+---
+name:            store_double
+alignment:       2
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a2, $d6
+
+    ; MIPS32FP32-LABEL: name: store_double
+    ; MIPS32FP32: liveins: $a2, $d6
+    ; MIPS32FP32: [[COPY:%[0-9]+]]:afgr64 = COPY $d6
+    ; MIPS32FP32: [[COPY1:%[0-9]+]]:gpr32 = COPY $a2
+    ; MIPS32FP32: SDC1 [[COPY]], [[COPY1]], 0 :: (store 8 into %ir.ptr)
+    ; MIPS32FP32: RetRA
+    ; MIPS32FP64-LABEL: name: store_double
+    ; MIPS32FP64: liveins: $a2, $d6
+    ; MIPS32FP64: [[COPY:%[0-9]+]]:fgr64 = COPY $d6
+    ; MIPS32FP64: [[COPY1:%[0-9]+]]:gpr32 = COPY $a2
+    ; MIPS32FP64: SDC164 [[COPY]], [[COPY1]], 0 :: (store 8 into %ir.ptr)
+    ; MIPS32FP64: RetRA
+    %0:fprb(s64) = COPY $d6
+    %1:gprb(p0) = COPY $a2
+    G_STORE %0(s64), %1(p0) :: (store 8 into %ir.ptr)
+    RetRA
+
+...
index 4208a6e..00b5c26 100644 (file)
@@ -25,3 +25,25 @@ entry:
   %0 = load i64, i64* %ptr
   ret i64 %0
 }
+
+define float @load_float(float* %ptr) {
+; MIPS32-LABEL: load_float:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    lwc1 $f0, 0($4)
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  %0 = load float, float* %ptr
+  ret float %0
+}
+
+define double @load_double(double* %ptr) {
+; MIPS32-LABEL: load_double:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    ldc1 $f0, 0($4)
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  %0 = load double, double* %ptr
+  ret double %0
+}
index 0bad24c..17ba6c0 100644 (file)
@@ -25,3 +25,25 @@ entry:
   store i64 %val, i64* %ptr
   ret void
 }
+
+define void @store_float(float %val, float* %ptr)  {
+; MIPS32-LABEL: store_float:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    swc1 $f12, 0($5)
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  store float %val, float* %ptr
+  ret void
+}
+
+define void @store_double(double %val, double* %ptr)  {
+; MIPS32-LABEL: store_double:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    sdc1 $f12, 0($6)
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  store double %val, double* %ptr
+  ret void
+}