mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-25 23:00:15 +00:00
[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! llvm-svn: 246239
This commit is contained in:
parent
f0fa8a80a3
commit
fa4ecb4b9a
@ -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<const MachineInstr *, 3> 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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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> <i32 0, i32 0>, 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> <i32 0, i32 0, i32 0, i32 0>, 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> <i8 0>, 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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user