summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/ARM/ARMInstructionSelector.cpp35
-rw-r--r--llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir34
2 files changed, 63 insertions, 6 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
index dcdd0e83550..5201ddba781 100644
--- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
+++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
@@ -61,8 +61,12 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
const TargetRegisterClass *RC = &ARM::GPRRegClass;
if (RegBank->getID() == ARM::FPRRegBankID) {
- assert(DstSize == 32 && "Only 32-bit FP values are supported");
- RC = &ARM::SPRRegClass;
+ if (DstSize == 32)
+ RC = &ARM::SPRRegClass;
+ else if (DstSize == 64)
+ RC = &ARM::DPRRegClass;
+ else
+ llvm_unreachable("Unsupported destination size");
}
// No need to constrain SrcReg. It will get constrained when
@@ -76,6 +80,28 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
return true;
}
+static bool selectFAdd(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII,
+ MachineRegisterInfo &MRI) {
+ assert(TII.getSubtarget().hasVFP2() && "Can't select fp add without vfp");
+
+ LLT Ty = MRI.getType(MIB->getOperand(0).getReg());
+ unsigned ValSize = Ty.getSizeInBits();
+
+ if (ValSize == 32) {
+ if (TII.getSubtarget().useNEONForSinglePrecisionFP())
+ return false;
+ MIB->setDesc(TII.get(ARM::VADDS));
+ } else {
+ assert(ValSize == 64 && "Unsupported size for floating point value");
+ if (TII.getSubtarget().isFPOnlySP())
+ return false;
+ MIB->setDesc(TII.get(ARM::VADDD));
+ }
+ MIB.add(predOps(ARMCC::AL));
+
+ return true;
+}
+
/// Select the opcode for simple extensions (that translate to a single SXT/UXT
/// instruction). Extension operations more complicated than that should not
/// invoke this.
@@ -186,11 +212,8 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
break;
case G_FADD:
- if (!TII.getSubtarget().hasVFP2() ||
- TII.getSubtarget().useNEONForSinglePrecisionFP())
+ if (!selectFAdd(MIB, TII, MRI))
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
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
index 48d58d71eb6..659c52c338d 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
@@ -10,6 +10,7 @@
define void @test_add_s32() { ret void }
define void @test_fadd_s32() #0 { ret void }
+ define void @test_fadd_s64() #0 { ret void }
define void @test_load_from_stack() { ret void }
@@ -254,6 +255,39 @@ body: |
; CHECK: BX_RET 14, _, implicit %s0
...
---
+name: test_fadd_s64
+# CHECK-LABEL: name: test_fadd_s64
+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: dpr
+# CHECK: id: 1, class: dpr
+# CHECK: id: 2, class: dpr
+body: |
+ bb.0:
+ liveins: %d0, %d1
+
+ %0(s64) = COPY %d0
+ ; CHECK: [[VREGX:%[0-9]+]] = COPY %d0
+
+ %1(s64) = COPY %d1
+ ; CHECK: [[VREGY:%[0-9]+]] = COPY %d1
+
+ %2(s64) = G_FADD %0, %1
+ ; CHECK: [[VREGSUM:%[0-9]+]] = VADDD [[VREGX]], [[VREGY]], 14, _
+
+ %d0 = COPY %2(s64)
+ ; CHECK: %d0 = COPY [[VREGSUM]]
+
+ BX_RET 14, _, implicit %d0
+ ; CHECK: BX_RET 14, _, implicit %d0
+...
+---
name: test_load_from_stack
# CHECK-LABEL: name: test_load_from_stack
legalized: true
OpenPOWER on IntegriCloud