xref: /llvm-project/llvm/test/CodeGen/ARM/execute-only-split-offset.ll (revision f83ab2b3beb0303e0775ea187d9575faa4a048eb)
1*f83ab2b3SJohn Brawn; RUN: llc -mtriple=thumbv8m.base-eabi -mattr=+execute-only %s -o - | FileCheck --check-prefixes=CHECK,CHECK-MOVW %s
2*f83ab2b3SJohn Brawn; RUN: llc -mtriple=thumbv6m-eabi -mattr=+execute-only %s -o - | FileCheck --check-prefixes=CHECK,CHECK-NOMOVW %s
3*f83ab2b3SJohn Brawn
4*f83ab2b3SJohn Brawn; Largest offset that fits into sp-relative ldr
5*f83ab2b3SJohn Brawn; CHECK-LABEL: ldr_range_end:
6*f83ab2b3SJohn Brawn; CHECK: ldr {{r[0-9]+}}, [sp, #1020]
7*f83ab2b3SJohn Brawndefine i32 @ldr_range_end() {
8*f83ab2b3SJohn Brawnentry:
9*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
10*f83ab2b3SJohn Brawn  %arr = alloca [1020 x i8], align 4
11*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
12*f83ab2b3SJohn Brawn  ret i32 %0
13*f83ab2b3SJohn Brawn}
14*f83ab2b3SJohn Brawn
15*f83ab2b3SJohn Brawn; Smallest offset that fits into add+ldr
16*f83ab2b3SJohn Brawn; CHECK-LABEL: add_ldr_range_start:
17*f83ab2b3SJohn Brawn; CHECK:      add [[REG:r[0-9]+]], sp, #900
18*f83ab2b3SJohn Brawn; CHECK-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]
19*f83ab2b3SJohn Brawndefine i32 @add_ldr_range_start() {
20*f83ab2b3SJohn Brawnentry:
21*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
22*f83ab2b3SJohn Brawn  %arr = alloca [1024 x i8], align 4
23*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
24*f83ab2b3SJohn Brawn  ret i32 %0
25*f83ab2b3SJohn Brawn}
26*f83ab2b3SJohn Brawn
27*f83ab2b3SJohn Brawn; Largest offset that fits into add+ldr
28*f83ab2b3SJohn Brawn; CHECK-LABEL: add_ldr_range_end:
29*f83ab2b3SJohn Brawn; CHECK:      add [[REG:r[0-9]+]], sp, #1020
30*f83ab2b3SJohn Brawn; CHECK-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]
31*f83ab2b3SJohn Brawndefine i32 @add_ldr_range_end() {
32*f83ab2b3SJohn Brawnentry:
33*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
34*f83ab2b3SJohn Brawn  %arr = alloca [1144 x i8], align 4
35*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
36*f83ab2b3SJohn Brawn  ret i32 %0
37*f83ab2b3SJohn Brawn}
38*f83ab2b3SJohn Brawn
39*f83ab2b3SJohn Brawn; Smallest offset where we start using mov32. If we don't have movw then using
40*f83ab2b3SJohn Brawn; an ldr offset means we save an add.
41*f83ab2b3SJohn Brawn; CHECK-LABEL: mov32_range_start:
42*f83ab2b3SJohn Brawn; CHECK-MOVW:        movw [[REG:r[0-9]+]], #1148
43*f83ab2b3SJohn Brawn; CHECK-NOMOVW:      movs [[REG:r[0-9]+]], #4
44*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: lsls [[REG]], [[REG]], #8
45*f83ab2b3SJohn Brawn; CHECK-NEXT:        add [[REG]], sp
46*f83ab2b3SJohn Brawn; CHECK-MOVW-NEXT:   ldr {{r[0-9]+}}, [[[REG]]]
47*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]
48*f83ab2b3SJohn Brawndefine i32 @mov32_range_start() {
49*f83ab2b3SJohn Brawnentry:
50*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
51*f83ab2b3SJohn Brawn  %arr = alloca [1148 x i8], align 4
52*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
53*f83ab2b3SJohn Brawn  ret i32 %0
54*f83ab2b3SJohn Brawn}
55*f83ab2b3SJohn Brawn
56*f83ab2b3SJohn Brawn; Here using an ldr offset doesn't save an add so we shouldn't do it.
57*f83ab2b3SJohn Brawn; CHECK-LABEL: mov32_range_next:
58*f83ab2b3SJohn Brawn; CHECK-MOVW:        movw [[REG:r[0-9]+]], #1152
59*f83ab2b3SJohn Brawn; CHECK-NOMOVW:      movs [[REG:r[0-9]+]], #4
60*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: lsls [[REG]], [[REG]], #8
61*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: adds [[REG]], #128
62*f83ab2b3SJohn Brawn; CHECK-NEXT:        add [[REG]], sp
63*f83ab2b3SJohn Brawn; CHECK-NEXT:        ldr {{r[0-9]+}}, [[[REG]]]
64*f83ab2b3SJohn Brawndefine i32 @mov32_range_next() {
65*f83ab2b3SJohn Brawnentry:
66*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
67*f83ab2b3SJohn Brawn  %arr = alloca [1152 x i8], align 4
68*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
69*f83ab2b3SJohn Brawn  ret i32 %0
70*f83ab2b3SJohn Brawn}
71*f83ab2b3SJohn Brawn
72*f83ab2b3SJohn Brawn; Smallest offset where using an ldr offset prevents needing a movt or lsl+add
73*f83ab2b3SJohn Brawn; CHECK-LABEL: can_clear_top_byte_start:
74*f83ab2b3SJohn Brawn; CHECK:             add sp, {{r[0-9]+}}
75*f83ab2b3SJohn Brawn; CHECK-MOVW:        movw [[REG:r[0-9]+]], #65412
76*f83ab2b3SJohn Brawn; CHECK-NOMOVW:      movs [[REG:r[0-9]+]], #255
77*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: lsls [[REG:r[0-9]+]], [[REG:r[0-9]+]], #8
78*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: adds [[REG:r[0-9]+]], #132
79*f83ab2b3SJohn Brawn; CHECK-NEXT:        add [[REG]], sp
80*f83ab2b3SJohn Brawn; CHECK-NEXT:        ldr {{r[0-9]+}}, [[[REG]], #124]
81*f83ab2b3SJohn Brawndefine i32 @can_clear_top_byte_start() {
82*f83ab2b3SJohn Brawnentry:
83*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
84*f83ab2b3SJohn Brawn  %arr = alloca [65536 x i8], align 4
85*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
86*f83ab2b3SJohn Brawn  ret i32 %0
87*f83ab2b3SJohn Brawn}
88*f83ab2b3SJohn Brawn
89*f83ab2b3SJohn Brawn; Largest offset where using an ldr offset prevents needing a movt or lsl+add
90*f83ab2b3SJohn Brawn; CHECK-LABEL: can_clear_top_byte_end:
91*f83ab2b3SJohn Brawn; CHECK:             add sp, {{r[0-9]+}}
92*f83ab2b3SJohn Brawn; CHECK-MOVW:        movw [[REG:r[0-9]+]], #65532
93*f83ab2b3SJohn Brawn; CHECK-NOMOVW:      movs [[REG:r[0-9]+]], #255
94*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: lsls [[REG:r[0-9]+]], [[REG:r[0-9]+]], #8
95*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: adds [[REG:r[0-9]+]], #252
96*f83ab2b3SJohn Brawn; CHECK-NEXT:        add [[REG]], sp
97*f83ab2b3SJohn Brawn; CHECK-NEXT:        ldr {{r[0-9]+}}, [[[REG]], #124]
98*f83ab2b3SJohn Brawndefine i32 @can_clear_top_byte_end() {
99*f83ab2b3SJohn Brawnentry:
100*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
101*f83ab2b3SJohn Brawn  %arr = alloca [65656 x i8], align 4
102*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
103*f83ab2b3SJohn Brawn  ret i32 %0
104*f83ab2b3SJohn Brawn}
105*f83ab2b3SJohn Brawn
106*f83ab2b3SJohn Brawn; Smallest offset where using an ldr offset doesn't clear the top byte, though
107*f83ab2b3SJohn Brawn; we can use an ldr offset if not using movt to save an add of the low byte.
108*f83ab2b3SJohn Brawn; CHECK-LABEL: cant_clear_top_byte_start:
109*f83ab2b3SJohn Brawn; CHECK:             add sp, {{r[0-9]+}}
110*f83ab2b3SJohn Brawn; CHECK-MOVW:        movw [[REG:r[0-9]+]], #124
111*f83ab2b3SJohn Brawn; CHECK-MOVW-NEXT:   movt [[REG:r[0-9]+]], #1
112*f83ab2b3SJohn Brawn; CHECK-NOMOVW:      movs [[REG:r[0-9]+]], #1
113*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: lsls [[REG:r[0-9]+]], [[REG:r[0-9]+]], #16
114*f83ab2b3SJohn Brawn; CHECK-NEXT:        add [[REG]], sp
115*f83ab2b3SJohn Brawn; CHECK-MOVW-NEXT:   ldr {{r[0-9]+}}, [[[REG]]]
116*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]
117*f83ab2b3SJohn Brawndefine i32 @cant_clear_top_byte_start() {
118*f83ab2b3SJohn Brawnentry:
119*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
120*f83ab2b3SJohn Brawn  %arr = alloca [65660 x i8], align 4
121*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
122*f83ab2b3SJohn Brawn  ret i32 %0
123*f83ab2b3SJohn Brawn}
124*f83ab2b3SJohn Brawn
125*f83ab2b3SJohn Brawn; An ldr offset doesn't help for anything, so we shouldn't do it.
126*f83ab2b3SJohn Brawn; CHECK-LABEL: cant_clear_top_byte_next:
127*f83ab2b3SJohn Brawn; CHECK:             add sp, {{r[0-9]+}}
128*f83ab2b3SJohn Brawn; CHECK-MOVW:        movw [[REG:r[0-9]+]], #128
129*f83ab2b3SJohn Brawn; CHECK-MOVW:        movt [[REG:r[0-9]+]], #1
130*f83ab2b3SJohn Brawn; CHECK-NOMOVW:      movs [[REG:r[0-9]+]], #1
131*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: lsls [[REG:r[0-9]+]], [[REG:r[0-9]+]], #16
132*f83ab2b3SJohn Brawn; CHECK-NOMOVW-NEXT: adds [[REG:r[0-9]+]], #128
133*f83ab2b3SJohn Brawn; CHECK-NEXT:        add [[REG]], sp
134*f83ab2b3SJohn Brawn; CHECK-NEXT:        ldr {{r[0-9]+}}, [[[REG]]]
135*f83ab2b3SJohn Brawndefine i32 @cant_clear_top_byte_next() {
136*f83ab2b3SJohn Brawnentry:
137*f83ab2b3SJohn Brawn  %var = alloca i32, align 4
138*f83ab2b3SJohn Brawn  %arr = alloca [65664 x i8], align 4
139*f83ab2b3SJohn Brawn  %0 = load i32, ptr %var, align 4
140*f83ab2b3SJohn Brawn  ret i32 %0
141*f83ab2b3SJohn Brawn}
142