mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-05 10:17:36 +00:00
[AArch64] Optimise load(adr address) to ldr address
Providing that the load is known to be 4 byte aligned, we can optimise a ldr(adr address) to just ldr address. Differential Revision: https://reviews.llvm.org/D51030 llvm-svn: 341058
This commit is contained in:
parent
38dbf57876
commit
b3ee777d21
@ -2853,10 +2853,10 @@ def am_ldrlit : Operand<iPTR> {
|
||||
let OperandType = "OPERAND_PCREL";
|
||||
}
|
||||
|
||||
let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
|
||||
class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm>
|
||||
let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
|
||||
class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
|
||||
: I<(outs regtype:$Rt), (ins am_ldrlit:$label),
|
||||
asm, "\t$Rt, $label", "", []>,
|
||||
asm, "\t$Rt, $label", "", pat>,
|
||||
Sched<[WriteLD]> {
|
||||
bits<5> Rt;
|
||||
bits<19> label;
|
||||
|
@ -1891,14 +1891,37 @@ def : InstAlias<"prfm $Rt, [$Rn]", (PRFMui prfop:$Rt, GPR64sp:$Rn, 0)>;
|
||||
|
||||
//---
|
||||
// (literal)
|
||||
def LDRWl : LoadLiteral<0b00, 0, GPR32z, "ldr">;
|
||||
def LDRXl : LoadLiteral<0b01, 0, GPR64z, "ldr">;
|
||||
def LDRSl : LoadLiteral<0b00, 1, FPR32Op, "ldr">;
|
||||
def LDRDl : LoadLiteral<0b01, 1, FPR64Op, "ldr">;
|
||||
def LDRQl : LoadLiteral<0b10, 1, FPR128Op, "ldr">;
|
||||
|
||||
def alignedglobal : PatLeaf<(iPTR iPTR:$label), [{
|
||||
if (auto *G = dyn_cast<GlobalAddressSDNode>(N)) {
|
||||
const DataLayout &DL = MF->getDataLayout();
|
||||
unsigned Align = G->getGlobal()->getPointerAlignment(DL);
|
||||
return Align >= 4 && G->getOffset() % 4 == 0;
|
||||
}
|
||||
if (auto *C = dyn_cast<ConstantPoolSDNode>(N))
|
||||
return C->getAlignment() >= 4 && C->getOffset() % 4 == 0;
|
||||
return false;
|
||||
}]>;
|
||||
|
||||
def LDRWl : LoadLiteral<0b00, 0, GPR32z, "ldr",
|
||||
[(set GPR32z:$Rt, (load (AArch64adr alignedglobal:$label)))]>;
|
||||
def LDRXl : LoadLiteral<0b01, 0, GPR64z, "ldr",
|
||||
[(set GPR64z:$Rt, (load (AArch64adr alignedglobal:$label)))]>;
|
||||
def LDRSl : LoadLiteral<0b00, 1, FPR32Op, "ldr",
|
||||
[(set (f32 FPR32Op:$Rt), (load (AArch64adr alignedglobal:$label)))]>;
|
||||
def LDRDl : LoadLiteral<0b01, 1, FPR64Op, "ldr",
|
||||
[(set (f64 FPR64Op:$Rt), (load (AArch64adr alignedglobal:$label)))]>;
|
||||
def LDRQl : LoadLiteral<0b10, 1, FPR128Op, "ldr",
|
||||
[(set (f128 FPR128Op:$Rt), (load (AArch64adr alignedglobal:$label)))]>;
|
||||
|
||||
// load sign-extended word
|
||||
def LDRSWl : LoadLiteral<0b10, 0, GPR64z, "ldrsw">;
|
||||
def LDRSWl : LoadLiteral<0b10, 0, GPR64z, "ldrsw",
|
||||
[(set GPR64z:$Rt, (sextloadi32 (AArch64adr alignedglobal:$label)))]>;
|
||||
|
||||
let AddedComplexity = 20 in {
|
||||
def : Pat<(i64 (zextloadi32 (AArch64adr alignedglobal:$label))),
|
||||
(SUBREG_TO_REG (i64 0), (LDRWl $label), sub_32)>;
|
||||
}
|
||||
|
||||
// prefetch
|
||||
def PRFMl : PrefetchLiteral<0b11, 0, "prfm", []>;
|
||||
|
@ -33,16 +33,14 @@ define i32 @global_i32() {
|
||||
; CHECK-LABEL: global_i32:
|
||||
%val = load i32, i32* @var32
|
||||
ret i32 %val
|
||||
; CHECK: adr x[[ADDR_REG:[0-9]+]], var32
|
||||
; CHECK: ldr w0, [x[[ADDR_REG]]]
|
||||
; CHECK: ldr w0, var32
|
||||
}
|
||||
|
||||
define i64 @global_i64() {
|
||||
; CHECK-LABEL: global_i64:
|
||||
%val = load i64, i64* @var64
|
||||
ret i64 %val
|
||||
; CHECK: adr x[[ADDR_REG:[0-9]+]], var64
|
||||
; CHECK: ldr x0, [x[[ADDR_REG]]]
|
||||
; CHECK: ldr x0, var64
|
||||
}
|
||||
|
||||
define <2 x i64> @constpool() {
|
||||
|
@ -19,7 +19,7 @@ define void @check_float() {
|
||||
%newval2 = fadd float %val, 128.0
|
||||
store volatile float %newval2, float* @varf32
|
||||
; CHECK-DAG: ldr {{s[0-9]+}}, [{{x[0-9]+}}, {{#?}}:lo12:.LCPI0_0
|
||||
; TINY-DAG: ldr {{s[0-9]+}}, [{{x[0-9]+}}]
|
||||
; TINY-DAG: ldr {{s[0-9]+}}, .LCPI0_0
|
||||
|
||||
; CHECK: ret
|
||||
; TINY: ret
|
||||
@ -39,7 +39,7 @@ define void @check_double() {
|
||||
%newval2 = fadd double %val, 128.0
|
||||
store volatile double %newval2, double* @varf64
|
||||
; CHECK-DAG: ldr {{d[0-9]+}}, [{{x[0-9]+}}, {{#?}}:lo12:.LCPI1_0
|
||||
; TINY-DAG: ldr {{d[0-9]+}}, [{{x[0-9]+}}]
|
||||
; TINY-DAG: ldr {{d[0-9]+}}, .LCPI1_0
|
||||
|
||||
; CHECK: ret
|
||||
; TINY: ret
|
||||
@ -51,8 +51,7 @@ define void @check_double() {
|
||||
; LARGE-NEXT: movk [[REG]], #16457, lsl #16
|
||||
; LARGE-NEXT: fmov s0, [[REG]]
|
||||
; TINY-LABEL: check_float2
|
||||
; TINY: adr x[[REG:[0-9]+]], .LCPI2_0
|
||||
; TINY-NEXT: ldr s0, [x[[REG]]]
|
||||
; TINY: ldr s0, .LCPI2_0
|
||||
define float @check_float2() {
|
||||
ret float 3.14159274101257324218750
|
||||
}
|
||||
@ -64,8 +63,7 @@ define float @check_float2() {
|
||||
; LARGE-NEXT: movk [[REG]], #16393, lsl #48
|
||||
; LARGE-NEXT: fmov d0, [[REG]]
|
||||
; TINY-LABEL: check_double2
|
||||
; TINY: adr x[[REG:[0-9]+]], .LCPI3_0
|
||||
; TINY-NEXT: ldr d0, [x[[REG]]]
|
||||
; TINY: ldr d0, .LCPI3_0
|
||||
define double @check_double2() {
|
||||
ret double 3.1415926535897931159979634685441851615905761718750
|
||||
}
|
||||
|
132
test/CodeGen/AArch64/ldradr.ll
Normal file
132
test/CodeGen/AArch64/ldradr.ll
Normal file
@ -0,0 +1,132 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mtriple=aarch64-none-eabi -code-model=tiny -verify-machineinstrs | FileCheck %s
|
||||
|
||||
%struct.T = type <{ i32, i64, i8, i32 }>
|
||||
|
||||
@ptr = external local_unnamed_addr global i32*, align 8
|
||||
@ch = external local_unnamed_addr global i32, align 4
|
||||
@ch8 = external local_unnamed_addr global i8, align 4
|
||||
@t = external local_unnamed_addr global %struct.T, align 4
|
||||
@t2 = external local_unnamed_addr global %struct.T, align 2
|
||||
@f = external local_unnamed_addr global float, align 4
|
||||
|
||||
define i32 @barp() {
|
||||
; CHECK-LABEL: barp:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr x8, ptr
|
||||
; CHECK-NEXT: ldr w0, [x8]
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i32*, i32** @ptr, align 8
|
||||
%1 = load i32, i32* %0, align 4
|
||||
ret i32 %1
|
||||
}
|
||||
|
||||
define i32 @barch() {
|
||||
; CHECK-LABEL: barch:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w0, ch
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i32, i32* @ch, align 4
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
define i32 @barta() {
|
||||
; CHECK-LABEL: barta:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w0, t
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i32, i32* getelementptr inbounds (%struct.T, %struct.T* @t, i64 0, i32 0), align 4
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
define i64 @bartb() {
|
||||
; CHECK-LABEL: bartb:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr x0, t+4
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i64, i64* getelementptr inbounds (%struct.T, %struct.T* @t, i64 0, i32 1), align 8
|
||||
ret i64 %0
|
||||
}
|
||||
|
||||
define i32 @bartc() {
|
||||
; CHECK-LABEL: bartc:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: adr x8, t+13
|
||||
; CHECK-NEXT: ldr w0, [x8]
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i32, i32* getelementptr inbounds (%struct.T, %struct.T* @t, i64 0, i32 3), align 1
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
define i32 @bart2a() {
|
||||
; CHECK-LABEL: bart2a:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: adr x8, t2
|
||||
; CHECK-NEXT: ldr w0, [x8]
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i32, i32* getelementptr inbounds (%struct.T, %struct.T* @t2, i64 0, i32 0), align 2
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
define i64 @zextload() {
|
||||
; CHECK-LABEL: zextload:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr w0, ch
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i32, i32* @ch, align 4
|
||||
%1 = zext i32 %0 to i64
|
||||
ret i64 %1
|
||||
}
|
||||
|
||||
define i64 @zextload8() {
|
||||
; CHECK-LABEL: zextload8:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: adr x8, ch8
|
||||
; CHECK-NEXT: ldrb w0, [x8]
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i8, i8* @ch8, align 4
|
||||
%1 = zext i8 %0 to i64
|
||||
ret i64 %1
|
||||
}
|
||||
|
||||
define i64 @sextload() {
|
||||
; CHECK-LABEL: sextload:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldrsw x0, ch
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i32, i32* @ch, align 4
|
||||
%1 = sext i32 %0 to i64
|
||||
ret i64 %1
|
||||
}
|
||||
|
||||
define i64 @sextload8() {
|
||||
; CHECK-LABEL: sextload8:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: adr x8, ch8
|
||||
; CHECK-NEXT: ldrsb x0, [x8]
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load i8, i8* @ch8, align 4
|
||||
%1 = sext i8 %0 to i64
|
||||
ret i64 %1
|
||||
}
|
||||
|
||||
define float @floatload() {
|
||||
; CHECK-LABEL: floatload:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr s0, f
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%0 = load float, float* @f, align 4
|
||||
ret float %0
|
||||
}
|
||||
|
@ -17,8 +17,7 @@ define void @floating_lits() {
|
||||
; CHECK: ldr [[LIT128:s[0-9]+]], [x[[LITBASE]], {{#?}}:lo12:[[CURLIT]]]
|
||||
; CHECK-NOFP-NOT: ldr {{s[0-9]+}},
|
||||
|
||||
; CHECK-TINY: adr x[[LITBASE:[0-9]+]], [[CURLIT:.LCPI[0-9]+_[0-9]+]]
|
||||
; CHECK-TINY: ldr [[LIT128:s[0-9]+]], [x[[LITBASE]]]
|
||||
; CHECK-TINY: ldr [[LIT128:s[0-9]+]], [[CURLIT:.LCPI[0-9]+_[0-9]+]]
|
||||
; CHECK-NOFP-TINY-NOT: ldr {{s[0-9]+}},
|
||||
|
||||
; CHECK-LARGE: movz x[[LITADDR:[0-9]+]], #:abs_g0_nc:[[CURLIT:.LCPI[0-9]+_[0-9]+]]
|
||||
@ -39,8 +38,7 @@ define void @floating_lits() {
|
||||
; CHECK-NOFP-NOT: ldr {{d[0-9]+}},
|
||||
; CHECK-NOFP-NOT: fadd
|
||||
|
||||
; CHECK-TINY: adr x[[LITBASE:[0-9]+]], [[CURLIT:.LCPI[0-9]+_[0-9]+]]
|
||||
; CHECK-TINY: ldr [[LIT129:d[0-9]+]], [x[[LITBASE]]]
|
||||
; CHECK-TINY: ldr [[LIT129:d[0-9]+]], [[CURLIT:.LCPI[0-9]+_[0-9]+]]
|
||||
; CHECK-NOFP-TINY-NOT: ldr {{d[0-9]+}},
|
||||
; CHECK-NOFP-TINY-NOT: fadd
|
||||
|
||||
|
@ -89,9 +89,8 @@ define void @foo3() {
|
||||
; CHECK-LABEL: foo3:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: adr x8, src
|
||||
; CHECK-NEXT: adr x9, ptr
|
||||
; CHECK-NEXT: ldrb w8, [x8]
|
||||
; CHECK-NEXT: ldr x9, [x9]
|
||||
; CHECK-NEXT: ldr x9, ptr
|
||||
; CHECK-NEXT: strb w8, [x9]
|
||||
; CHECK-NEXT: ret
|
||||
;
|
||||
@ -209,9 +208,8 @@ define void @bar3() {
|
||||
; CHECK-LABEL: bar3:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: adr x8, lsrc
|
||||
; CHECK-NEXT: adr x9, lptr
|
||||
; CHECK-NEXT: ldrb w8, [x8]
|
||||
; CHECK-NEXT: ldr x9, [x9]
|
||||
; CHECK-NEXT: ldr x9, lptr
|
||||
; CHECK-NEXT: strb w8, [x9]
|
||||
; CHECK-NEXT: ret
|
||||
;
|
||||
@ -227,9 +225,8 @@ define void @bar3() {
|
||||
; CHECK-PIC-LABEL: bar3:
|
||||
; CHECK-PIC: // %bb.0: // %entry
|
||||
; CHECK-PIC-NEXT: adr x8, lsrc
|
||||
; CHECK-PIC-NEXT: adr x9, lptr
|
||||
; CHECK-PIC-NEXT: ldrb w8, [x8]
|
||||
; CHECK-PIC-NEXT: ldr x9, [x9]
|
||||
; CHECK-PIC-NEXT: ldr x9, lptr
|
||||
; CHECK-PIC-NEXT: strb w8, [x9]
|
||||
; CHECK-PIC-NEXT: ret
|
||||
;
|
||||
@ -329,9 +326,8 @@ define void @baz3() {
|
||||
; CHECK-LABEL: baz3:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: adr x8, lbsrc
|
||||
; CHECK-NEXT: adr x9, lptr
|
||||
; CHECK-NEXT: ldrb w8, [x8]
|
||||
; CHECK-NEXT: ldr x9, [x9]
|
||||
; CHECK-NEXT: ldr x9, lptr
|
||||
; CHECK-NEXT: strb w8, [x9]
|
||||
; CHECK-NEXT: ret
|
||||
;
|
||||
@ -347,9 +343,8 @@ define void @baz3() {
|
||||
; CHECK-PIC-LABEL: baz3:
|
||||
; CHECK-PIC: // %bb.0: // %entry
|
||||
; CHECK-PIC-NEXT: adr x8, lbsrc
|
||||
; CHECK-PIC-NEXT: adr x9, lptr
|
||||
; CHECK-PIC-NEXT: ldrb w8, [x8]
|
||||
; CHECK-PIC-NEXT: ldr x9, [x9]
|
||||
; CHECK-PIC-NEXT: ldr x9, lptr
|
||||
; CHECK-PIC-NEXT: strb w8, [x9]
|
||||
; CHECK-PIC-NEXT: ret
|
||||
;
|
||||
|
Loading…
Reference in New Issue
Block a user