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