1# RUN: llc -o /dev/null %s -mtriple=aarch64-apple-ios -run-pass=aarch64-collect-loh -debug-only=aarch64-collect-loh 2>&1 | FileCheck %s
2# REQUIRES: asserts
3--- |
4  define void @func0() { ret void }
5
6  declare void @extfunc()
7
8  @g0 = external global i32
9  @g1 = external global i32
10  @g2 = external global i32
11  @g3 = external global i32
12  @g4 = external global i32
13  @g5 = external global i32
14...
15---
16# Check various LOH variants. Remember that the algorithms walks the basic
17# blocks backwards.
18# CHECK-LABEL: ********** AArch64 Collect LOH **********
19# CHECK-LABEL: Looking in function func0
20name: func0
21body: |
22  bb.0:
23    ; CHECK: Adding MCLOH_AdrpAdrp:
24    ; CHECK-NEXT: %X1<def> = ADRP <ga:@g3>
25    ; CHECK-NEXT: %X1<def> = ADRP <ga:@g4>
26    ; CHECK-NEXT: Adding MCLOH_AdrpAdrp:
27    ; CHECK-NEXT: %X1<def> = ADRP <ga:@g2>
28    ; CHECK-NEXT: %X1<def> = ADRP <ga:@g3>
29    ; CHECK-NEXT: Adding MCLOH_AdrpAdrp:
30    ; CHECK-NEXT: %X0<def> = ADRP <ga:@g0>
31    ; CHECK-NEXT: %X0<def> = ADRP <ga:@g1>
32    %x0 = ADRP target-flags(aarch64-page) @g0
33    %x0 = ADRP target-flags(aarch64-page) @g1
34    %x1 = ADRP target-flags(aarch64-page) @g2
35    %x1 = ADRP target-flags(aarch64-page) @g3
36    %x1 = ADRP target-flags(aarch64-page) @g4
37
38  bb.1:
39    ; CHECK-NEXT: Adding MCLOH_AdrpAdd:
40    ; CHECK-NEXT: %X20<def> = ADRP <ga:@g0>
41    ; CHECK-NEXT: %X3<def> = ADDXri %X20, <ga:@g0>
42    ; CHECK-NEXT: Adding MCLOH_AdrpAdd:
43    ; CHECK-NEXT: %X1<def> = ADRP <ga:@g0>
44    ; CHECK-NEXT: %X1<def> = ADDXri %X1, <ga:@g0>
45    %x1 = ADRP target-flags(aarch64-page) @g0
46    %x9 = SUBXri %x11, 5, 0 ; should not affect MCLOH formation
47    %x1 = ADDXri %x1, target-flags(aarch64-pageoff) @g0, 0
48    %x20 = ADRP target-flags(aarch64-page) @g0
49    BL @extfunc, csr_aarch64_aapcs ; should not clobber X20
50    %x3 = ADDXri %x20, target-flags(aarch64-pageoff) @g0, 0
51
52  bb.2:
53    ; CHECK-NOT: MCLOH_AdrpAdd
54    %x9 = ADRP target-flags(aarch64-page) @g0
55    BL @extfunc, csr_aarch64_aapcs ; clobbers x9
56    %x9 = ADDXri %x9, target-flags(aarch64-pageoff) @g0, 0
57
58  bb.3:
59    ; CHECK-NOT: MCLOH_AdrpAdd
60    %x10 = ADRP target-flags(aarch64-page) @g0
61    HINT 0, implicit def dead %x10 ; clobbers x10
62    %x10 = ADDXri %x10, target-flags(aarch64-pageoff) @g0, 0
63
64  bb.4:
65    ; Cannot produce a LOH for multiple users
66    ; CHECK-NOT: MCLOH_AdrpAdd
67    %x10 = ADRP target-flags(aarch64-page) @g0
68    HINT 0, implicit def dead %x10 ; clobbers x10
69    %x11 = ADDXri %x10, target-flags(aarch64-pageoff) @g0, 0
70    %x12 = ADDXri %x10, target-flags(aarch64-pageoff) @g0, 0
71
72  bb.5:
73    ; CHECK-NEXT: Adding MCLOH_AdrpLdr:
74    ; CHECK-NEXT: %X5<def> = ADRP <ga:@g2>
75    ; CHECK-NEXT: %S6<def> = LDRSui %X5, <ga:@g2>
76    ; CHECK-NEXT: Adding MCLOH_AdrpLdr:
77    ; CHECK-NEXT: %X4<def> = ADRP <ga:@g2>
78    ; CHECK-NEXT: %X4<def> = LDRXui %X4, <ga:@g2>
79    %x4 = ADRP target-flags(aarch64-page) @g2
80    %x4 = LDRXui %x4, target-flags(aarch64-pageoff) @g2
81    %x5 = ADRP target-flags(aarch64-page) @g2
82    %s6 = LDRSui %x5, target-flags(aarch64-pageoff) @g2
83
84  bb.6:
85    ; CHECK-NEXT: Adding MCLOH_AdrpLdrGot:
86    ; CHECK-NEXT: %X5<def> = ADRP <ga:@g2>
87    ; CHECK-NEXT: %X6<def> = LDRXui %X5, <ga:@g2>
88    ; CHECK-NEXT: Adding MCLOH_AdrpLdrGot:
89    ; CHECK-NEXT: %X4<def> = ADRP <ga:@g2>
90    ; CHECK-NEXT: %X4<def> = LDRXui %X4, <ga:@g2>
91    %x4 = ADRP target-flags(aarch64-page, aarch64-got) @g2
92    %x4 = LDRXui %x4, target-flags(aarch64-pageoff, aarch64-got) @g2
93    %x5 = ADRP target-flags(aarch64-page, aarch64-got) @g2
94    %x6 = LDRXui %x5, target-flags(aarch64-pageoff, aarch64-got) @g2
95
96  bb.7:
97    ; CHECK-NOT: Adding MCLOH_AdrpLdrGot:
98    ; This sequence makes no sense and should not produce a LdrGot
99    %x11 = ADRP target-flags(aarch64-page, aarch64-got) @g5
100    %s11 = LDRSui %x4, target-flags(aarch64-pageoff, aarch64-got) @g5
101
102  bb.8:
103    ; CHECK-NEXT: Adding MCLOH_AdrpAddLdr:
104    ; CHECK-NEXT: %X7<def> = ADRP <ga:@g3>[TF=1]
105    ; CHECK-NEXT: %X8<def> = ADDXri %X7, <ga:@g3>
106    ; CHECK-NEXT: %D1<def> = LDRDui %X8, 8
107    %x7 = ADRP target-flags(aarch64-page) @g3
108    %x8 = ADDXri %x7, target-flags(aarch64-pageoff) @g3, 0
109    %d1 = LDRDui %x8, 8
110
111  bb.9:
112    ; CHECK-NEXT: Adding MCLOH_AdrpAdd:
113    ; CHECK-NEXT: %X3<def> = ADRP <ga:@g3>
114    ; CHECK-NEXT: %X3<def> = ADDXri %X3, <ga:@g3>
115    ; CHECK-NEXT: Adding MCLOH_AdrpAdd:
116    ; CHECK-NEXT: %X5<def> = ADRP <ga:@g3>
117    ; CHECK-NEXT: %X2<def> = ADDXri %X5, <ga:@g3>
118    ; CHECK-NEXT: Adding MCLOH_AdrpAddStr:
119    ; CHECK-NEXT: %X1<def> = ADRP <ga:@g3>
120    ; CHECK-NEXT: %X1<def> = ADDXri %X1, <ga:@g3>
121    ; CHECK-NEXT: STRXui %X2, %X1, 16
122    %x1 = ADRP target-flags(aarch64-page) @g3
123    %x1 = ADDXri %x1, target-flags(aarch64-pageoff) @g3, 0
124    STRXui %x2, %x1, 16
125
126    ; This sequence should just produce an AdrpAdd (not AdrpAddStr)
127    %x5 = ADRP target-flags(aarch64-page) @g3
128    %x2 = ADDXri %x5, target-flags(aarch64-pageoff) @g3, 0
129    STRXui %x2, %x11, 16
130
131    ; This sequence should just produce an AdrpAdd (not AdrpAddStr)
132    %x3 = ADRP target-flags(aarch64-page) @g3
133    %x3 = ADDXri %x3, target-flags(aarch64-pageoff) @g3, 0
134    STRXui %x3, %x3, 16
135
136  bb.10:
137    ; CHECK-NEXT: Adding MCLOH_AdrpLdr:
138    ; CHECK-NEXT: %X2<def> = ADRP <ga:@g3>
139    ; CHECK-NEXT: %X2<def> = LDRXui %X2, <ga:@g3>
140    ; CHECK-NEXT: Adding MCLOH_AdrpLdrGotLdr:
141    ; CHECK-NEXT: %X1<def> = ADRP <ga:@g4>
142    ; CHECK-NEXT: %X1<def> = LDRXui %X1, <ga:@g4>
143    ; CHECK-NEXT: %X1<def> = LDRXui %X1, 24
144    %x1 = ADRP target-flags(aarch64-page, aarch64-got) @g4
145    %x1 = LDRXui %x1, target-flags(aarch64-pageoff, aarch64-got) @g4
146    %x1 = LDRXui %x1, 24
147    ; Should just produce a MCLOH_AdrpLdr (not MCLOH_AdrpLdrGotLdr)
148    %x2 = ADRP target-flags(aarch64-page) @g3
149    %x2 = LDRXui %x2, target-flags(aarch64-pageoff) @g3
150    %x2 = LDRXui %x2, 24
151
152  bb.11:
153    ; CHECK-NEXT: Adding MCLOH_AdrpLdr
154    ; CHECK-NEXT: %X5<def> = ADRP <ga:@g1>
155    ; CHECK-NEXT: %X5<def> = LDRXui %X5, <ga:@g1>
156    ; CHECK-NEXT: Adding MCLOH_AdrpLdrGotStr:
157    ; CHECK-NEXT: %X1<def> = ADRP <ga:@g4>
158    ; CHECK-NEXT: %X1<def> = LDRXui %X1, <ga:@g4>
159    ; CHECK-NEXT: STRXui %X4, %X1, 32
160    %x1 = ADRP target-flags(aarch64-page, aarch64-got) @g4
161    %x1 = LDRXui %x1, target-flags(aarch64-pageoff, aarch64-got) @g4
162    STRXui %x4, %x1, 32
163    ; Should just produce a MCLOH_AdrpLdr (not MCLOH_AdrpLdrGotStr)
164    %x5 = ADRP target-flags(aarch64-page) @g1
165    %x5 = LDRXui %x5, target-flags(aarch64-pageoff) @g1
166    STRXui %x11, %x5, 32
167
168  bb.12:
169    successors: %bb.13
170    ; Cannot produce a LOH for multiple users
171    ; CHECK-NOT: MCLOH_AdrpAdd
172    %x10 = ADRP target-flags(aarch64-page) @g0
173    HINT 0, implicit def dead %x10 ; clobbers x10
174    %x11 = ADDXri %x10, target-flags(aarch64-pageoff) @g0, 0
175    B %bb.13
176
177  bb.13:
178    liveins: %x10
179    %x12 = ADDXri %x10, target-flags(aarch64-pageoff) @g0, 0
180...
181