[ARM GlobalISel] Support integer division for Thumb2

Support G_SDIV, G_UDIV, G_SREM and G_UREM.

The only significant difference between arm and thumb mode is that we
need to check a different subtarget feature.

llvm-svn: 352346
This commit is contained in:
Diana Picus 2019-01-28 10:37:30 +00:00
parent 059c1d8e72
commit 574e0c5e32
3 changed files with 145 additions and 58 deletions

View File

@ -92,6 +92,27 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
.legalFor({{s32, s32}})
.clampScalar(1, s32, s32);
bool HasHWDivide = (!ST.isThumb() && ST.hasDivideInARMMode()) ||
(ST.isThumb() && ST.hasDivideInThumbMode());
if (HasHWDivide)
getActionDefinitionsBuilder({G_SDIV, G_UDIV})
.legalFor({s32})
.clampScalar(0, s32, s32);
else
getActionDefinitionsBuilder({G_SDIV, G_UDIV})
.libcallFor({s32})
.clampScalar(0, s32, s32);
for (unsigned Op : {G_SREM, G_UREM}) {
setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
if (HasHWDivide)
setAction({Op, s32}, Lower);
else if (AEABI(ST))
setAction({Op, s32}, Custom);
else
setAction({Op, s32}, Libcall);
}
getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}});
getActionDefinitionsBuilder(G_PTRTOINT).legalFor({{s32, p0}});
@ -120,25 +141,6 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
if (ST.hasDivideInARMMode())
getActionDefinitionsBuilder({G_SDIV, G_UDIV})
.legalFor({s32})
.clampScalar(0, s32, s32);
else
getActionDefinitionsBuilder({G_SDIV, G_UDIV})
.libcallFor({s32})
.clampScalar(0, s32, s32);
for (unsigned Op : {G_SREM, G_UREM}) {
setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
if (ST.hasDivideInARMMode())
setAction({Op, s32}, Lower);
else if (AEABI(ST))
setAction({Op, s32}, Custom);
else
setAction({Op, s32}, Libcall);
}
if (ST.hasV5TOps()) {
getActionDefinitionsBuilder(G_CTLZ)
.legalFor({s32})

View File

@ -1,7 +1,11 @@
# RUN: llc -O0 -mtriple arm-linux-gnueabi -mattr=+hwdiv-arm -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV
# RUN: llc -O0 -mtriple arm-linux-gnueabi -mattr=-hwdiv-arm -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT,SOFT-AEABI
# RUN: llc -O0 -mtriple arm-linux-gnueabi -mattr=-hwdiv-arm -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT,SOFT-AEABI,ARM-AEABI
# RUN: llc -O0 -mtriple arm-linux-gnu -mattr=+hwdiv-arm -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV
# RUN: llc -O0 -mtriple arm-linux-gnu -mattr=-hwdiv-arm -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT,SOFT-DEFAULT
# RUN: llc -O0 -mtriple arm-linux-gnu -mattr=-hwdiv-arm -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT,SOFT-DEFAULT,ARM-DEFAULT
# RUN: llc -O0 -mtriple thumb-linux-gnueabi -mattr=+v6t2,+hwdiv -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV
# RUN: llc -O0 -mtriple thumb-linux-gnueabi -mattr=+v6t2,-hwdiv -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT,SOFT-AEABI,THUMB-AEABI
# RUN: llc -O0 -mtriple thumb-linux-gnu -mattr=+v6t2,+hwdiv -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV
# RUN: llc -O0 -mtriple thumb-linux-gnu -mattr=+v6t2,-hwdiv -run-pass=legalizer %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT,SOFT-DEFAULT,THUMB-DEFAULT
--- |
define void @test_sdiv_i32() { ret void }
define void @test_udiv_i32() { ret void }
@ -46,10 +50,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X]]
; SOFT-DAG: $r1 = COPY [[Y]]
; SOFT-AEABI: BL &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R:%[0-9]+]]:_(s32) = COPY $r0
; SOFT-DEFAULT: BL &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R:%[0-9]+]]:_(s32) = COPY $r0
; ARM-AEABI: BL &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT: [[R:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_SDIV
%2(s32) = G_SDIV %0, %1
@ -82,10 +87,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X]]
; SOFT-DAG: $r1 = COPY [[Y]]
; SOFT-AEABI: BL &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R:%[0-9]+]]:_(s32) = COPY $r0
; SOFT-DEFAULT: BL &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R:%[0-9]+]]:_(s32) = COPY $r0
; ARM-AEABI: BL &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT: [[R:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_UDIV
%2(s32) = G_UDIV %0, %1
@ -133,10 +139,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X32]]
; SOFT-DAG: $r1 = COPY [[Y32]]
; SOFT-AEABI: BL &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT-DEFAULT: BL &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; ARM-AEABI: BL &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_SDIV
; CHECK: [[R:%[0-9]+]]:_(s32) = G_ASHR
@ -185,10 +192,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X32]]
; SOFT-DAG: $r1 = COPY [[Y32]]
; SOFT-AEABI: BL &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT-DEFAULT: BL &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; ARM-AEABI: BL &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_UDIV
; CHECK: [[R:%[0-9]+]]:_(s32) = G_AND
@ -239,10 +247,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X32]]
; SOFT-DAG: $r1 = COPY [[Y32]]
; SOFT-AEABI: BL &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT-DEFAULT: BL &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; ARM-AEABI: BL &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_idiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__divsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_SDIV
; CHECK: [[R:%[0-9]+]]:_(s32) = G_ASHR
@ -291,10 +300,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X32]]
; SOFT-DAG: $r1 = COPY [[Y32]]
; SOFT-AEABI: BL &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT-DEFAULT: BL &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; ARM-AEABI: BL &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_uidiv, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__udivsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_UDIV
; CHECK: [[R:%[0-9]+]]:_(s32) = G_AND
@ -332,9 +342,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X]]
; SOFT-DAG: $r1 = COPY [[Y]]
; SOFT-AEABI: BL &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
; ARM-AEABI: BL &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
; SOFT-AEABI: [[R:%[0-9]+]]:_(s32) = COPY $r1
; SOFT-DEFAULT: BL &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_SREM
@ -370,9 +382,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X]]
; SOFT-DAG: $r1 = COPY [[Y]]
; SOFT-AEABI: BL &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
; ARM-AEABI: BL &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
; SOFT-AEABI: [[R:%[0-9]+]]:_(s32) = COPY $r1
; SOFT-DEFAULT: BL &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_UREM
@ -423,9 +437,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X32]]
; SOFT-DAG: $r1 = COPY [[Y32]]
; SOFT-AEABI: BL &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-AEABI: BL &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R32:%[0-9]+]]:_(s32) = COPY $r1
; SOFT-DEFAULT: BL &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_SREM
@ -477,9 +493,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X32]]
; SOFT-DAG: $r1 = COPY [[Y32]]
; SOFT-AEABI: BL &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-AEABI: BL &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R32:%[0-9]+]]:_(s32) = COPY $r1
; SOFT-DEFAULT: BL &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_UREM
@ -533,9 +551,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X32]]
; SOFT-DAG: $r1 = COPY [[Y32]]
; SOFT-AEABI: BL &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-AEABI: BL &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_idivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R32:%[0-9]+]]:_(s32) = COPY $r1
; SOFT-DEFAULT: BL &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__modsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_SREM
@ -587,9 +607,11 @@ body: |
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: $r0 = COPY [[X32]]
; SOFT-DAG: $r1 = COPY [[Y32]]
; SOFT-AEABI: BL &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-AEABI: BL &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-AEABI: tBL 14, $noreg, &__aeabi_uidivmod, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-AEABI: [[R32:%[0-9]+]]:_(s32) = COPY $r1
; SOFT-DEFAULT: BL &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; ARM-DEFAULT: BL &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; THUMB-DEFAULT: tBL 14, $noreg, &__umodsi3, {{.*}}, implicit $r0, implicit $r1, implicit-def $r0
; SOFT-DEFAULT: [[R32:%[0-9]+]]:_(s32) = COPY $r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_UREM

