]> granicus.if.org Git - llvm/commitdiff
[ARM] GlobalISel: Add FPR reg bank
authorDiana Picus <diana.picus@linaro.org>
Wed, 8 Feb 2017 13:23:04 +0000 (13:23 +0000)
committerDiana Picus <diana.picus@linaro.org>
Wed, 8 Feb 2017 13:23:04 +0000 (13:23 +0000)
Add a register bank for floating point values and select simple instructions
using them (add, copies from GPR).

This assumes that the hardware can cope with a single precision add (VADDS)
instruction, so the legalizer will treat G_FADD as legal and the instruction
selector will refuse to select if the hardware doesn't support it. In the future
we'll want to be more careful about this, and legalize to libcalls if we have to
use soft float.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294442 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMInstructionSelector.cpp
lib/Target/ARM/ARMLegalizerInfo.cpp
lib/Target/ARM/ARMRegisterBankInfo.cpp
lib/Target/ARM/ARMRegisterBanks.td
test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
test/CodeGen/ARM/GlobalISel/arm-legalizer.mir
test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir

index 538060d4334b250751fcc98c11d8d690a136aeea..dcdd0e83550f66806078b40305bc102d7ebda933 100644 (file)
@@ -54,9 +54,17 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
            DstSize <= SrcSize)) &&
          "Copy with different width?!");
 
-  assert(RegBank->getID() == ARM::GPRRegBankID && "Unsupported reg bank");
+  assert((RegBank->getID() == ARM::GPRRegBankID ||
+          RegBank->getID() == ARM::FPRRegBankID) &&
+         "Unsupported reg bank");
+
   const TargetRegisterClass *RC = &ARM::GPRRegClass;
 
+  if (RegBank->getID() == ARM::FPRRegBankID) {
+    assert(DstSize == 32 && "Only 32-bit FP values are supported");
+    RC = &ARM::SPRRegClass;
+  }
+
   // No need to constrain SrcReg. It will get constrained when
   // we hit another of its uses or its defs.
   // Copies do not have constraints.
@@ -177,6 +185,13 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
     I.setDesc(TII.get(ARM::ADDrr));
     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
     break;
+  case G_FADD:
+    if (!TII.getSubtarget().hasVFP2() ||
+        TII.getSubtarget().useNEONForSinglePrecisionFP())
+      return false;
+    I.setDesc(TII.get(ARM::VADDS));
+    MIB.add(predOps(ARMCC::AL));
+    break;
   case G_FRAME_INDEX:
     // Add 0 to the given frame index and hope it will eventually be folded into
     // the user(s).
index d1276df57b189e5291638ea509b43e4fba3a319e..af44cbf50f05b7122621333e3656c048155f27a2 100644 (file)
@@ -48,5 +48,9 @@ ARMLegalizerInfo::ARMLegalizerInfo() {
       setAction({Op, 1, Ty}, Legal);
   }
 
+  // FIXME: This is a bit sloppy, but for now we'll just rely on the instruction
+  // selector to complain if it doesn't support floating point.
+  setAction({G_FADD, s32}, Legal);
+
   computeTables();
 }
index f65b6787697b15b105096b6e5e56ffce2333ab51..dc111069921b1a2f3f83168143bbfbe720805d82 100644 (file)
@@ -33,9 +33,11 @@ using namespace llvm;
 namespace llvm {
 namespace ARM {
 RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank};
+RegisterBankInfo::PartialMapping FPRPartialMapping{0, 32, FPRRegBank};
 
 RegisterBankInfo::ValueMapping ValueMappings[] = {
-    {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}};
+    {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1},
+    {&FPRPartialMapping, 1}, {&FPRPartialMapping, 1}, {&FPRPartialMapping, 1}};
 } // end namespace arm
 } // end namespace llvm
 
@@ -82,6 +84,9 @@ const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
   case GPRnopcRegClassID:
   case tGPR_and_tcGPRRegClassID:
     return getRegBank(ARM::GPRRegBankID);
+  case SPR_8RegClassID:
+  case SPRRegClassID:
+    return getRegBank(ARM::FPRRegBankID);
   default:
     llvm_unreachable("Unsupported register kind");
   }
@@ -115,6 +120,9 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
     // the real world we would use different mappings.
     OperandsMapping = &ARM::ValueMappings[0];
     break;
+  case G_FADD:
+    OperandsMapping = &ARM::ValueMappings[3];
+    break;
   case G_FRAME_INDEX:
     OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr});
     break;
