forked from OSchip/llvm-project
[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
This commit is contained in:
parent
e97822e1b7
commit
b70e88bdec
|
@ -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;
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
...
|
|
@ -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
|
||||
|
@ -290,6 +294,58 @@ body: |
|
|||
%r0 = COPY %2(s8)
|
||||
BX_RET 14, _, implicit %r0
|
||||
|
||||
...
|
||||
---
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue