Index: lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- lib/Target/AArch64/AArch64InstrFormats.td +++ lib/Target/AArch64/AArch64InstrFormats.td @@ -2853,10 +2853,10 @@ let OperandType = "OPERAND_PCREL"; } -let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in -class LoadLiteral opc, bit V, RegisterOperand regtype, string asm> +let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in +class LoadLiteral opc, bit V, RegisterOperand regtype, string asm, list 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; Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -1891,14 +1891,51 @@ //--- // (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 alignedAArch64adr : PatFrag<(ops node:$ptr), (AArch64adr node:$ptr), [{ + SDValue Base = N->getOperand(0); + if (auto *G = dyn_cast(Base.getNode())) { + unsigned Align = G->getGlobal()->getAlignment(); + if (auto *GV = dyn_cast(G->getGlobal())) + Align = MF->getDataLayout().getPreferredAlignment(GV); + return Align >= 4 && G->getOffset() % 4 == 0; + } + if (auto *C = dyn_cast(Base.getNode())) + return C->getAlignment() >= 4 && C->getOffset() % 4 == 0; + return false; +}]>; + +def LDRWl : LoadLiteral<0b00, 0, GPR32z, "ldr", + [(set GPR32z:$Rt, (load (alignedAArch64adr tconstpool:$label)))]>; +def LDRXl : LoadLiteral<0b01, 0, GPR64z, "ldr", + [(set GPR64z:$Rt, (load (alignedAArch64adr tconstpool:$label)))]>; +def LDRSl : LoadLiteral<0b00, 1, FPR32Op, "ldr", + [(set (f32 FPR32Op:$Rt), (load (alignedAArch64adr tconstpool:$label)))]>; +def LDRDl : LoadLiteral<0b01, 1, FPR64Op, "ldr", + [(set (f64 FPR64Op:$Rt), (load (alignedAArch64adr tconstpool:$label)))]>; +def LDRQl : LoadLiteral<0b10, 1, FPR128Op, "ldr", + [(set (f128 FPR128Op:$Rt), (load (alignedAArch64adr tconstpool:$label)))]>; // load sign-extended word -def LDRSWl : LoadLiteral<0b10, 0, GPR64z, "ldrsw">; +def LDRSWl : LoadLiteral<0b10, 0, GPR64z, "ldrsw", + [(set GPR64z:$Rt, (zextloadi32 (alignedAArch64adr tconstpool:$label)))]>; + +let AddedComplexity = 20 in { +def : Pat<(i32 (load (alignedAArch64adr tglobaladdr:$label))), + (LDRWl tglobaladdr:$label)>; +def : Pat<(i64 (load (alignedAArch64adr tglobaladdr:$label))), + (LDRXl tglobaladdr:$label)>; +def : Pat<(f32 (load (alignedAArch64adr tglobaladdr:$label))), + (LDRSl tglobaladdr:$label)>; +def : Pat<(f64 (load (alignedAArch64adr tglobaladdr:$label))), + (LDRDl tglobaladdr:$label)>; +def : Pat<(f128 (load (alignedAArch64adr tglobaladdr:$label))), + (LDRQl tglobaladdr:$label)>; +def : Pat<(i64 (sextloadi32 (alignedAArch64adr tglobaladdr:$label))), + (LDRSWl tglobaladdr:$label)>; +def : Pat<(i64 (zextloadi32 (alignedAArch64adr tglobaladdr:$label))), + (SUBREG_TO_REG (i64 0), (LDRWl tglobaladdr:$label), sub_32)>; +} // prefetch def PRFMl : PrefetchLiteral<0b11, 0, "prfm", []>; Index: test/CodeGen/AArch64/code-model-tiny-abs.ll =================================================================== --- test/CodeGen/AArch64/code-model-tiny-abs.ll +++ test/CodeGen/AArch64/code-model-tiny-abs.ll @@ -33,16 +33,14 @@ ; 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() { Index: test/CodeGen/AArch64/fpimm.ll =================================================================== --- test/CodeGen/AArch64/fpimm.ll +++ test/CodeGen/AArch64/fpimm.ll @@ -19,7 +19,7 @@ %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 @@ %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 @@ ; 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 @@ ; 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 } Index: test/CodeGen/AArch64/ldradr.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/ldradr.ll @@ -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 +} + Index: test/CodeGen/AArch64/literal_pools_float.ll =================================================================== --- test/CodeGen/AArch64/literal_pools_float.ll +++ test/CodeGen/AArch64/literal_pools_float.ll @@ -17,8 +17,7 @@ ; 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 @@ ; 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 Index: test/CodeGen/AArch64/tiny_model.ll =================================================================== --- test/CodeGen/AArch64/tiny_model.ll +++ test/CodeGen/AArch64/tiny_model.ll @@ -89,9 +89,8 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 ;