index a2b3a7943c1678815d2f2cf1f3f20f68ac5e133d..b8e0347ef62d66e091bb3a5b2aa554a32d8d4e6b 100644 (file)
@@ -11,3 +11,4 @@
 //===----------------------------------------------------------------------===//
 
 def GPRRegBank : RegisterBank<"GPRB", [GPR, GPRwithAPSR]>;
+def FPRRegBank : RegisterBank<"FPRB", [SPR]>;
index ab2ddf88ff390b36b6a1ec5aae8a255b3e0e799e..8d18513766d3736ccbc8c8d985d0df42c7d23cf6 100644 (file)
@@ -9,7 +9,11 @@
   define void @test_add_s16() { ret void }
   define void @test_add_s32() { ret void }
 
+  define void @test_fadd_s32() #0 { ret void }
+
   define void @test_load_from_stack() { ret void }
+
+  attributes #0 = { "target-features"="+vfp2" }
 ...
 ---
 name:            test_zext_s1
@@ -217,6 +221,39 @@ body:             |
     ; CHECK: BX_RET 14, _, implicit %r0
 ...
 ---
+name:            test_fadd_s32
+# CHECK-LABEL: name: test_fadd_s32
+legalized:       true
+regBankSelected: true
+selected:        false
+# CHECK: selected: true
+registers:
+  - { id: 0, class: fprb }
+  - { id: 1, class: fprb }
+  - { id: 2, class: fprb }
+# CHECK: id: 0, class: spr
+# CHECK: id: 1, class: spr
+# CHECK: id: 2, class: spr
+body:             |
+  bb.0:
+    liveins: %s0, %s1
+
+    %0(s32) = COPY %s0
+    ; CHECK: [[VREGX:%[0-9]+]] = COPY %s0
+
+    %1(s32) = COPY %s1
+    ; CHECK: [[VREGY:%[0-9]+]] = COPY %s1
+
+    %2(s32) = G_FADD %0, %1
+    ; CHECK: [[VREGSUM:%[0-9]+]] = VADDS [[VREGX]], [[VREGY]], 14, _
+
+    %s0 = COPY %2(s32)
+    ; CHECK: %s0 = COPY [[VREGSUM]]
+
+    BX_RET 14, _, implicit %s0
+    ; CHECK: BX_RET 14, _, implicit %s0
+...
+---
 name:            test_load_from_stack
 # CHECK-LABEL: name: test_load_from_stack
 legalized:       true
index 249a0b03795233acb5d90071a3e6f8241991c376..f187e886930057b411159d342da17ab371fc6840 100644 (file)
@@ -9,6 +9,8 @@
 
   define void @test_load_from_stack() { ret void }
   define void @test_legal_loads() { ret void }
+
+  define void @test_fadd_s32() { ret void }
 ...
 ---
 name:            test_sext_s8
@@ -190,3 +192,28 @@ body:             |
     %5(p0)  = G_LOAD %0(p0)
     BX_RET 14, _
 ...
+---
+name:            test_fadd_s32
+# CHECK-LABEL: name: test_fadd_s32
+legalized:       false
+# CHECK: legalized: true
+regBankSelected: false
+selected:        false
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.0:
+    liveins: %r0, %r1
+
+    %0(s32) = COPY %r0
+    %1(s32) = COPY %r1
+    %2(s32) = G_FADD %0, %1
+    ; G_FADD with s32 is legal, so we should find it unchanged in the output
+    ; CHECK: {{%[0-9]+}}(s32) = G_FADD {{%[0-9]+, %[0-9]+}}
+    %r0 = COPY %2(s32)
+    BX_RET 14, _, implicit %r0
+
+...
index ba6880f3e43356102a73274b19693c0ff8b05361..c66aa3cb937d47e1fbe01227cb28b6fd42fe48c8 100644 (file)
@@ -6,6 +6,8 @@
   define void @test_add_s1() { ret void }
 
   define void @test_loads() { ret void }
+
+  define void @test_fadd_s32() { ret void }
 ...
 ---
 name:            test_add_s32
@@ -144,3 +146,29 @@ body:             |
     BX_RET 14, _, implicit %r0
 
 ...
+---
+name:            test_fadd_s32
+# CHECK-LABEL: name: test_fadd_s32
+legalized:       true
+regBankSelected: false
+selected:        false
+# CHECK: registers:
+# CHECK: - { id: 0, class: fprb }
+# CHECK: - { id: 1, class: fprb }
+# CHECK: - { id: 2, class: fprb }
+
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body:             |
+  bb.0:
+    liveins: %r0, %r1
+
+    %0(s32) = COPY %s0
+    %1(s32) = COPY %s1
+    %2(s32) = G_FADD %0, %1
+    %s0 = COPY %2(s32)
+    BX_RET 14, _, implicit %r0
+
+...