blob: c9cd7d6ab9601906dbdc5dffb740f9a29c715787 [file] [log] [blame]
Tim Northover397f9d92016-11-16 20:54:28 +00001; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s
Weiming Zhao665784f2018-01-24 18:00:57 +00002; RUN: llc -mtriple=armv6m-eabi %s -o - | FileCheck %s --check-prefix=EXPAND
Tim Northover397f9d92016-11-16 20:54:28 +00003
4define i64 @test_shl(i64 %val, i64 %amt) {
5; CHECK-LABEL: test_shl:
Weiming Zhao665784f2018-01-24 18:00:57 +00006; EXPAND-LABEL: test_shl:
Tim Northover397f9d92016-11-16 20:54:28 +00007 ; First calculate the hi part when the shift amount is small enough that it
8 ; contains components from both halves. It'll be returned in r1 so that's a
9 ; reasonable place for it to end up.
10; CHECK: rsb [[REVERSE_SHIFT:.*]], r2, #32
11; CHECK: lsr [[TMP:.*]], r0, [[REVERSE_SHIFT]]
12; CHECK: orr r1, [[TMP]], r1, lsl r2
13
14 ; Check whether the shift was in fact small (< 32 bits).
15; CHECK: sub [[EXTRA_SHIFT:.*]], r2, #32
16; CHECK: cmp [[EXTRA_SHIFT]], #0
17
18 ; If not, the high part of the answer is just the low part shifted by the
19 ; excess.
20; CHECK: lslge r1, r0, [[EXTRA_SHIFT]]
21
22 ; The low part is either a direct shift (1st inst) or 0. We can reuse the same
23 ; NZCV.
24; CHECK: lsl r0, r0, r2
25; CHECK: movge r0, #0
26
Weiming Zhao665784f2018-01-24 18:00:57 +000027; EXPAND: push {[[REG:r[0-9]+]], lr}
28; EXPAND-NEXT: bl __aeabi_llsl
29; EXPAND-NEXT: pop {[[REG]], pc}
Tim Northover397f9d92016-11-16 20:54:28 +000030 %res = shl i64 %val, %amt
31 ret i64 %res
32}
33
34; Explanation for lshr is pretty much the reverse of shl.
35define i64 @test_lshr(i64 %val, i64 %amt) {
36; CHECK-LABEL: test_lshr:
Weiming Zhao665784f2018-01-24 18:00:57 +000037; EXPAND-LABEL: test_lshr:
Tim Northover397f9d92016-11-16 20:54:28 +000038; CHECK: rsb [[REVERSE_SHIFT:.*]], r2, #32
Kristof Beylseecb3532017-06-28 07:07:03 +000039; CHECK: lsr r0, r0, r2
Tim Northover397f9d92016-11-16 20:54:28 +000040; CHECK: orr r0, r0, r1, lsl [[REVERSE_SHIFT]]
41; CHECK: sub [[EXTRA_SHIFT:.*]], r2, #32
42; CHECK: cmp [[EXTRA_SHIFT]], #0
43; CHECK: lsrge r0, r1, [[EXTRA_SHIFT]]
44; CHECK: lsr r1, r1, r2
45; CHECK: movge r1, #0
Weiming Zhao665784f2018-01-24 18:00:57 +000046
47; EXPAND: push {[[REG:r[0-9]+]], lr}
48; EXPAND-NEXT: bl __aeabi_llsr
49; EXPAND-NEXT: pop {[[REG]], pc}
Tim Northover397f9d92016-11-16 20:54:28 +000050 %res = lshr i64 %val, %amt
51 ret i64 %res
52}
53
54; One minor difference for ashr: the high bits must be "hi >> 31" if the shift
55; amount is large to get the right sign bit.
56define i64 @test_ashr(i64 %val, i64 %amt) {
57; CHECK-LABEL: test_ashr:
Weiming Zhao665784f2018-01-24 18:00:57 +000058; EXPAND-LABEL: test_ashr:
Tim Northover397f9d92016-11-16 20:54:28 +000059; CHECK: sub [[EXTRA_SHIFT:.*]], r2, #32
60; CHECK: asr [[HI_TMP:.*]], r1, r2
61; CHECK: lsr r0, r0, r2
62; CHECK: rsb [[REVERSE_SHIFT:.*]], r2, #32
63; CHECK: cmp [[EXTRA_SHIFT]], #0
64; CHECK: orr r0, r0, r1, lsl [[REVERSE_SHIFT]]
65; CHECK: asrge [[HI_TMP]], r1, #31
66; CHECK: asrge r0, r1, [[EXTRA_SHIFT]]
67; CHECK: mov r1, [[HI_TMP]]
Weiming Zhao665784f2018-01-24 18:00:57 +000068
69; EXPAND: push {[[REG:r[0-9]+]], lr}
70; EXPAND-NEXT: bl __aeabi_lasr
71; EXPAND-NEXT: pop {[[REG]], pc}
Tim Northover397f9d92016-11-16 20:54:28 +000072 %res = ashr i64 %val, %amt
73 ret i64 %res
74}