summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDiana Picus <diana.picus@linaro.org>2017-04-24 08:20:05 +0000
committerDiana Picus <diana.picus@linaro.org>2017-04-24 08:20:05 +0000
commitb70e88bdec9791538624399131071e56e124641a (patch)
treed5f25c705e691f3c17dff80cbc6aad04a0f5c495
parente97822e1b7af54c20f0185340e87168ab4e00dec (diff)
downloadbcm5719-llvm-b70e88bdec9791538624399131071e56e124641a.tar.gz
bcm5719-llvm-b70e88bdec9791538624399131071e56e124641a.zip
[ARM] GlobalISel: Support G_(S|U)DIV for s32
Add support for both targets with hardware division and without. For hardware division we have to add support throughout the pipeline (legalizer, reg bank select, instruction select). For targets without hardware division, we only need to mark it as a libcall. llvm-svn: 301164
-rw-r--r--llvm/lib/Target/ARM/ARMInstructionSelector.cpp10
-rw-r--r--llvm/lib/Target/ARM/ARMLegalizerInfo.cpp7
-rw-r--r--llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp2
-rw-r--r--llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir70
-rw-r--r--llvm/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll23
-rw-r--r--llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir76
-rw-r--r--llvm/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir56
7 files changed, 244 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
index a99dc159d11..1c13d51a468 100644
--- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
+++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
@@ -332,6 +332,16 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
}
MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
break;
+ case G_SDIV:
+ assert(TII.getSubtarget().hasDivideInARMMode() && "Unsupported operation");
+ I.setDesc(TII.get(ARM::SDIV));
+ MIB.add(predOps(ARMCC::AL));
+ break;
+ case G_UDIV:
+ assert(TII.getSubtarget().hasDivideInARMMode() && "Unsupported operation");
+ I.setDesc(TII.get(ARM::UDIV));
+ MIB.add(predOps(ARMCC::AL));
+ break;
case G_FADD:
if (!selectFAdd(MIB, TII, MRI))
return false;
diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
index fe9681439e6..d1c5d964d95 100644
--- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
@@ -47,6 +47,13 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
for (auto Ty : {s1, s8, s16, s32})
setAction({Op, Ty}, Legal);
+ for (unsigned Op : {G_SDIV, G_UDIV}) {
+ if (ST.hasDivideInARMMode())
+ setAction({Op, s32}, Legal);
+ else
+ setAction({Op, s32}, Libcall);
+ }
+
for (unsigned Op : {G_SEXT, G_ZEXT}) {
setAction({Op, s32}, Legal);
for (auto Ty : {s1, s8, s16})
diff --git a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
index 7c5ba499550..7325817d446 100644
--- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp
@@ -221,6 +221,8 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
case G_ADD:
case G_SUB:
case G_MUL:
+ case G_SDIV:
+ case G_UDIV:
case G_SEXT:
case G_ZEXT:
case G_TRUNC:
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
index 5fd6e93263a..83ab2659ef4 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir
@@ -23,6 +23,9 @@
define void @test_mul_s32() #1 { ret void }
define void @test_mulv5_s32() { ret void }
+ define void @test_sdiv_s32() #2 { ret void }
+ define void @test_udiv_s32() #2 { ret void }
+
define void @test_load_from_stack() { ret void }
define void @test_load_f32() #0 { ret void }
define void @test_load_f64() #0 { ret void }
@@ -37,6 +40,7 @@
attributes #0 = { "target-features"="+vfp2,-neonfp" }
attributes #1 = { "target-features"="+v6" }
+ attributes #2 = { "target-features"="+hwdiv-arm" }
...
---
name: test_zext_s1
@@ -569,6 +573,72 @@ body: |
; CHECK: BX_RET 14, _, implicit %r0
...
---
+name: test_sdiv_s32
+# CHECK-LABEL: name: test_sdiv_s32
+legalized: true
+regBankSelected: true
+selected: false
+# CHECK: selected: true
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+# CHECK: id: 0, class: gpr
+# CHECK: id: 1, class: gpr
+# CHECK: id: 2, class: gpr
+body: |
+ bb.0:
+ liveins: %r0, %r1
+
+ %0(s32) = COPY %r0
+ ; CHECK: [[VREGX:%[0-9]+]] = COPY %r0
+
+ %1(s32) = COPY %r1
+ ; CHECK: [[VREGY:%[0-9]+]] = COPY %r1
+
+ %2(s32) = G_SDIV %0, %1
+ ; CHECK: [[VREGRES:%[0-9]+]] = SDIV [[VREGX]], [[VREGY]], 14, _
+
+ %r0 = COPY %2(s32)
+ ; CHECK: %r0 = COPY [[VREGRES]]
+
+ BX_RET 14, _, implicit %r0
+ ; CHECK: BX_RET 14, _, implicit %r0
+...
+---
+name: test_udiv_s32
+# CHECK-LABEL: name: test_udiv_s32
+legalized: true
+regBankSelected: true
+selected: false
+# CHECK: selected: true
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+# CHECK: id: 0, class: gpr
+# CHECK: id: 1, class: gpr
+# CHECK: id: 2, class: gpr
+body: |
+ bb.0:
+ liveins: %r0, %r1
+
+ %0(s32) = COPY %r0
+ ; CHECK: [[VREGX:%[0-9]+]] = COPY %r0
+
+ %1(s32) = COPY %r1
+ ; CHECK: [[VREGY:%[0-9]+]] = COPY %r1
+
+ %2(s32) = G_UDIV %0, %1
+ ; CHECK: [[VREGRES:%[0-9]+]] = UDIV [[VREGX]], [[VREGY]], 14, _
+
+ %r0 = COPY %2(s32)
+ ; CHECK: %r0 = COPY [[VREGRES]]
+
+ BX_RET 14, _, implicit %r0
+ ; CHECK: BX_RET 14, _, implicit %r0
+...
+---
name: test_load_from_stack
# CHECK-LABEL: name: test_load_from_stack
legalized: true
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll b/llvm/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll
new file mode 100644
index 00000000000..87655b53bf0
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll
@@ -0,0 +1,23 @@
+; RUN: llc -mtriple arm-gnueabi -mattr=+hwdiv-arm -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV
+; RUN: llc -mtriple arm-gnueabi -mattr=-hwdiv-arm -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT-AEABI
+; RUN: llc -mtriple arm-gnu -mattr=+hwdiv-arm -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV
+; RUN: llc -mtriple arm-gnu -mattr=-hwdiv-arm -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT-DEFAULT
+
+define arm_aapcscc i32 @test_sdiv_i32(i32 %a, i32 %b) {
+; CHECK-LABEL: test_sdiv_i32:
+; HWDIV: sdiv r0, r0, r1
+; SOFT-AEABI: blx __aeabi_idiv
+; SOFT-DEFAULT: blx __divsi3
+ %r = sdiv i32 %a, %b
+ ret i32 %r
+}
+
+define arm_aapcscc i32 @test_udiv_i32(i32 %a, i32 %b) {
+; CHECK-LABEL: test_udiv_i32:
+; HWDIV: udiv r0, r0, r1
+; SOFT-AEABI: blx __aeabi_uidiv
+; SOFT-DEFAULT: blx __udivsi3
+ %r = udiv i32 %a, %b
+ ret i32 %r
+}
+
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir
new file mode 100644
index 00000000000..1f056067e8d
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir
@@ -0,0 +1,76 @@
+# RUN: llc -mtriple arm-linux-gnueabi -mattr=+hwdiv-arm -global-isel -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV
+# RUN: llc -mtriple arm-linux-gnueabi -mattr=-hwdiv-arm -global-isel -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT,SOFT-AEABI
+# RUN: llc -mtriple arm-linux-gnu -mattr=+hwdiv-arm -global-isel -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV
+# RUN: llc -mtriple arm-linux-gnu -mattr=-hwdiv-arm -global-isel -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT,SOFT-DEFAULT
+--- |
+ define void @test_sdiv_i32() { ret void }
+ define void @test_udiv_i32() { ret void }
+...
+---
+name: test_sdiv_i32
+# CHECK-LABEL: name: test_sdiv_i32
+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
+
+ ; CHECK-DAG: [[X:%[0-9]+]](s32) = COPY %r0
+ ; CHECK-DAG: [[Y:%[0-9]+]](s32) = COPY %r1
+ %0(s32) = COPY %r0
+ %1(s32) = COPY %r1
+ ; HWDIV: [[R:%[0-9]+]](s32) = G_SDIV [[X]], [[Y]]
+ ; SOFT: ADJCALLSTACKDOWN
+ ; SOFT-DAG: %r0 = COPY [[X]]
+ ; SOFT-DAG: %r1 = COPY [[Y]]
+ ; SOFT-AEABI: BLX $__aeabi_idiv, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
+ ; SOFT-AEABI: [[R:%[0-9]+]](s32) = COPY %r0
+ ; SOFT-DEFAULT: BLX $__divsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
+ ; SOFT-DEFAULT: [[R:%[0-9]+]](s32) = COPY %r0
+ ; SOFT: ADJCALLSTACKUP
+ %2(s32) = G_SDIV %0, %1
+ ; CHECK: %r0 = COPY [[R]]
+ %r0 = COPY %2(s32)
+ BX_RET 14, _, implicit %r0
+...
+---
+name: test_udiv_i32
+# CHECK-LABEL: name: test_udiv_i32
+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
+
+ ; CHECK-DAG: [[X:%[0-9]+]](s32) = COPY %r0
+ ; CHECK-DAG: [[Y:%[0-9]+]](s32) = COPY %r1
+ %0(s32) = COPY %r0
+ %1(s32) = COPY %r1
+ ; HWDIV: [[R:%[0-9]+]](s32) = G_UDIV [[X]], [[Y]]
+ ; SOFT: ADJCALLSTACKDOWN
+ ; SOFT-DAG: %r0 = COPY [[X]]
+ ; SOFT-DAG: %r1 = COPY [[Y]]
+ ; SOFT-AEABI: BLX $__aeabi_uidiv, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
+ ; SOFT-AEABI: [[R:%[0-9]+]](s32) = COPY %r0
+ ; SOFT-DEFAULT: BLX $__udivsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
+ ; SOFT-DEFAULT: [[R:%[0-9]+]](s32) = COPY %r0
+ ; SOFT: ADJCALLSTACKUP
+ %2(s32) = G_UDIV %0, %1
+ ; CHECK: %r0 = COPY [[R]]
+ %r0 = COPY %2(s32)
+ BX_RET 14, _, implicit %r0
+...
diff --git a/llvm/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir b/llvm/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir
index dc9163497ce..4e94fb4e348 100644
--- a/llvm/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir
+++ b/llvm/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir
@@ -13,6 +13,9 @@
define void @test_mul_s16() { ret void }
define void @test_mul_s8() { ret void }
+ define void @test_sdiv_s32() #1 { ret void }
+ define void @test_udiv_s32() #1 { ret void }
+
define void @test_loads() #0 { ret void }
define void @test_stores() #0 { ret void }
@@ -30,6 +33,7 @@
define void @test_soft_fp_s64() #0 { ret void }
attributes #0 = { "target-features"="+vfp2"}
+ attributes #1 = { "target-features"="+hwdiv-arm" }
...
---
name: test_add_s32
@@ -292,6 +296,58 @@ body: |
...
---
+name: test_sdiv_s32
+# CHECK-LABEL: name: test_sdiv_s32
+legalized: true
+regBankSelected: false
+selected: false
+# CHECK: registers:
+# CHECK: - { id: 0, class: gprb }
+# CHECK: - { id: 1, class: gprb }
+# CHECK: - { id: 2, class: gprb }
+
+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_SDIV %0, %1
+ %r0 = COPY %2(s32)
+ BX_RET 14, _, implicit %r0
+
+...
+---
+name: test_udiv_s32
+# CHECK-LABEL: name: test_udiv_s32
+legalized: true
+regBankSelected: false
+selected: false
+# CHECK: registers:
+# CHECK: - { id: 0, class: gprb }
+# CHECK: - { id: 1, class: gprb }
+# CHECK: - { id: 2, class: gprb }
+
+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_UDIV %0, %1
+ %r0 = COPY %2(s32)
+ BX_RET 14, _, implicit %r0
+
+...
+---
name: test_loads
# CHECK-LABEL: name: test_loads
legalized: true
OpenPOWER on IntegriCloud