Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -mtriple=arm64-apple-ios -O2 -aarch64-collect-loh -aarch64-collect-loh-bb-only=false < %s -o - | FileCheck %s
      2 ; RUN: llc -mtriple=arm64-linux-gnu -O2 -aarch64-collect-loh -aarch64-collect-loh-bb-only=false < %s -o - | FileCheck %s --check-prefix=CHECK-ELF
      3 
      4 ; CHECK-ELF-NOT: .loh
      5 ; CHECK-ELF-NOT: AdrpAdrp
      6 ; CHECK-ELF-NOT: AdrpAdd
      7 ; CHECK-ELF-NOT: AdrpLdrGot
      8 
      9 @a = internal unnamed_addr global i32 0, align 4
     10 @b = external global i32
     11 
     12 ; Function Attrs: noinline nounwind ssp
     13 define void @foo(i32 %t) {
     14 entry:
     15   %tmp = load i32, i32* @a, align 4
     16   %add = add nsw i32 %tmp, %t
     17   store i32 %add, i32* @a, align 4
     18   ret void
     19 }
     20 
     21 ; Function Attrs: nounwind ssp
     22 ; Testcase for <rdar://problem/15438605>, AdrpAdrp reuse is valid only when the first adrp
     23 ; dominates the second.
     24 ; The first adrp comes from the loading of 'a' and the second the loading of 'b'.
     25 ; 'a' is loaded in if.then, 'b' in if.end4, if.then does not dominates if.end4.
     26 ; CHECK-LABEL: _test
     27 ; CHECK: ret
     28 ; CHECK-NOT: .loh AdrpAdrp
     29 define i32 @test(i32 %t) {
     30 entry:
     31   %cmp = icmp sgt i32 %t, 5
     32   br i1 %cmp, label %if.then, label %if.end4
     33 
     34 if.then:                                          ; preds = %entry
     35   %tmp = load i32, i32* @a, align 4
     36   %add = add nsw i32 %tmp, %t
     37   %cmp1 = icmp sgt i32 %add, 12
     38   br i1 %cmp1, label %if.then2, label %if.end4
     39 
     40 if.then2:                                         ; preds = %if.then
     41   tail call void @foo(i32 %add)
     42   %tmp1 = load i32, i32* @a, align 4
     43   br label %if.end4
     44 
     45 if.end4:                                          ; preds = %if.then2, %if.then, %entry
     46   %t.addr.0 = phi i32 [ %tmp1, %if.then2 ], [ %t, %if.then ], [ %t, %entry ]
     47   %tmp2 = load i32, i32* @b, align 4
     48   %add5 = add nsw i32 %tmp2, %t.addr.0
     49   tail call void @foo(i32 %add5)
     50   %tmp3 = load i32, i32* @b, align 4
     51   %add6 = add nsw i32 %tmp3, %t.addr.0
     52   ret i32 %add6
     53 }
     54 
     55 @C = common global i32 0, align 4
     56 
     57 ; Check that we catch AdrpLdrGotLdr case when we have a simple chain:
     58 ; adrp -> ldrgot -> ldr.
     59 ; CHECK-LABEL: _getC
     60 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
     61 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
     62 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
     63 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
     64 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
     65 ; CHECK-NEXT: ldr w0, {{\[}}[[LDRGOT_REG]]]
     66 ; CHECK-NEXT: ret
     67 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
     68 define i32 @getC() {
     69   %res = load i32, i32* @C, align 4
     70   ret i32 %res
     71 }
     72 
     73 ; LDRSW supports loading from a literal.
     74 ; Make sure we emit AdrpLdrGotLdr for those.
     75 ; CHECK-LABEL: _getSExtC
     76 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
     77 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
     78 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
     79 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
     80 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
     81 ; CHECK-NEXT: ldrsw x0, {{\[}}[[LDRGOT_REG]]]
     82 ; CHECK-NEXT: ret
     83 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
     84 define i64 @getSExtC() {
     85   %res = load i32, i32* @C, align 4
     86   %sextres = sext i32 %res to i64
     87   ret i64 %sextres
     88 }
     89 
     90 ; It may not be safe to fold the literal in the load if the address is
     91 ; used several times.
     92 ; Make sure we emit AdrpLdrGot for those.
     93 ; CHECK-LABEL: _getSeveralC
     94 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
     95 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
     96 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
     97 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
     98 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[LDRGOT_REG]]]
     99 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
    100 ; CHECK-NEXT: str [[ADD]], {{\[}}[[LDRGOT_REG]]]
    101 ; CHECK-NEXT: ret
    102 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
    103 define void @getSeveralC(i32 %t) {
    104 entry:
    105   %tmp = load i32, i32* @C, align 4
    106   %add = add nsw i32 %tmp, %t
    107   store i32 %add, i32* @C, align 4
    108   ret void
    109 }
    110 
    111 ; Make sure we catch that:
    112 ; adrp -> ldrgot -> str.
    113 ; CHECK-LABEL: _setC
    114 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    115 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE
    116 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    117 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF]
    118 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    119 ; CHECK-NEXT: str w0, {{\[}}[[LDRGOT_REG]]]
    120 ; CHECK-NEXT: ret
    121 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    122 define void @setC(i32 %t) {
    123 entry:
    124   store i32 %t, i32* @C, align 4
    125   ret void
    126 }
    127 
    128 ; Perform the same tests for internal global and a displacement
    129 ; in the addressing mode.
    130 ; Indeed we will get an ADD for those instead of LOADGot.
    131 @InternalC = internal global i32 0, align 4
    132 
    133 ; Check that we catch AdrpAddLdr case when we have a simple chain:
    134 ; adrp -> add -> ldr.
    135 ; CHECK-LABEL: _getInternalCPlus4
    136 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    137 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
    138 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
    139 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
    140 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    141 ; CHECK-NEXT: ldr w0, {{\[}}[[ADDGOT_REG]], #16]
    142 ; CHECK-NEXT: ret
    143 ; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
    144 define i32 @getInternalCPlus4() {
    145   %addr = getelementptr i32, i32* @InternalC, i32 4
    146   %res = load i32, i32* %addr, align 4
    147   ret i32 %res
    148 }
    149 
    150 ; LDRSW supports loading from a literal.
    151 ; Make sure we emit AdrpLdrGotLdr for those.
    152 ; CHECK-LABEL: _getSExtInternalCPlus4
    153 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    154 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
    155 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
    156 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
    157 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    158 ; CHECK-NEXT: ldrsw x0, {{\[}}[[ADDGOT_REG]], #16]
    159 ; CHECK-NEXT: ret
    160 ; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
    161 define i64 @getSExtInternalCPlus4() {
    162   %addr = getelementptr i32, i32* @InternalC, i32 4
    163   %res = load i32, i32* %addr, align 4
    164   %sextres = sext i32 %res to i64
    165   ret i64 %sextres
    166 }
    167 
    168 ; It may not be safe to fold the literal in the load if the address is
    169 ; used several times.
    170 ; Make sure we emit AdrpAdd for those.
    171 ; CHECK-LABEL: _getSeveralInternalCPlus4
    172 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    173 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
    174 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
    175 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
    176 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[ADDGOT_REG]], #16]
    177 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
    178 ; CHECK-NEXT: str [[ADD]], {{\[}}[[ADDGOT_REG]], #16]
    179 ; CHECK-NEXT: ret
    180 ; CHECK: .loh AdrpAdd [[ADRP_LABEL]], [[ADDGOT_LABEL]]
    181 define void @getSeveralInternalCPlus4(i32 %t) {
    182 entry:
    183   %addr = getelementptr i32, i32* @InternalC, i32 4
    184   %tmp = load i32, i32* %addr, align 4
    185   %add = add nsw i32 %tmp, %t
    186   store i32 %add, i32* %addr, align 4
    187   ret void
    188 }
    189 
    190 ; Make sure we catch that:
    191 ; adrp -> add -> str.
    192 ; CHECK-LABEL: _setInternalCPlus4
    193 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    194 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
    195 ; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]:
    196 ; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF
    197 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    198 ; CHECK-NEXT: str w0, {{\[}}[[ADDGOT_REG]], #16]
    199 ; CHECK-NEXT: ret
    200 ; CHECK: .loh AdrpAddStr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]]
    201 define void @setInternalCPlus4(i32 %t) {
    202 entry:
    203   %addr = getelementptr i32, i32* @InternalC, i32 4
    204   store i32 %t, i32* %addr, align 4
    205   ret void
    206 }
    207 
    208 ; Check that we catch AdrpAddLdr case when we have a simple chain:
    209 ; adrp -> ldr.
    210 ; CHECK-LABEL: _getInternalC
    211 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    212 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
    213 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    214 ; CHECK-NEXT: ldr w0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
    215 ; CHECK-NEXT: ret
    216 ; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]]
    217 define i32 @getInternalC() {
    218   %res = load i32, i32* @InternalC, align 4
    219   ret i32 %res
    220 }
    221 
    222 ; LDRSW supports loading from a literal.
    223 ; Make sure we emit AdrpLdrGotLdr for those.
    224 ; CHECK-LABEL: _getSExtInternalC
    225 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    226 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
    227 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    228 ; CHECK-NEXT: ldrsw x0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
    229 ; CHECK-NEXT: ret
    230 ; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]]
    231 define i64 @getSExtInternalC() {
    232   %res = load i32, i32* @InternalC, align 4
    233   %sextres = sext i32 %res to i64
    234   ret i64 %sextres
    235 }
    236 
    237 ; It may not be safe to fold the literal in the load if the address is
    238 ; used several times.
    239 ; Make sure we do not catch anything here. We have a adrp alone,
    240 ; there is not much we can do about it.
    241 ; CHECK-LABEL: _getSeveralInternalC
    242 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
    243 ; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
    244 ; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0
    245 ; CHECK-NEXT: str [[ADD]], {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
    246 ; CHECK-NEXT: ret
    247 define void @getSeveralInternalC(i32 %t) {
    248 entry:
    249   %tmp = load i32, i32* @InternalC, align 4
    250   %add = add nsw i32 %tmp, %t
    251   store i32 %add, i32* @InternalC, align 4
    252   ret void
    253 }
    254 
    255 ; Make sure we do not catch anything when:
    256 ; adrp -> str.
    257 ; We cannot fold anything in the str at this point.
    258 ; Indeed, strs do not support litterals.
    259 ; CHECK-LABEL: _setInternalC
    260 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE
    261 ; CHECK-NEXT: str w0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF]
    262 ; CHECK-NEXT: ret
    263 define void @setInternalC(i32 %t) {
    264 entry:
    265   store i32 %t, i32* @InternalC, align 4
    266   ret void
    267 }
    268 
    269 ; Now check other variant of loads/stores.
    270 
    271 @D = common global i8 0, align 4
    272 
    273 ; LDRB does not support loading from a literal.
    274 ; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those.
    275 ; CHECK-LABEL: _getD
    276 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    277 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
    278 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    279 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
    280 ; CHECK-NEXT: ldrb w0, {{\[}}[[LDRGOT_REG]]]
    281 ; CHECK-NEXT: ret
    282 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
    283 define i8 @getD() {
    284   %res = load i8, i8* @D, align 4
    285   ret i8 %res
    286 }
    287 
    288 ; CHECK-LABEL: _setD
    289 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    290 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
    291 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    292 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
    293 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
    294 ; CHECK-NEXT: strb w0, {{\[}}[[LDRGOT_REG]]]
    295 ; CHECK-NEXT: ret
    296 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
    297 define void @setD(i8 %t) {
    298   store i8 %t, i8* @D, align 4
    299   ret void
    300 }
    301 
    302 ; LDRSB supports loading from a literal.
    303 ; Make sure we emit AdrpLdrGotLdr for those.
    304 ; CHECK-LABEL: _getSExtD
    305 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    306 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
    307 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    308 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
    309 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    310 ; CHECK-NEXT: ldrsb w0, {{\[}}[[LDRGOT_REG]]]
    311 ; CHECK-NEXT: ret
    312 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    313 define i32 @getSExtD() {
    314   %res = load i8, i8* @D, align 4
    315   %sextres = sext i8 %res to i32
    316   ret i32 %sextres
    317 }
    318 
    319 ; LDRSB supports loading from a literal.
    320 ; Make sure we emit AdrpLdrGotLdr for those.
    321 ; CHECK-LABEL: _getSExt64D
    322 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    323 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE
    324 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    325 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF]
    326 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    327 ; CHECK-NEXT: ldrsb x0, {{\[}}[[LDRGOT_REG]]]
    328 ; CHECK-NEXT: ret
    329 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    330 define i64 @getSExt64D() {
    331   %res = load i8, i8* @D, align 4
    332   %sextres = sext i8 %res to i64
    333   ret i64 %sextres
    334 }
    335 
    336 @E = common global i16 0, align 4
    337 
    338 ; LDRH does not support loading from a literal.
    339 ; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those.
    340 ; CHECK-LABEL: _getE
    341 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    342 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
    343 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    344 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
    345 ; CHECK-NEXT: ldrh w0, {{\[}}[[LDRGOT_REG]]]
    346 ; CHECK-NEXT: ret
    347 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
    348 define i16 @getE() {
    349   %res = load i16, i16* @E, align 4
    350   ret i16 %res
    351 }
    352 
    353 ; LDRSH supports loading from a literal.
    354 ; Make sure we emit AdrpLdrGotLdr for those.
    355 ; CHECK-LABEL: _getSExtE
    356 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    357 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
    358 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    359 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
    360 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    361 ; CHECK-NEXT: ldrsh w0, {{\[}}[[LDRGOT_REG]]]
    362 ; CHECK-NEXT: ret
    363 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    364 define i32 @getSExtE() {
    365   %res = load i16, i16* @E, align 4
    366   %sextres = sext i16 %res to i32
    367   ret i32 %sextres
    368 }
    369 
    370 ; CHECK-LABEL: _setE
    371 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    372 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
    373 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    374 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
    375 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
    376 ; CHECK-NEXT: strh w0, {{\[}}[[LDRGOT_REG]]]
    377 ; CHECK-NEXT: ret
    378 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
    379 define void @setE(i16 %t) {
    380   store i16 %t, i16* @E, align 4
    381   ret void
    382 }
    383 
    384 ; LDRSH supports loading from a literal.
    385 ; Make sure we emit AdrpLdrGotLdr for those.
    386 ; CHECK-LABEL: _getSExt64E
    387 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    388 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE
    389 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    390 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF]
    391 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    392 ; CHECK-NEXT: ldrsh x0, {{\[}}[[LDRGOT_REG]]]
    393 ; CHECK-NEXT: ret
    394 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    395 define i64 @getSExt64E() {
    396   %res = load i16, i16* @E, align 4
    397   %sextres = sext i16 %res to i64
    398   ret i64 %sextres
    399 }
    400 
    401 @F = common global i64 0, align 4
    402 
    403 ; LDR supports loading from a literal.
    404 ; Make sure we emit AdrpLdrGotLdr for those.
    405 ; CHECK-LABEL: _getF
    406 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    407 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F@GOTPAGE
    408 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    409 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _F@GOTPAGEOFF]
    410 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    411 ; CHECK-NEXT: ldr x0, {{\[}}[[LDRGOT_REG]]]
    412 ; CHECK-NEXT: ret
    413 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    414 define i64 @getF() {
    415   %res = load i64, i64* @F, align 4
    416   ret i64 %res
    417 }
    418 
    419 ; CHECK-LABEL: _setF
    420 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    421 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F@GOTPAGE
    422 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    423 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _F@GOTPAGEOFF]
    424 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
    425 ; CHECK-NEXT: str x0, {{\[}}[[LDRGOT_REG]]]
    426 ; CHECK-NEXT: ret
    427 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
    428 define void @setF(i64 %t) {
    429   store i64 %t, i64* @F, align 4
    430   ret void
    431 }
    432 
    433 @G = common global float 0.0, align 4
    434 
    435 ; LDR float supports loading from a literal.
    436 ; Make sure we emit AdrpLdrGotLdr for those.
    437 ; CHECK-LABEL: _getG
    438 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    439 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G@GOTPAGE
    440 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    441 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _G@GOTPAGEOFF]
    442 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    443 ; CHECK-NEXT: ldr s0, {{\[}}[[LDRGOT_REG]]]
    444 ; CHECK-NEXT: ret
    445 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    446 define float @getG() {
    447   %res = load float, float* @G, align 4
    448   ret float %res
    449 }
    450 
    451 ; CHECK-LABEL: _setG
    452 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    453 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G@GOTPAGE
    454 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    455 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _G@GOTPAGEOFF]
    456 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
    457 ; CHECK-NEXT: str s0, {{\[}}[[LDRGOT_REG]]]
    458 ; CHECK-NEXT: ret
    459 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
    460 define void @setG(float %t) {
    461   store float %t, float* @G, align 4
    462   ret void
    463 }
    464 
    465 @H = common global half 0.0, align 4
    466 
    467 ; LDR half supports loading from a literal.
    468 ; Make sure we emit AdrpLdrGotLdr for those.
    469 ; CHECK-LABEL: _getH
    470 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    471 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H@GOTPAGE
    472 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    473 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _H@GOTPAGEOFF]
    474 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    475 ; CHECK-NEXT: ldr h0, {{\[}}[[LDRGOT_REG]]]
    476 ; CHECK-NEXT: ret
    477 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    478 define half @getH() {
    479   %res = load half, half* @H, align 4
    480   ret half %res
    481 }
    482 
    483 ; CHECK-LABEL: _setH
    484 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    485 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H@GOTPAGE
    486 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    487 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _H@GOTPAGEOFF]
    488 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
    489 ; CHECK-NEXT: str h0, {{\[}}[[LDRGOT_REG]]]
    490 ; CHECK-NEXT: ret
    491 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
    492 define void @setH(half %t) {
    493   store half %t, half* @H, align 4
    494   ret void
    495 }
    496 
    497 @I = common global double 0.0, align 4
    498 
    499 ; LDR double supports loading from a literal.
    500 ; Make sure we emit AdrpLdrGotLdr for those.
    501 ; CHECK-LABEL: _getI
    502 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    503 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I@GOTPAGE
    504 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    505 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _I@GOTPAGEOFF]
    506 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    507 ; CHECK-NEXT: ldr d0, {{\[}}[[LDRGOT_REG]]]
    508 ; CHECK-NEXT: ret
    509 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    510 define double @getI() {
    511   %res = load double, double* @I, align 4
    512   ret double %res
    513 }
    514 
    515 ; CHECK-LABEL: _setI
    516 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    517 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I@GOTPAGE
    518 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    519 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _I@GOTPAGEOFF]
    520 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
    521 ; CHECK-NEXT: str d0, {{\[}}[[LDRGOT_REG]]]
    522 ; CHECK-NEXT: ret
    523 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
    524 define void @setI(double %t) {
    525   store double %t, double* @I, align 4
    526   ret void
    527 }
    528 
    529 @J = common global <2 x i32> <i32 0, i32 0>, align 4
    530 
    531 ; LDR 64-bit vector supports loading from a literal.
    532 ; Make sure we emit AdrpLdrGotLdr for those.
    533 ; CHECK-LABEL: _getJ
    534 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    535 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J@GOTPAGE
    536 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    537 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _J@GOTPAGEOFF]
    538 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    539 ; CHECK-NEXT: ldr d0, {{\[}}[[LDRGOT_REG]]]
    540 ; CHECK-NEXT: ret
    541 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    542 define <2 x i32> @getJ() {
    543   %res = load <2 x i32>, <2 x i32>* @J, align 4
    544   ret <2 x i32> %res
    545 }
    546 
    547 ; CHECK-LABEL: _setJ
    548 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    549 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J@GOTPAGE
    550 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    551 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _J@GOTPAGEOFF]
    552 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
    553 ; CHECK-NEXT: str d0, {{\[}}[[LDRGOT_REG]]]
    554 ; CHECK-NEXT: ret
    555 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
    556 define void @setJ(<2 x i32> %t) {
    557   store <2 x i32> %t, <2 x i32>* @J, align 4
    558   ret void
    559 }
    560 
    561 @K = common global <4 x i32> <i32 0, i32 0, i32 0, i32 0>, align 4
    562 
    563 ; LDR 128-bit vector supports loading from a literal.
    564 ; Make sure we emit AdrpLdrGotLdr for those.
    565 ; CHECK-LABEL: _getK
    566 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    567 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K@GOTPAGE
    568 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    569 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _K@GOTPAGEOFF]
    570 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    571 ; CHECK-NEXT: ldr q0, {{\[}}[[LDRGOT_REG]]]
    572 ; CHECK-NEXT: ret
    573 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    574 define <4 x i32> @getK() {
    575   %res = load <4 x i32>, <4 x i32>* @K, align 4
    576   ret <4 x i32> %res
    577 }
    578 
    579 ; CHECK-LABEL: _setK
    580 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    581 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K@GOTPAGE
    582 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    583 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _K@GOTPAGEOFF]
    584 ; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]:
    585 ; CHECK-NEXT: str q0, {{\[}}[[LDRGOT_REG]]]
    586 ; CHECK-NEXT: ret
    587 ; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]]
    588 define void @setK(<4 x i32> %t) {
    589   store <4 x i32> %t, <4 x i32>* @K, align 4
    590   ret void
    591 }
    592 
    593 @L = common global <1 x i8> <i8 0>, align 4
    594 
    595 ; LDR 8-bit vector supports loading from a literal.
    596 ; Make sure we emit AdrpLdrGotLdr for those.
    597 ; CHECK-LABEL: _getL
    598 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    599 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L@GOTPAGE
    600 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    601 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _L@GOTPAGEOFF]
    602 ; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]:
    603 ; CHECK-NEXT: ldr b0, {{\[}}[[LDRGOT_REG]]]
    604 ; CHECK-NEXT: ret
    605 ; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]]
    606 define <1 x i8> @getL() {
    607   %res = load <1 x i8>, <1 x i8>* @L, align 4
    608   ret <1 x i8> %res
    609 }
    610 
    611 ; CHECK-LABEL: _setL
    612 ; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]:
    613 ; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L@GOTPAGE
    614 ; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]:
    615 ; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _L@GOTPAGEOFF]
    616 ; CHECK-NEXT: ; kill
    617 ; Ultimately we should generate str b0, but right now, we match the vector
    618 ; variant which does not allow to fold the immediate into the store.
    619 ; CHECK-NEXT: st1.b { v0 }[0], {{\[}}[[LDRGOT_REG]]]
    620 ; CHECK-NEXT: ret
    621 ; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]]
    622 define void @setL(<1 x i8> %t) {
    623   store <1 x i8> %t, <1 x i8>* @L, align 4
    624   ret void
    625 }
    626 
    627 ; Make sure we do not assert when we do not track
    628 ; all the aliases of a tuple register.
    629 ; Indeed the tuple register can be tracked because of
    630 ; one of its element, but the other elements of the tuple
    631 ; do not need to be tracked and we used to assert on that.
    632 ; Note: The test case is fragile in the sense that we need
    633 ; a tuple register to appear in the lowering. Thus, the target
    634 ; cpu is required to have the problem reproduced.
    635 ; CHECK-LABEL: _uninterestingSub
    636 ; CHECK: adrp [[ADRP_REG:x[0-9]+]], [[CONSTPOOL:lCPI[0-9]+_[0-9]+]]@PAGE
    637 ; CHECK-NEXT: ldr q[[IDX:[0-9]+]], {{\[}}[[ADRP_REG]], [[CONSTPOOL]]@PAGEOFF]
    638 ; The tuple comes from the next instruction.
    639 ; CHECK-NEXT: tbl.16b v{{[0-9]+}}, { v{{[0-9]+}}, v{{[0-9]+}} }, v[[IDX]]
    640 ; CHECK: ret
    641 define void @uninterestingSub(i8* nocapture %row) #0 {
    642   %tmp = bitcast i8* %row to <16 x i8>*
    643   %tmp1 = load <16 x i8>, <16 x i8>* %tmp, align 16
    644   %vext43 = shufflevector <16 x i8> <i8 undef, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0>, <16 x i8> %tmp1, <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>
    645   %add.i.414 = add <16 x i8> zeroinitializer, %vext43
    646   store <16 x i8> %add.i.414, <16 x i8>* %tmp, align 16
    647   %add.ptr51 = getelementptr inbounds i8, i8* %row, i64 16
    648   %tmp2 = bitcast i8* %add.ptr51 to <16 x i8>*
    649   %tmp3 = load <16 x i8>, <16 x i8>* %tmp2, align 16
    650   %tmp4 = bitcast i8* undef to <16 x i8>*
    651   %tmp5 = load <16 x i8>, <16 x i8>* %tmp4, align 16
    652   %vext157 = shufflevector <16 x i8> %tmp3, <16 x i8> %tmp5, <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>
    653   %add.i.402 = add <16 x i8> zeroinitializer, %vext157
    654   store <16 x i8> %add.i.402, <16 x i8>* %tmp4, align 16
    655   ret void
    656 }
    657 
    658 @.str.89 = external unnamed_addr constant [12 x i8], align 1
    659 @.str.90 = external unnamed_addr constant [5 x i8], align 1
    660 ; CHECK-LABEL: test_r274582
    661 define void @test_r274582() {
    662 entry:
    663   br i1 undef, label %if.then.i, label %if.end.i
    664 if.then.i:
    665   ret void
    666 if.end.i:
    667 ; CHECK: .loh AdrpAdrp Lloh91, Lloh93
    668 ; CHECK: .loh AdrpLdr Lloh91, Lloh92
    669 ; CHECK: .loh AdrpLdrGot Lloh93, Lloh95
    670 ; CHECK: .loh AdrpLdrGot Lloh94, Lloh96
    671   %mul.i.i.i = fmul double undef, 1.000000e-06
    672   %add.i.i.i = fadd double undef, %mul.i.i.i
    673   %sub.i.i = fsub double %add.i.i.i, undef
    674   call void (i8*, ...) @callee(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str.89, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.90, i64 0, i64 0), double %sub.i.i)
    675   unreachable
    676 }
    677 declare void @callee(i8* nocapture readonly, ...) 
    678 
    679 attributes #0 = { "target-cpu"="cyclone" }
    680