• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -mtriple=arm-eabi %s -o - | FileCheck %s
2; RUN: llc -mtriple=armv6m-eabi %s -o - | FileCheck %s --check-prefix=EXPAND
3
4define i64 @test_shl(i64 %val, i64 %amt) {
5; CHECK-LABEL: test_shl:
6; EXPAND-LABEL: test_shl:
7  ; 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
27; EXPAND:      push {[[REG:r[0-9]+]], lr}
28; EXPAND-NEXT: bl __aeabi_llsl
29; EXPAND-NEXT: pop {[[REG]], pc}
30  %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:
37; EXPAND-LABEL: test_lshr:
38; CHECK: rsb [[REVERSE_SHIFT:.*]], r2, #32
39; CHECK: lsr r0, r0, r2
40; 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
46
47; EXPAND:      push {[[REG:r[0-9]+]], lr}
48; EXPAND-NEXT: bl __aeabi_llsr
49; EXPAND-NEXT: pop {[[REG]], pc}
50  %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:
58; EXPAND-LABEL: test_ashr:
59; 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]]
68
69; EXPAND:      push {[[REG:r[0-9]+]], lr}
70; EXPAND-NEXT: bl __aeabi_lasr
71; EXPAND-NEXT: pop {[[REG]], pc}
72  %res = ashr i64 %val, %amt
73  ret i64 %res
74}
75