diff options
Diffstat (limited to 'test/CodeGen/ARM')
-rw-r--r-- | test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir | 127 | ||||
-rw-r--r-- | test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll | 68 | ||||
-rw-r--r-- | test/CodeGen/ARM/GlobalISel/arm-isel.ll | 32 | ||||
-rw-r--r-- | test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir | 230 | ||||
-rw-r--r-- | test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir | 79 | ||||
-rw-r--r-- | test/CodeGen/ARM/GlobalISel/arm-unsupported.ll | 80 | ||||
-rw-r--r-- | test/CodeGen/ARM/bool-ext-inc.ll | 39 | ||||
-rw-r--r-- | test/CodeGen/ARM/fence-singlethread.ll | 16 | ||||
-rw-r--r-- | test/CodeGen/ARM/v6m-smul-with-overflow.ll | 16 | ||||
-rw-r--r-- | test/CodeGen/ARM/vpadd.ll | 20 |
10 files changed, 704 insertions, 3 deletions
diff --git a/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir b/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir index 21c774133f89..83ab2659ef4a 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir +++ b/test/CodeGen/ARM/GlobalISel/arm-instruction-select.mir @@ -5,6 +5,8 @@ define void @test_sext_s8() { ret void } define void @test_zext_s16() { ret void } + define void @test_trunc_s32_16() { ret void } + define void @test_add_s8() { ret void } define void @test_add_s16() { ret void } define void @test_add_s32() { ret void } @@ -21,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 } @@ -28,12 +33,14 @@ define void @test_stores() #0 { ret void } define void @test_gep() { ret void } - define void @test_constants() { ret void } + define void @test_constant_imm() { ret void } + define void @test_constant_cimm() { ret void } define void @test_soft_fp_double() #0 { ret void } attributes #0 = { "target-features"="+vfp2,-neonfp" } attributes #1 = { "target-features"="+v6" } + attributes #2 = { "target-features"="+hwdiv-arm" } ... --- name: test_zext_s1 @@ -142,6 +149,34 @@ body: | ; CHECK: BX_RET 14, _, implicit %r0 ... --- +name: test_trunc_s32_16 +# CHECK-LABEL: name: test_trunc_s32_16 +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: gprb } + - { id: 1, class: gprb } +# CHECK-DAG: id: 0, class: gpr +# CHECK-DAG: id: 1, class: gpr +body: | + bb.0: + liveins: %r0 + + %0(s32) = COPY %r0 + ; CHECK: [[VREGX:%[0-9]+]] = COPY %r0 + + %1(s16) = G_TRUNC %0(s32) + ; CHECK: [[VREGTRUNC:%[0-9]+]] = COPY [[VREGX]] + + %r0 = COPY %1(s16) + ; CHECK: %r0 = COPY [[VREGTRUNC]] + + BX_RET 14, _, implicit %r0 + ; CHECK: BX_RET 14, _, implicit %r0 +... +--- name: test_add_s8 # CHECK-LABEL: name: test_add_s8 legalized: true @@ -538,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 @@ -714,8 +815,8 @@ body: | BX_RET 14, _, implicit %r0 ... --- -name: test_constants -# CHECK-LABEL: name: test_constants +name: test_constant_imm +# CHECK-LABEL: name: test_constant_imm legalized: true regBankSelected: true selected: false @@ -732,6 +833,26 @@ body: | BX_RET 14, _, implicit %r0 ... --- +name: test_constant_cimm +# CHECK-LABEL: name: test_constant_cimm +legalized: true +regBankSelected: true +selected: false +# CHECK: selected: true +registers: + - { id: 0, class: gprb } +# CHECK: id: [[C:[0-9]+]], class: gpr +body: | + bb.0: + ; Adding a type on G_CONSTANT changes its operand from an Imm into a CImm. + ; We still want to see the same thing in the output though. + %0(s32) = G_CONSTANT i32 42 + ; CHECK: %[[C]] = MOVi 42, 14, _, _ + + %r0 = COPY %0(s32) + BX_RET 14, _, implicit %r0 +... +--- name: test_soft_fp_double # CHECK-LABEL: name: test_soft_fp_double legalized: true diff --git a/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll b/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll new file mode 100644 index 000000000000..2881740b016f --- /dev/null +++ b/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll @@ -0,0 +1,68 @@ +; We use V6 ops so we can easily check for the extensions (sxth vs bit tricks). +; RUN: llc -mtriple arm-gnueabi -mattr=+v6,+hwdiv-arm -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV +; RUN: llc -mtriple arm-gnueabi -mattr=+v6,-hwdiv-arm -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,SOFT-AEABI +; RUN: llc -mtriple arm-gnu -mattr=+v6,+hwdiv-arm -global-isel %s -o - | FileCheck %s -check-prefixes=CHECK,HWDIV +; RUN: llc -mtriple arm-gnu -mattr=+v6,-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 +} + +define arm_aapcscc i16 @test_sdiv_i16(i16 %a, i16 %b) { +; CHECK-LABEL: test_sdiv_i16: +; CHECK-DAG: sxth r0, r0 +; CHECK-DAG: sxth r1, r1 +; HWDIV: sdiv r0, r0, r1 +; SOFT-AEABI: blx __aeabi_idiv +; SOFT-DEFAULT: blx __divsi3 + %r = sdiv i16 %a, %b + ret i16 %r +} + +define arm_aapcscc i16 @test_udiv_i16(i16 %a, i16 %b) { +; CHECK-LABEL: test_udiv_i16: +; CHECK-DAG: uxth r0, r0 +; CHECK-DAG: uxth r1, r1 +; HWDIV: udiv r0, r0, r1 +; SOFT-AEABI: blx __aeabi_uidiv +; SOFT-DEFAULT: blx __udivsi3 + %r = udiv i16 %a, %b + ret i16 %r +} + +define arm_aapcscc i8 @test_sdiv_i8(i8 %a, i8 %b) { +; CHECK-LABEL: test_sdiv_i8: +; CHECK-DAG: sxtb r0, r0 +; CHECK-DAG: sxtb r1, r1 +; HWDIV: sdiv r0, r0, r1 +; SOFT-AEABI: blx __aeabi_idiv +; SOFT-DEFAULT: blx __divsi3 + %r = sdiv i8 %a, %b + ret i8 %r +} + +define arm_aapcscc i8 @test_udiv_i8(i8 %a, i8 %b) { +; CHECK-LABEL: test_udiv_i8: +; CHECK-DAG: uxtb r0, r0 +; CHECK-DAG: uxtb r1, r1 +; HWDIV: udiv r0, r0, r1 +; SOFT-AEABI: blx __aeabi_uidiv +; SOFT-DEFAULT: blx __udivsi3 + %r = udiv i8 %a, %b + ret i8 %r +} + diff --git a/test/CodeGen/ARM/GlobalISel/arm-isel.ll b/test/CodeGen/ARM/GlobalISel/arm-isel.ll index f3ca2915f306..da02bfe68519 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-isel.ll +++ b/test/CodeGen/ARM/GlobalISel/arm-isel.ll @@ -7,6 +7,14 @@ entry: ret void } +define i32 @test_constant_return_i32() { +; CHECK-LABEL: test_constant_return_i32: +; CHECK: mov r0, #42 +; CHECK: bx lr +entry: + ret i32 42 +} + define zeroext i1 @test_zext_i1(i1 %x) { ; CHECK-LABEL: test_zext_i1 ; CHECK: and r0, r0, #1 @@ -40,6 +48,30 @@ entry: ret i16 %x } +define void @test_trunc_i32_i16(i32 %v, i16 *%p) { +; CHECK-LABEL: test_trunc_i32_i16: +; The trunc doesn't result in any instructions, but we +; expect the store to be explicitly 16-bit. +; CHECK: strh r0, [r1] +; CHECK: bx lr +entry: + %v16 = trunc i32 %v to i16 + store i16 %v16, i16 *%p + ret void +} + +define void @test_trunc_i32_i8(i32 %v, i8 *%p) { +; CHECK-LABEL: test_trunc_i32_i8: +; The trunc doesn't result in any instructions, but we +; expect the store to be explicitly 8-bit. +; CHECK: strb r0, [r1] +; CHECK: bx lr +entry: + %v8 = trunc i32 %v to i8 + store i8 %v8, i8 *%p + ret void +} + define i8 @test_add_i8(i8 %x, i8 %y) { ; CHECK-LABEL: test_add_i8: ; CHECK: add r0, r0, r1 diff --git a/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir b/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir new file mode 100644 index 000000000000..6f3e09d328cf --- /dev/null +++ b/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir @@ -0,0 +1,230 @@ +# 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 } + + define void @test_sdiv_i16() { ret void } + define void @test_udiv_i16() { ret void } + + define void @test_sdiv_i8() { ret void } + define void @test_udiv_i8() { 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 +... +--- +name: test_sdiv_i16 +# CHECK-LABEL: name: test_sdiv_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: [[R32:%[0-9]+]](s32) = G_SDIV [[X32]], [[Y32]] + ; SOFT: ADJCALLSTACKDOWN + ; SOFT-DAG: %r0 = COPY [[X32]] + ; SOFT-DAG: %r1 = COPY [[Y32]] + ; SOFT-AEABI: BLX $__aeabi_idiv, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-AEABI: [[R32:%[0-9]+]](s32) = COPY %r0 + ; SOFT-DEFAULT: BLX $__divsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-DEFAULT: [[R32:%[0-9]+]](s32) = COPY %r0 + ; SOFT: ADJCALLSTACKUP + ; CHECK: [[R:%[0-9]+]](s16) = G_TRUNC [[R32]] + %2(s16) = G_SDIV %0, %1 + ; CHECK: %r0 = COPY [[R]] + %r0 = COPY %2(s16) + BX_RET 14, _, implicit %r0 +... +--- +name: test_udiv_i16 +# CHECK-LABEL: name: test_udiv_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: [[R32:%[0-9]+]](s32) = G_UDIV [[X32]], [[Y32]] + ; SOFT: ADJCALLSTACKDOWN + ; SOFT-DAG: %r0 = COPY [[X32]] + ; SOFT-DAG: %r1 = COPY [[Y32]] + ; SOFT-AEABI: BLX $__aeabi_uidiv, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-AEABI: [[R32:%[0-9]+]](s32) = COPY %r0 + ; SOFT-DEFAULT: BLX $__udivsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-DEFAULT: [[R32:%[0-9]+]](s32) = COPY %r0 + ; SOFT: ADJCALLSTACKUP + ; CHECK: [[R:%[0-9]+]](s16) = G_TRUNC [[R32]] + %2(s16) = G_UDIV %0, %1 + ; CHECK: %r0 = COPY [[R]] + %r0 = COPY %2(s16) + BX_RET 14, _, implicit %r0 +... +--- +name: test_sdiv_i8 +# CHECK-LABEL: name: test_sdiv_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: [[R32:%[0-9]+]](s32) = G_SDIV [[X32]], [[Y32]] + ; SOFT: ADJCALLSTACKDOWN + ; SOFT-DAG: %r0 = COPY [[X32]] + ; SOFT-DAG: %r1 = COPY [[Y32]] + ; SOFT-AEABI: BLX $__aeabi_idiv, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-AEABI: [[R32:%[0-9]+]](s32) = COPY %r0 + ; SOFT-DEFAULT: BLX $__divsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-DEFAULT: [[R32:%[0-9]+]](s32) = COPY %r0 + ; SOFT: ADJCALLSTACKUP + ; CHECK: [[R:%[0-9]+]](s8) = G_TRUNC [[R32]] + %2(s8) = G_SDIV %0, %1 + ; CHECK: %r0 = COPY [[R]] + %r0 = COPY %2(s8) + BX_RET 14, _, implicit %r0 +... +--- +name: test_udiv_i8 +# CHECK-LABEL: name: test_udiv_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: [[R32:%[0-9]+]](s32) = G_UDIV [[X32]], [[Y32]] + ; SOFT: ADJCALLSTACKDOWN + ; SOFT-DAG: %r0 = COPY [[X32]] + ; SOFT-DAG: %r1 = COPY [[Y32]] + ; SOFT-AEABI: BLX $__aeabi_uidiv, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-AEABI: [[R32:%[0-9]+]](s32) = COPY %r0 + ; SOFT-DEFAULT: BLX $__udivsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0 + ; SOFT-DEFAULT: [[R32:%[0-9]+]](s32) = COPY %r0 + ; SOFT: ADJCALLSTACKUP + ; CHECK: [[R:%[0-9]+]](s8) = G_TRUNC [[R32]] + %2(s8) = G_UDIV %0, %1 + ; CHECK: %r0 = COPY [[R]] + %r0 = COPY %2(s8) + BX_RET 14, _, implicit %r0 +... diff --git a/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir b/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir index e7935832f98a..4e94fb4e3481 100644 --- a/test/CodeGen/ARM/GlobalISel/arm-regbankselect.mir +++ b/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 } @@ -22,12 +25,15 @@ define void @test_constants() { ret void } + define void @test_trunc_s32_16() { ret void } + define void @test_fadd_s32() #0 { ret void } define void @test_fadd_s64() #0 { ret void } 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 +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 @@ -442,6 +500,27 @@ body: | BX_RET 14, _, implicit %r0 ... --- +name: test_trunc_s32_16 +# CHECK-LABEL: name: test_trunc_s32_16 +legalized: true +regBankSelected: false +selected: false +# CHECK: registers: +# CHECK: - { id: 0, class: gprb } +# CHECK: - { id: 1, class: gprb } +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } +body: | + bb.0: + liveins: %r0 + + %0(s32) = COPY %r0 + %1(s16) = G_TRUNC %0(s32) + %r0 = COPY %1(s16) + BX_RET 14, _, implicit %r0 +... +--- name: test_fadd_s32 # CHECK-LABEL: name: test_fadd_s32 legalized: true diff --git a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll new file mode 100644 index 000000000000..e3680ed2b929 --- /dev/null +++ b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll @@ -0,0 +1,80 @@ +; RUN: llc -mtriple arm-unknown -verify-machineinstrs -global-isel -global-isel-abort=2 -pass-remarks-missed='gisel*' %s -o - 2>&1 | FileCheck %s + +; This file checks that we use the fallback path for things that are known to +; be unsupported on the ARM target. It should progressively shrink in size. + +define <4 x i32> @test_int_vectors(<4 x i32> %a, <4 x i32> %b) { +; CHECK: remark: {{.*}} unable to lower arguments: <4 x i32> (<4 x i32>, <4 x i32>)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_int_vectors + %res = add <4 x i32> %a, %b + ret <4 x i32> %res +} + +define <4 x float> @test_float_vectors(<4 x float> %a, <4 x float> %b) { +; CHECK: remark: {{.*}} unable to lower arguments: <4 x float> (<4 x float>, <4 x float>)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_float_vectors + %res = fadd <4 x float> %a, %b + ret <4 x float> %res +} + +define i64 @test_i64(i64 %a, i64 %b) { +; CHECK: remark: {{.*}} unable to lower arguments: i64 (i64, i64)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_i64 + %res = add i64 %a, %b + ret i64 %res +} + +define i128 @test_i128(i128 %a, i128 %b) { +; CHECK: remark: {{.*}} unable to lower arguments: i128 (i128, i128)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_i128 + %res = add i128 %a, %b + ret i128 %res +} + +define i17 @test_funny_ints(i17 %a, i17 %b) { +; CHECK: remark: {{.*}} unable to lower arguments: i17 (i17, i17)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_funny_ints + %res = add i17 %a, %b + ret i17 %res +} + +define half @test_half(half %a, half %b) { +; CHECK: remark: {{.*}} unable to lower arguments: half (half, half)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_half + %res = fadd half %a, %b + ret half %res +} + +; On ARM, clang lowers structs to arrays. +define void @test_arrays([2 x i32] %this.could.come.from.a.struct) { +; CHECK: remark: {{.*}} unable to lower arguments: void ([2 x i32])* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_arrays + ret void +} + +define void @test_structs({i32, i32} %struct) { +; CHECK: remark: {{.*}} unable to lower arguments: void ({ i32, i32 })* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_structs + ret void +} + +define void @test_vararg_definition(i32 %a, ...) { +; CHECK: remark: {{.*}} unable to lower arguments: void (i32, ...)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_vararg_definition + ret void +} + +define void @test_vararg_call(i32 %a) { +; CHECK: remark: {{.*}} unable to translate instruction: call +; CHECK-LABEL: warning: Instruction selection used fallback path for test_vararg_call + call void(i32, ...) @test_vararg_definition(i32 %a, i32 %a, i32 %a) + ret void +} + +define i32 @test_thumb(i32 %a) #0 { +; CHECK: remark: {{.*}} unable to lower arguments: i32 (i32)* +; CHECK-LABEL: warning: Instruction selection used fallback path for test_thumb + ret i32 %a +} + +attributes #0 = { "target-features"="+thumb-mode" } diff --git a/test/CodeGen/ARM/bool-ext-inc.ll b/test/CodeGen/ARM/bool-ext-inc.ll index fe43f1b2ef93..b91b9b258991 100644 --- a/test/CodeGen/ARM/bool-ext-inc.ll +++ b/test/CodeGen/ARM/bool-ext-inc.ll @@ -30,3 +30,42 @@ define <4 x i32> @sext_inc_vec(<4 x i1> %x) { ret <4 x i32> %add } +define <4 x i32> @cmpgt_sext_inc_vec(<4 x i32> %x, <4 x i32> %y) { +; CHECK-LABEL: cmpgt_sext_inc_vec: +; CHECK: @ BB#0: +; CHECK-NEXT: mov r12, sp +; CHECK-NEXT: vmov d19, r2, r3 +; CHECK-NEXT: vmov.i32 q10, #0x1 +; CHECK-NEXT: vld1.64 {d16, d17}, [r12] +; CHECK-NEXT: vmov d18, r0, r1 +; CHECK-NEXT: vcgt.s32 q8, q9, q8 +; CHECK-NEXT: vadd.i32 q8, q8, q10 +; CHECK-NEXT: vmov r0, r1, d16 +; CHECK-NEXT: vmov r2, r3, d17 +; CHECK-NEXT: mov pc, lr + %cmp = icmp sgt <4 x i32> %x, %y + %ext = sext <4 x i1> %cmp to <4 x i32> + %add = add <4 x i32> %ext, <i32 1, i32 1, i32 1, i32 1> + ret <4 x i32> %add +} + +define <4 x i32> @cmpne_sext_inc_vec(<4 x i32> %x, <4 x i32> %y) { +; CHECK-LABEL: cmpne_sext_inc_vec: +; CHECK: @ BB#0: +; CHECK-NEXT: mov r12, sp +; CHECK-NEXT: vmov d19, r2, r3 +; CHECK-NEXT: vld1.64 {d16, d17}, [r12] +; CHECK-NEXT: vmov d18, r0, r1 +; CHECK-NEXT: vceq.i32 q8, q9, q8 +; CHECK-NEXT: vmov.i32 q9, #0x1 +; CHECK-NEXT: vmvn q8, q8 +; CHECK-NEXT: vadd.i32 q8, q8, q9 +; CHECK-NEXT: vmov r0, r1, d16 +; CHECK-NEXT: vmov r2, r3, d17 +; CHECK-NEXT: mov pc, lr + %cmp = icmp ne <4 x i32> %x, %y + %ext = sext <4 x i1> %cmp to <4 x i32> + %add = add <4 x i32> %ext, <i32 1, i32 1, i32 1, i32 1> + ret <4 x i32> %add +} + diff --git a/test/CodeGen/ARM/fence-singlethread.ll b/test/CodeGen/ARM/fence-singlethread.ll new file mode 100644 index 000000000000..ec032ccac423 --- /dev/null +++ b/test/CodeGen/ARM/fence-singlethread.ll @@ -0,0 +1,16 @@ +; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s +; RUN: llc -mtriple=thumbv7-apple-ios %s -o - | FileCheck %s +; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -filetype=obj -o %t +; RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=OBJ + +; OBJ-NOT: dmb + +define void @fence_singlethread() { +; CHECK-LABEL: fence_singlethread: +; CHECK-NOT: dmb +; CHECK: @ COMPILER BARRIER +; CHECK-NOT: dmb + + fence singlethread seq_cst + ret void +} diff --git a/test/CodeGen/ARM/v6m-smul-with-overflow.ll b/test/CodeGen/ARM/v6m-smul-with-overflow.ll new file mode 100644 index 000000000000..6e8a7041de2b --- /dev/null +++ b/test/CodeGen/ARM/v6m-smul-with-overflow.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -mtriple=thumbv6m-none-eabi | FileCheck %s + +define i1 @signed_multiplication_did_overflow(i32, i32) { +; CHECK-LABEL: signed_multiplication_did_overflow: +entry-block: + %2 = tail call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %0, i32 %1) + %3 = extractvalue { i32, i1 } %2, 1 + ret i1 %3 + +; CHECK: mov r2, r1 +; CHECK: asrs r1, r0, #31 +; CHECK: asrs r3, r2, #31 +; CHECK: bl __aeabi_lmul +} + +declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) diff --git a/test/CodeGen/ARM/vpadd.ll b/test/CodeGen/ARM/vpadd.ll index 1aa23597cf49..3409d37a31f4 100644 --- a/test/CodeGen/ARM/vpadd.ll +++ b/test/CodeGen/ARM/vpadd.ll @@ -485,6 +485,26 @@ define <2 x i16> @fromExtendingExtractVectorElt_i16(<4 x i16> %in) { ret <2 x i16> %x } +; And <2 x i8> to <2 x i32> +define <2 x i8> @fromExtendingExtractVectorElt_2i8(<8 x i8> %in) { +; CHECK-LABEL: fromExtendingExtractVectorElt_2i8: +; CHECK: vadd.i32 + %tmp1 = shufflevector <8 x i8> %in, <8 x i8> undef, <2 x i32> <i32 0, i32 2> + %tmp2 = shufflevector <8 x i8> %in, <8 x i8> undef, <2 x i32> <i32 1, i32 3> + %x = add <2 x i8> %tmp2, %tmp1 + ret <2 x i8> %x +} + +define <2 x i16> @fromExtendingExtractVectorElt_2i16(<8 x i16> %in) { +; CHECK-LABEL: fromExtendingExtractVectorElt_2i16: +; CHECK: vadd.i32 + %tmp1 = shufflevector <8 x i16> %in, <8 x i16> undef, <2 x i32> <i32 0, i32 2> + %tmp2 = shufflevector <8 x i16> %in, <8 x i16> undef, <2 x i32> <i32 1, i32 3> + %x = add <2 x i16> %tmp2, %tmp1 + ret <2 x i16> %x +} + + declare <4 x i16> @llvm.arm.neon.vpaddls.v4i16.v8i8(<8 x i8>) nounwind readnone declare <2 x i32> @llvm.arm.neon.vpaddls.v2i32.v4i16(<4 x i16>) nounwind readnone declare <1 x i64> @llvm.arm.neon.vpaddls.v1i64.v2i32(<2 x i32>) nounwind readnone |