From 4a93cd8f662b0d3c7b45163e3c165f9cef9a33c8 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Thu, 27 Aug 2015 23:47:10 +0000 Subject: [PATCH] [AArch64][CollectLOH] Fix a regression that prevented us to detect chains of more than 2 instructions. I introduced this regression a while back and did not noticed it because I somehow forgot to push the initial test cases for the pass! Fix that as well! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246239 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64CollectLOH.cpp | 8 +- .../AArch64/arm64-addr-type-promotion.ll | 5 +- test/CodeGen/AArch64/arm64-collect-loh.ll | 571 ++++++++++++++++++ 3 files changed, 580 insertions(+), 4 deletions(-) diff --git a/lib/Target/AArch64/AArch64CollectLOH.cpp b/lib/Target/AArch64/AArch64CollectLOH.cpp index 315aee76158..68d4a55fee4 100644 --- a/lib/Target/AArch64/AArch64CollectLOH.cpp +++ b/lib/Target/AArch64/AArch64CollectLOH.cpp @@ -523,6 +523,8 @@ static bool isCandidateStore(const MachineInstr *Instr) { switch (Instr->getOpcode()) { default: return false; + case AArch64::STRBBui: + case AArch64::STRHHui: case AArch64::STRBui: case AArch64::STRHui: case AArch64::STRWui: @@ -884,7 +886,8 @@ static void computeOthers(const InstrToInstrs &UseToDefs, bool IsL2Add = (ImmediateDefOpc == AArch64::ADDXri); // If the chain is three instructions long and ldr is the second element, // then this ldr must load form GOT, otherwise this is not a correct chain. - if (L2 && !IsL2Add && L2->getOperand(2).getTargetFlags() != AArch64II::MO_GOT) + if (L2 && !IsL2Add && + !(L2->getOperand(2).getTargetFlags() & AArch64II::MO_GOT)) continue; SmallVector Args; MCLOHType Kind; @@ -1000,7 +1003,8 @@ static void collectInvolvedReg(const MachineFunction &MF, MapRegToId &RegToId, DEBUG(dbgs() << "** Collect Involved Register\n"); for (const auto &MBB : MF) { for (const MachineInstr &MI : MBB) { - if (!canDefBePartOfLOH(&MI)) + if (!canDefBePartOfLOH(&MI) && + !isCandidateLoad(&MI) && !isCandidateStore(&MI)) continue; // Process defs diff --git a/test/CodeGen/AArch64/arm64-addr-type-promotion.ll b/test/CodeGen/AArch64/arm64-addr-type-promotion.ll index 1a9074beb40..d46800d34ca 100644 --- a/test/CodeGen/AArch64/arm64-addr-type-promotion.ll +++ b/test/CodeGen/AArch64/arm64-addr-type-promotion.ll @@ -1,6 +1,7 @@ -; RUN: llc -march arm64 < %s | FileCheck %s +; RUN: llc -march arm64 < %s -aarch64-collect-loh=false | FileCheck %s ; rdar://13452552 -; ModuleID = 'reduced_test.ll' +; Disable the collecting of LOH so that the labels do not get in the +; way of the NEXT patterns. target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n32:64-S128" target triple = "arm64-apple-ios3.0.0" diff --git a/test/CodeGen/AArch64/arm64-collect-loh.ll b/test/CodeGen/AArch64/arm64-collect-loh.ll index c0aa63cc433..e737861ae94 100644 --- a/test/CodeGen/AArch64/arm64-collect-loh.ll +++ b/test/CodeGen/AArch64/arm64-collect-loh.ll @@ -51,3 +51,574 @@ if.end4: ; preds = %if.then2, %if.then, %add6 = add nsw i32 %tmp3, %t.addr.0 ret i32 %add6 } + +@C = common global i32 0, align 4 + +; Check that we catch AdrpLdrGotLdr case when we have a simple chain: +; adrp -> ldrgot -> ldr. +; CHECK-LABEL: _getC +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr w0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define i32 @getC() { + %res = load i32, i32* @C, align 4 + ret i32 %res +} + +; LDRSW supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getSExtC +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldrsw x0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define i64 @getSExtC() { + %res = load i32, i32* @C, align 4 + %sextres = sext i32 %res to i64 + ret i64 %sextres +} + +; It may not be safe to fold the literal in the load if the address is +; used several times. +; Make sure we emit AdrpLdrGot for those. +; CHECK-LABEL: _getSeveralC +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF] +; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0 +; CHECK-NEXT: str [[ADD]], {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]] +define void @getSeveralC(i32 %t) { +entry: + %tmp = load i32, i32* @C, align 4 + %add = add nsw i32 %tmp, %t + store i32 %add, i32* @C, align 4 + ret void +} + +; Make sure we catch that: +; adrp -> ldrgot -> str. +; CHECK-LABEL: _setC +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _C@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _C@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: str w0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define void @setC(i32 %t) { +entry: + store i32 %t, i32* @C, align 4 + ret void +} + +; Perform the same tests for internal global and a displacement +; in the addressing mode. +; Indeed we will get an ADD for those instead of LOADGot. +@InternalC = internal global i32 0, align 4 + +; Check that we catch AdrpAddLdr case when we have a simple chain: +; adrp -> add -> ldr. +; CHECK-LABEL: _getInternalCPlus4 +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE +; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr w0, {{\[}}[[ADDGOT_REG]], #16] +; CHECK-NEXT: ret +; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]] +define i32 @getInternalCPlus4() { + %addr = getelementptr i32, i32* @InternalC, i32 4 + %res = load i32, i32* %addr, align 4 + ret i32 %res +} + +; LDRSW supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getSExtInternalCPlus4 +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE +; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldrsw x0, {{\[}}[[ADDGOT_REG]], #16] +; CHECK-NEXT: ret +; CHECK: .loh AdrpAddLdr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]] +define i64 @getSExtInternalCPlus4() { + %addr = getelementptr i32, i32* @InternalC, i32 4 + %res = load i32, i32* %addr, align 4 + %sextres = sext i32 %res to i64 + ret i64 %sextres +} + +; It may not be safe to fold the literal in the load if the address is +; used several times. +; Make sure we emit AdrpAdd for those. +; CHECK-LABEL: _getSeveralInternalCPlus4 +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE +; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF +; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[ADDGOT_REG]], #16] +; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0 +; CHECK-NEXT: str [[ADD]], {{\[}}[[ADDGOT_REG]], #16] +; CHECK-NEXT: ret +; CHECK: .loh AdrpAdd [[ADRP_LABEL]], [[ADDGOT_LABEL]] +define void @getSeveralInternalCPlus4(i32 %t) { +entry: + %addr = getelementptr i32, i32* @InternalC, i32 4 + %tmp = load i32, i32* %addr, align 4 + %add = add nsw i32 %tmp, %t + store i32 %add, i32* %addr, align 4 + ret void +} + +; Make sure we catch that: +; adrp -> add -> str. +; CHECK-LABEL: _setInternalCPlus4 +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE +; CHECK-NEXT: [[ADDGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: add [[ADDGOT_REG:x[0-9]+]], [[ADRP_REG]], _InternalC@PAGEOFF +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: str w0, {{\[}}[[ADDGOT_REG]], #16] +; CHECK-NEXT: ret +; CHECK: .loh AdrpAddStr [[ADRP_LABEL]], [[ADDGOT_LABEL]], [[LDR_LABEL]] +define void @setInternalCPlus4(i32 %t) { +entry: + %addr = getelementptr i32, i32* @InternalC, i32 4 + store i32 %t, i32* %addr, align 4 + ret void +} + +; Check that we catch AdrpAddLdr case when we have a simple chain: +; adrp -> ldr. +; CHECK-LABEL: _getInternalC +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr w0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]] +define i32 @getInternalC() { + %res = load i32, i32* @InternalC, align 4 + ret i32 %res +} + +; LDRSW supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getSExtInternalC +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldrsw x0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdr [[ADRP_LABEL]], [[LDR_LABEL]] +define i64 @getSExtInternalC() { + %res = load i32, i32* @InternalC, align 4 + %sextres = sext i32 %res to i64 + ret i64 %sextres +} + +; It may not be safe to fold the literal in the load if the address is +; used several times. +; Make sure we do not catch anything here. We have a adrp alone, +; there is not much we can do about it. +; CHECK-LABEL: _getSeveralInternalC +; CHECK: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE +; CHECK-NEXT: ldr [[LOAD:w[0-9]+]], {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF] +; CHECK-NEXT: add [[ADD:w[0-9]+]], [[LOAD]], w0 +; CHECK-NEXT: str [[ADD]], {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF] +; CHECK-NEXT: ret +define void @getSeveralInternalC(i32 %t) { +entry: + %tmp = load i32, i32* @InternalC, align 4 + %add = add nsw i32 %tmp, %t + store i32 %add, i32* @InternalC, align 4 + ret void +} + +; Make sure we do not catch anything when: +; adrp -> str. +; We cannot fold anything in the str at this point. +; Indeed, strs do not support litterals. +; CHECK-LABEL: _setInternalC +; CHECK: adrp [[ADRP_REG:x[0-9]+]], _InternalC@PAGE +; CHECK-NEXT: str w0, {{\[}}[[ADRP_REG]], _InternalC@PAGEOFF] +; CHECK-NEXT: ret +define void @setInternalC(i32 %t) { +entry: + store i32 %t, i32* @InternalC, align 4 + ret void +} + +; Now check other variant of loads/stores. + +@D = common global i8 0, align 4 + +; LDRB does not support loading from a literal. +; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those. +; CHECK-LABEL: _getD +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF] +; CHECK-NEXT: ldrb w0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]] +define i8 @getD() { + %res = load i8, i8* @D, align 4 + ret i8 %res +} + +; CHECK-LABEL: _setD +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF] +; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: strb w0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]] +define void @setD(i8 %t) { + store i8 %t, i8* @D, align 4 + ret void +} + +; LDRSB supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getSExtD +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldrsb w0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define i32 @getSExtD() { + %res = load i8, i8* @D, align 4 + %sextres = sext i8 %res to i32 + ret i32 %sextres +} + +; LDRSB supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getSExt64D +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _D@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _D@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldrsb x0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define i64 @getSExt64D() { + %res = load i8, i8* @D, align 4 + %sextres = sext i8 %res to i64 + ret i64 %sextres +} + +@E = common global i16 0, align 4 + +; LDRH does not support loading from a literal. +; Make sure we emit AdrpLdrGot and not AdrpLdrGotLdr for those. +; CHECK-LABEL: _getE +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF] +; CHECK-NEXT: ldrh w0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]] +define i16 @getE() { + %res = load i16, i16* @E, align 4 + ret i16 %res +} + +; LDRSH supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getSExtE +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldrsh w0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define i32 @getSExtE() { + %res = load i16, i16* @E, align 4 + %sextres = sext i16 %res to i32 + ret i32 %sextres +} + +; CHECK-LABEL: _setE +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF] +; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: strh w0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]] +define void @setE(i16 %t) { + store i16 %t, i16* @E, align 4 + ret void +} + +; LDRSH supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getSExt64E +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _E@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _E@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldrsh x0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define i64 @getSExt64E() { + %res = load i16, i16* @E, align 4 + %sextres = sext i16 %res to i64 + ret i64 %sextres +} + +@F = common global i64 0, align 4 + +; LDR supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getF +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _F@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr x0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define i64 @getF() { + %res = load i64, i64* @F, align 4 + ret i64 %res +} + +; CHECK-LABEL: _setF +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _F@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _F@GOTPAGEOFF] +; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: str x0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]] +define void @setF(i64 %t) { + store i64 %t, i64* @F, align 4 + ret void +} + +@G = common global float 0.0, align 4 + +; LDR float supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getG +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _G@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr s0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define float @getG() { + %res = load float, float* @G, align 4 + ret float %res +} + +; CHECK-LABEL: _setG +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _G@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _G@GOTPAGEOFF] +; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: str s0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]] +define void @setG(float %t) { + store float %t, float* @G, align 4 + ret void +} + +@H = common global half 0.0, align 4 + +; LDR half supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getH +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _H@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr h0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define half @getH() { + %res = load half, half* @H, align 4 + ret half %res +} + +; CHECK-LABEL: _setH +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _H@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _H@GOTPAGEOFF] +; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: str h0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]] +define void @setH(half %t) { + store half %t, half* @H, align 4 + ret void +} + +@I = common global double 0.0, align 4 + +; LDR double supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getI +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _I@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr d0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define double @getI() { + %res = load double, double* @I, align 4 + ret double %res +} + +; CHECK-LABEL: _setI +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _I@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _I@GOTPAGEOFF] +; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: str d0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]] +define void @setI(double %t) { + store double %t, double* @I, align 4 + ret void +} + +@J = common global <2 x i32> , align 4 + +; LDR 64-bit vector supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getJ +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _J@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr d0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define <2 x i32> @getJ() { + %res = load <2 x i32>, <2 x i32>* @J, align 4 + ret <2 x i32> %res +} + +; CHECK-LABEL: _setJ +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _J@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _J@GOTPAGEOFF] +; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: str d0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]] +define void @setJ(<2 x i32> %t) { + store <2 x i32> %t, <2 x i32>* @J, align 4 + ret void +} + +@K = common global <4 x i32> , align 4 + +; LDR 128-bit vector supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getK +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _K@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr q0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define <4 x i32> @getK() { + %res = load <4 x i32>, <4 x i32>* @K, align 4 + ret <4 x i32> %res +} + +; CHECK-LABEL: _setK +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _K@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _K@GOTPAGEOFF] +; CHECK-NEXT: [[STR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: str q0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotStr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[STR_LABEL]] +define void @setK(<4 x i32> %t) { + store <4 x i32> %t, <4 x i32>* @K, align 4 + ret void +} + +@L = common global <1 x i8> , align 4 + +; LDR 8-bit vector supports loading from a literal. +; Make sure we emit AdrpLdrGotLdr for those. +; CHECK-LABEL: _getL +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _L@GOTPAGEOFF] +; CHECK-NEXT: [[LDR_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr b0, {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGotLdr [[ADRP_LABEL]], [[LDRGOT_LABEL]], [[LDR_LABEL]] +define <1 x i8> @getL() { + %res = load <1 x i8>, <1 x i8>* @L, align 4 + ret <1 x i8> %res +} + +; CHECK-LABEL: _setL +; CHECK: [[ADRP_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: adrp [[ADRP_REG:x[0-9]+]], _L@GOTPAGE +; CHECK-NEXT: [[LDRGOT_LABEL:Lloh[0-9]+]]: +; CHECK-NEXT: ldr [[LDRGOT_REG:x[0-9]+]], {{\[}}[[ADRP_REG]], _L@GOTPAGEOFF] +; Ultimately we should generate str b0, but right now, we match the vector +; variant which does not allow to fold the immediate into the store. +; CHECK-NEXT: st1.b { v0 }[0], {{\[}}[[LDRGOT_REG]]] +; CHECK-NEXT: ret +; CHECK: .loh AdrpLdrGot [[ADRP_LABEL]], [[LDRGOT_LABEL]] +define void @setL(<1 x i8> %t) { + store <1 x i8> %t, <1 x i8>* @L, align 4 + ret void +} -- 2.34.1