View File

@ -1,4 +1,4 @@
# RUN: llc -O0 -mtriple thumb-- -mattr=+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
# RUN: llc -O0 -mtriple thumb-- -mattr=+v6t2,+hwdiv -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
--- |
define void @test_add_regs() { ret void }
define void @test_add_fold_imm() { ret void }
@ -10,6 +10,9 @@
define void @test_mul() { ret void }
define void @test_mla() { ret void }
define void @test_sdiv() { ret void }
define void @test_udiv() { ret void }
...
---
name: test_add_regs
@ -249,3 +252,63 @@ body: |
BX_RET 14, $noreg, implicit $r0
; CHECK: BX_RET 14, $noreg, implicit $r0
...
---
name: test_sdiv
# CHECK-LABEL: name: test_sdiv
legalized: true
regBankSelected: true
selected: false
# CHECK: selected: true
registers:
- { id: 0, class: gprb }
- { id: 1, class: gprb }
- { id: 2, class: gprb }
body: |
bb.0:
liveins: $r0, $r1
%0(s32) = COPY $r0
; CHECK: [[VREGX:%[0-9]+]]:rgpr = COPY $r0
%1(s32) = COPY $r1
; CHECK: [[VREGY:%[0-9]+]]:rgpr = COPY $r1
%2(s32) = G_SDIV %0, %1
; CHECK: [[VREGRES:%[0-9]+]]:rgpr = t2SDIV [[VREGX]], [[VREGY]], 14, $noreg
$r0 = COPY %2(s32)
; CHECK: $r0 = COPY [[VREGRES]]
BX_RET 14, $noreg, implicit $r0
; CHECK: BX_RET 14, $noreg, implicit $r0
...
---
name: test_udiv
# CHECK-LABEL: name: test_udiv
legalized: true
regBankSelected: true
selected: false
# CHECK: selected: true
registers:
- { id: 0, class: gprb }
- { id: 1, class: gprb }
- { id: 2, class: gprb }
body: |
bb.0:
liveins: $r0, $r1
%0(s32) = COPY $r0
; CHECK: [[VREGX:%[0-9]+]]:rgpr = COPY $r0
%1(s32) = COPY $r1
; CHECK: [[VREGY:%[0-9]+]]:rgpr = COPY $r1
%2(s32) = G_UDIV %0, %1
; CHECK: [[VREGRES:%[0-9]+]]:rgpr = t2UDIV [[VREGX]], [[VREGY]], 14, $noreg
$r0 = COPY %2(s32)
; CHECK: $r0 = COPY [[VREGRES]]
BX_RET 14, $noreg, implicit $r0
; CHECK: BX_RET 14, $noreg, implicit $r0
...