[ARM] GlobalISel: Support G_(S|U)REM for s8 and s16

Widen to s32, and then do whatever Lowering/Custom/Libcall action the
subtarget wants.

llvm-svn: 308285
This commit is contained in:
Diana Picus 2017-07-18 10:07:01 +00:00
parent caa2269e29
commit 5112f60df1
3 changed files with 230 additions and 2 deletions

View File

@ -66,14 +66,16 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
setAction({Op, s32}, Libcall);
}
// FIXME: Support s8 and s16 as well
for (unsigned Op : {G_SREM, G_UREM})
for (unsigned Op : {G_SREM, G_UREM}) {
for (auto Ty : {s8, s16})
setAction({Op, Ty}, WidenScalar);
if (ST.hasDivideInARMMode())
setAction({Op, s32}, Lower);
else if (AEABI(ST))
setAction({Op, s32}, Custom);
else
setAction({Op, s32}, Libcall);
}
for (unsigned Op : {G_SEXT, G_ZEXT}) {
setAction({Op, s32}, Legal);

View File

@ -87,3 +87,55 @@ define arm_aapcscc i32 @test_urem_i32(i32 %x, i32 %y) {
%r = urem i32 %x, %y
ret i32 %r
}
define arm_aapcscc i16 @test_srem_i16(i16 %x, i16 %y) {
; CHECK-LABEL: test_srem_i16:
; CHECK-DAG: sxth r0, r0
; CHECK-DAG: sxth r1, r1
; HWDIV: sdiv [[Q:r[0-9]+]], r0, r1
; HWDIV: mul [[P:r[0-9]+]], [[Q]], r1
; HWDIV: sub r0, r0, [[P]]
; SOFT-AEABI: blx __aeabi_idivmod
; SOFT-DEFAULT: blx __modsi3
%r = srem i16 %x, %y
ret i16 %r
}
define arm_aapcscc i16 @test_urem_i16(i16 %x, i16 %y) {
; CHECK-LABEL: test_urem_i16:
; CHECK-DAG: uxth r0, r0
; CHECK-DAG: uxth r1, r1
; HWDIV: udiv [[Q:r[0-9]+]], r0, r1
; HWDIV: mul [[P:r[0-9]+]], [[Q]], r1
; HWDIV: sub r0, r0, [[P]]
; SOFT-AEABI: blx __aeabi_uidivmod
; SOFT-DEFAULT: blx __umodsi3
%r = urem i16 %x, %y
ret i16 %r
}
define arm_aapcscc i8 @test_srem_i8(i8 %x, i8 %y) {
; CHECK-LABEL: test_srem_i8:
; CHECK-DAG: sxtb r0, r0
; CHECK-DAG: sxtb r1, r1
; HWDIV: sdiv [[Q:r[0-9]+]], r0, r1
; HWDIV: mul [[P:r[0-9]+]], [[Q]], r1
; HWDIV: sub r0, r0, [[P]]
; SOFT-AEABI: blx __aeabi_idivmod
; SOFT-DEFAULT: blx __modsi3
%r = srem i8 %x, %y
ret i8 %r
}
define arm_aapcscc i8 @test_urem_i8(i8 %x, i8 %y) {
; CHECK-LABEL: test_urem_i8:
; CHECK-DAG: uxtb r0, r0
; CHECK-DAG: uxtb r1, r1
; HWDIV: udiv [[Q:r[0-9]+]], r0, r1
; HWDIV: mul [[P:r[0-9]+]], [[Q]], r1
; HWDIV: sub r0, r0, [[P]]
; SOFT-AEABI: blx __aeabi_uidivmod
; SOFT-DEFAULT: blx __umodsi3
%r = urem i8 %x, %y
ret i8 %r
}

View File

@ -14,6 +14,12 @@
define void @test_srem_i32() { ret void }
define void @test_urem_i32() { ret void }
define void @test_srem_i16() { ret void }
define void @test_urem_i16() { ret void }
define void @test_srem_i8() { ret void }
define void @test_urem_i8() { ret void }
...
---
name: test_sdiv_i32
@ -323,3 +329,171 @@ body: |
%r0 = COPY %2(s32)
BX_RET 14, _, implicit %r0
...
---
name: test_srem_i16
# CHECK-LABEL: name: test_srem_i16
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]+]](s16) = COPY %r0
; CHECK-DAG: [[Y:%[0-9]+]](s16) = COPY %r1
; CHECK-DAG: [[X32:%[0-9]+]](s32) = G_SEXT [[X]](s16)
; CHECK-DAG: [[Y32:%[0-9]+]](s32) = G_SEXT [[Y]](s16)
%0(s16) = COPY %r0
%1(s16) = COPY %r1
; HWDIV: [[Q32:%[0-9]+]](s32) = G_SDIV [[X32]], [[Y32]]
; HWDIV: [[P32:%[0-9]+]](s32) = G_MUL [[Q32]], [[Y32]]
; HWDIV: [[R32:%[0-9]+]](s32) = G_SUB [[X32]], [[P32]]
; SOFT-NOT: G_SREM
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: %r0 = COPY [[X32]]
; SOFT-DAG: %r1 = COPY [[Y32]]
; SOFT-AEABI: BLX $__aeabi_idivmod, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
; SOFT-AEABI: [[R32:%[0-9]+]](s32) = COPY %r1
; SOFT-DEFAULT: BLX $__modsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
; SOFT-DEFAULT: [[R32:%[0-9]+]](s32) = COPY %r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_SREM
; CHECK: [[R:%[0-9]+]](s16) = G_TRUNC [[R32]]
; SOFT-NOT: G_SREM
%2(s16) = G_SREM %0, %1
; CHECK: %r0 = COPY [[R]]
%r0 = COPY %2(s16)
BX_RET 14, _, implicit %r0
...
---
name: test_urem_i16
# CHECK-LABEL: name: test_urem_i16
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]+]](s16) = COPY %r0
; CHECK-DAG: [[Y:%[0-9]+]](s16) = COPY %r1
; CHECK-DAG: [[X32:%[0-9]+]](s32) = G_ZEXT [[X]](s16)
; CHECK-DAG: [[Y32:%[0-9]+]](s32) = G_ZEXT [[Y]](s16)
%0(s16) = COPY %r0
%1(s16) = COPY %r1
; HWDIV: [[Q32:%[0-9]+]](s32) = G_UDIV [[X32]], [[Y32]]
; HWDIV: [[P32:%[0-9]+]](s32) = G_MUL [[Q32]], [[Y32]]
; HWDIV: [[R32:%[0-9]+]](s32) = G_SUB [[X32]], [[P32]]
; SOFT-NOT: G_UREM
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: %r0 = COPY [[X32]]
; SOFT-DAG: %r1 = COPY [[Y32]]
; SOFT-AEABI: BLX $__aeabi_uidivmod, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
; SOFT-AEABI: [[R32:%[0-9]+]](s32) = COPY %r1
; SOFT-DEFAULT: BLX $__umodsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
; SOFT-DEFAULT: [[R32:%[0-9]+]](s32) = COPY %r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_UREM
; CHECK: [[R:%[0-9]+]](s16) = G_TRUNC [[R32]]
; SOFT-NOT: G_UREM
%2(s16) = G_UREM %0, %1
; CHECK: %r0 = COPY [[R]]
%r0 = COPY %2(s16)
BX_RET 14, _, implicit %r0
...
---
name: test_srem_i8
# CHECK-LABEL: name: test_srem_i8
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]+]](s8) = COPY %r0
; CHECK-DAG: [[Y:%[0-9]+]](s8) = COPY %r1
; CHECK-DAG: [[X32:%[0-9]+]](s32) = G_SEXT [[X]](s8)
; CHECK-DAG: [[Y32:%[0-9]+]](s32) = G_SEXT [[Y]](s8)
%0(s8) = COPY %r0
%1(s8) = COPY %r1
; HWDIV: [[Q32:%[0-9]+]](s32) = G_SDIV [[X32]], [[Y32]]
; HWDIV: [[P32:%[0-9]+]](s32) = G_MUL [[Q32]], [[Y32]]
; HWDIV: [[R32:%[0-9]+]](s32) = G_SUB [[X32]], [[P32]]
; SOFT-NOT: G_SREM
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: %r0 = COPY [[X32]]
; SOFT-DAG: %r1 = COPY [[Y32]]
; SOFT-AEABI: BLX $__aeabi_idivmod, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
; SOFT-AEABI: [[R32:%[0-9]+]](s32) = COPY %r1
; SOFT-DEFAULT: BLX $__modsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
; SOFT-DEFAULT: [[R32:%[0-9]+]](s32) = COPY %r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_SREM
; CHECK: [[R:%[0-9]+]](s8) = G_TRUNC [[R32]]
; SOFT-NOT: G_SREM
%2(s8) = G_SREM %0, %1
; CHECK: %r0 = COPY [[R]]
%r0 = COPY %2(s8)
BX_RET 14, _, implicit %r0
...
---
name: test_urem_i8
# CHECK-LABEL: name: test_urem_i8
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]+]](s8) = COPY %r0
; CHECK-DAG: [[Y:%[0-9]+]](s8) = COPY %r1
; CHECK-DAG: [[X32:%[0-9]+]](s32) = G_ZEXT [[X]](s8)
; CHECK-DAG: [[Y32:%[0-9]+]](s32) = G_ZEXT [[Y]](s8)
%0(s8) = COPY %r0
%1(s8) = COPY %r1
; HWDIV: [[Q32:%[0-9]+]](s32) = G_UDIV [[X32]], [[Y32]]
; HWDIV: [[P32:%[0-9]+]](s32) = G_MUL [[Q32]], [[Y32]]
; HWDIV: [[R32:%[0-9]+]](s32) = G_SUB [[X32]], [[P32]]
; SOFT-NOT: G_UREM
; SOFT: ADJCALLSTACKDOWN
; SOFT-DAG: %r0 = COPY [[X32]]
; SOFT-DAG: %r1 = COPY [[Y32]]
; SOFT-AEABI: BLX $__aeabi_uidivmod, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
; SOFT-AEABI: [[R32:%[0-9]+]](s32) = COPY %r1
; SOFT-DEFAULT: BLX $__umodsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
; SOFT-DEFAULT: [[R32:%[0-9]+]](s32) = COPY %r0
; SOFT: ADJCALLSTACKUP
; SOFT-NOT: G_UREM
; CHECK: [[R:%[0-9]+]](s8) = G_TRUNC [[R32]]
; SOFT-NOT: G_UREM
%2(s8) = G_UREM %0, %1
; CHECK: %r0 = COPY [[R]]
%r0 = COPY %2(s8)
BX_RET 14, _, implicit %r0
...