| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDISEL |
| ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny -fast-isel < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST |
| ; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -code-model=tiny -global-isel < %s | FileCheck %s --check-prefix=CHECK-GLOBISEL |
| |
| ; Note fast-isel tests here will fall back to isel |
| |
| @src = external local_unnamed_addr global [65536 x i8], align 1 |
| @dst = external global [65536 x i8], align 1 |
| @ptr = external local_unnamed_addr global ptr, align 8 |
| |
| define dso_local void @foo1() { |
| ; CHECK-LABEL: foo1: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr x8, :got:src |
| ; CHECK-NEXT: ldrb w8, [x8] |
| ; CHECK-NEXT: ldr x9, :got:dst |
| ; CHECK-NEXT: strb w8, [x9] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: foo1: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: ldr x8, :got:src |
| ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8] |
| ; CHECK-GLOBISEL-NEXT: ldr x9, :got:dst |
| ; CHECK-GLOBISEL-NEXT: strb w8, [x9] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| %0 = load i8, ptr @src, align 1 |
| store i8 %0, ptr @dst, align 1 |
| ret void |
| } |
| |
| define dso_local void @foo2() { |
| ; CHECK-LABEL: foo2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr x8, :got:ptr |
| ; CHECK-NEXT: ldr x9, :got:dst |
| ; CHECK-NEXT: str x9, [x8] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: foo2: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: ldr x8, :got:ptr |
| ; CHECK-GLOBISEL-NEXT: ldr x9, :got:dst |
| ; CHECK-GLOBISEL-NEXT: str x9, [x8] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| store ptr @dst, ptr @ptr, align 8 |
| ret void |
| } |
| |
| define dso_local void @foo3() { |
| ; FIXME: Needn't adr ptr |
| ; |
| ; CHECK-LABEL: foo3: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr x8, :got:src |
| ; CHECK-NEXT: ldr x9, :got:ptr |
| ; CHECK-NEXT: ldrb w8, [x8] |
| ; CHECK-NEXT: ldr x9, [x9] |
| ; CHECK-NEXT: strb w8, [x9] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: foo3: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: ldr x8, :got:src |
| ; CHECK-GLOBISEL-NEXT: ldr x9, :got:ptr |
| ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8] |
| ; CHECK-GLOBISEL-NEXT: ldr x9, [x9] |
| ; CHECK-GLOBISEL-NEXT: strb w8, [x9] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| %0 = load i8, ptr @src, align 1 |
| %1 = load ptr, ptr @ptr, align 8 |
| store i8 %0, ptr %1, align 1 |
| ret void |
| } |
| |
| @lsrc = internal global i8 0, align 4 |
| @ldst = internal global i8 0, align 4 |
| @lptr = internal global ptr null, align 8 |
| |
| define dso_local void @bar1() { |
| ; CHECK-LABEL: bar1: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: adr x8, lsrc |
| ; CHECK-NEXT: adr x9, ldst |
| ; CHECK-NEXT: ldrb w8, [x8] |
| ; CHECK-NEXT: strb w8, [x9] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: bar1: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: adr x8, lsrc |
| ; CHECK-GLOBISEL-NEXT: adr x9, ldst |
| ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8] |
| ; CHECK-GLOBISEL-NEXT: strb w8, [x9] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| %0 = load i8, ptr @lsrc, align 4 |
| store i8 %0, ptr @ldst, align 4 |
| ret void |
| } |
| |
| define dso_local void @bar2() { |
| ; CHECK-LABEL: bar2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: adr x8, lptr |
| ; CHECK-NEXT: adr x9, ldst |
| ; CHECK-NEXT: str x9, [x8] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: bar2: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: adr x8, lptr |
| ; CHECK-GLOBISEL-NEXT: adr x9, ldst |
| ; CHECK-GLOBISEL-NEXT: str x9, [x8] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| store ptr @ldst, ptr @lptr, align 8 |
| ret void |
| } |
| |
| define dso_local void @bar3() { |
| ; FIXME: Needn't adr lptr |
| ; |
| ; CHECK-LABEL: bar3: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: adr x8, lsrc |
| ; CHECK-NEXT: ldr x9, lptr |
| ; CHECK-NEXT: ldrb w8, [x8] |
| ; CHECK-NEXT: strb w8, [x9] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: bar3: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: adr x8, lsrc |
| ; CHECK-GLOBISEL-NEXT: adr x9, lptr |
| ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8] |
| ; CHECK-GLOBISEL-NEXT: ldr x9, [x9] |
| ; CHECK-GLOBISEL-NEXT: strb w8, [x9] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| %0 = load i8, ptr @lsrc, align 4 |
| %1 = load ptr, ptr @lptr, align 8 |
| store i8 %0, ptr %1, align 1 |
| ret void |
| } |
| |
| |
| @lbsrc = internal global [65536 x i8] zeroinitializer, align 4 |
| @lbdst = internal global [65536 x i8] zeroinitializer, align 4 |
| |
| define dso_local void @baz1() { |
| ; CHECK-LABEL: baz1: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: adr x8, lbsrc |
| ; CHECK-NEXT: adr x9, lbdst |
| ; CHECK-NEXT: ldrb w8, [x8] |
| ; CHECK-NEXT: strb w8, [x9] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: baz1: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: adr x8, lbsrc |
| ; CHECK-GLOBISEL-NEXT: adr x9, lbdst |
| ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8] |
| ; CHECK-GLOBISEL-NEXT: strb w8, [x9] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| %0 = load i8, ptr @lbsrc, align 4 |
| store i8 %0, ptr @lbdst, align 4 |
| ret void |
| } |
| |
| define dso_local void @baz2() { |
| ; CHECK-LABEL: baz2: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: adr x8, lptr |
| ; CHECK-NEXT: adr x9, lbdst |
| ; CHECK-NEXT: str x9, [x8] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: baz2: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: adr x8, lptr |
| ; CHECK-GLOBISEL-NEXT: adr x9, lbdst |
| ; CHECK-GLOBISEL-NEXT: str x9, [x8] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| store ptr @lbdst, ptr @lptr, align 8 |
| ret void |
| } |
| |
| define dso_local void @baz3() { |
| ; FIXME: Needn't adr lptr |
| ; |
| ; CHECK-LABEL: baz3: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: adr x8, lbsrc |
| ; CHECK-NEXT: ldr x9, lptr |
| ; CHECK-NEXT: ldrb w8, [x8] |
| ; CHECK-NEXT: strb w8, [x9] |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: baz3: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: adr x8, lbsrc |
| ; CHECK-GLOBISEL-NEXT: adr x9, lptr |
| ; CHECK-GLOBISEL-NEXT: ldrb w8, [x8] |
| ; CHECK-GLOBISEL-NEXT: ldr x9, [x9] |
| ; CHECK-GLOBISEL-NEXT: strb w8, [x9] |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| %0 = load i8, ptr @lbsrc, align 4 |
| %1 = load ptr, ptr @lptr, align 8 |
| store i8 %0, ptr %1, align 1 |
| ret void |
| } |
| |
| |
| declare void @func(...) |
| |
| define dso_local ptr @externfuncaddr() { |
| ; CHECK-LABEL: externfuncaddr: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: ldr x0, :got:func |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: externfuncaddr: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: ldr x0, :got:func |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| ret ptr @func |
| } |
| |
| define dso_local ptr @localfuncaddr() { |
| ; CHECK-LABEL: localfuncaddr: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: adr x0, externfuncaddr |
| ; CHECK-NEXT: ret |
| ; |
| ; CHECK-GLOBISEL-LABEL: localfuncaddr: |
| ; CHECK-GLOBISEL: // %bb.0: // %entry |
| ; CHECK-GLOBISEL-NEXT: adr x0, externfuncaddr |
| ; CHECK-GLOBISEL-NEXT: ret |
| entry: |
| ret ptr @externfuncaddr |
| } |
| |
| define dso_local void @stackprot(ptr %callee) sspstrong { |
| ; SDISEL-LABEL: stackprot: |
| ; SDISEL: // %bb.0: |
| ; SDISEL-NEXT: sub sp, sp, #96 |
| ; SDISEL-NEXT: str x30, [sp, #80] // 8-byte Spill |
| ; SDISEL-NEXT: .cfi_def_cfa_offset 96 |
| ; SDISEL-NEXT: .cfi_offset w30, -16 |
| ; SDISEL-NEXT: adrp x9, __stack_chk_guard |
| ; SDISEL-NEXT: mov x8, x0 |
| ; SDISEL-NEXT: add x0, sp, #8 |
| ; SDISEL-NEXT: ldr x9, [x9, :lo12:__stack_chk_guard] |
| ; SDISEL-NEXT: str x9, [sp, #72] |
| ; SDISEL-NEXT: blr x8 |
| ; SDISEL-NEXT: adrp x8, __stack_chk_guard |
| ; SDISEL-NEXT: ldr x9, [sp, #72] |
| ; SDISEL-NEXT: ldr x8, [x8, :lo12:__stack_chk_guard] |
| ; SDISEL-NEXT: cmp x8, x9 |
| ; SDISEL-NEXT: b.ne .LBB11_2 |
| ; SDISEL-NEXT: // %bb.1: |
| ; SDISEL-NEXT: ldr x30, [sp, #80] // 8-byte Reload |
| ; SDISEL-NEXT: add sp, sp, #96 |
| ; SDISEL-NEXT: ret |
| ; SDISEL-NEXT: .LBB11_2: |
| ; SDISEL-NEXT: bl __stack_chk_fail |
| ; |
| ; FAST-LABEL: stackprot: |
| ; FAST: // %bb.0: |
| ; FAST-NEXT: sub sp, sp, #96 |
| ; FAST-NEXT: str x30, [sp, #80] // 8-byte Spill |
| ; FAST-NEXT: .cfi_def_cfa_offset 96 |
| ; FAST-NEXT: .cfi_offset w30, -16 |
| ; FAST-NEXT: adrp x9, __stack_chk_guard |
| ; FAST-NEXT: mov x8, x0 |
| ; FAST-NEXT: add x0, sp, #8 |
| ; FAST-NEXT: ldr x9, [x9, :lo12:__stack_chk_guard] |
| ; FAST-NEXT: str x9, [sp, #72] |
| ; FAST-NEXT: blr x8 |
| ; FAST-NEXT: adrp x8, __stack_chk_guard |
| ; FAST-NEXT: ldr x9, [sp, #72] |
| ; FAST-NEXT: ldr x8, [x8, :lo12:__stack_chk_guard] |
| ; FAST-NEXT: cmp x8, x9 |
| ; FAST-NEXT: b.ne .LBB11_2 |
| ; FAST-NEXT: // %bb.1: // %SP_return |
| ; FAST-NEXT: ldr x30, [sp, #80] // 8-byte Reload |
| ; FAST-NEXT: add sp, sp, #96 |
| ; FAST-NEXT: ret |
| ; FAST-NEXT: .LBB11_2: // %CallStackCheckFailBlk |
| ; FAST-NEXT: bl __stack_chk_fail |
| ; |
| ; CHECK-GLOBISEL-LABEL: stackprot: |
| ; CHECK-GLOBISEL: // %bb.0: |
| ; CHECK-GLOBISEL-NEXT: sub sp, sp, #96 |
| ; CHECK-GLOBISEL-NEXT: str x30, [sp, #80] // 8-byte Spill |
| ; CHECK-GLOBISEL-NEXT: .cfi_def_cfa_offset 96 |
| ; CHECK-GLOBISEL-NEXT: .cfi_offset w30, -16 |
| ; CHECK-GLOBISEL-NEXT: adrp x9, __stack_chk_guard |
| ; CHECK-GLOBISEL-NEXT: mov x8, x0 |
| ; CHECK-GLOBISEL-NEXT: add x0, sp, #8 |
| ; CHECK-GLOBISEL-NEXT: ldr x9, [x9, :lo12:__stack_chk_guard] |
| ; CHECK-GLOBISEL-NEXT: str x9, [sp, #72] |
| ; CHECK-GLOBISEL-NEXT: blr x8 |
| ; CHECK-GLOBISEL-NEXT: adrp x8, __stack_chk_guard |
| ; CHECK-GLOBISEL-NEXT: ldr x9, [sp, #72] |
| ; CHECK-GLOBISEL-NEXT: ldr x8, [x8, :lo12:__stack_chk_guard] |
| ; CHECK-GLOBISEL-NEXT: cmp x8, x9 |
| ; CHECK-GLOBISEL-NEXT: b.ne .LBB11_2 |
| ; CHECK-GLOBISEL-NEXT: // %bb.1: |
| ; CHECK-GLOBISEL-NEXT: ldr x30, [sp, #80] // 8-byte Reload |
| ; CHECK-GLOBISEL-NEXT: add sp, sp, #96 |
| ; CHECK-GLOBISEL-NEXT: ret |
| ; CHECK-GLOBISEL-NEXT: .LBB11_2: |
| ; CHECK-GLOBISEL-NEXT: bl __stack_chk_fail |
| %arr = alloca [64 x i8], align 1 |
| call void %callee(ptr %arr) |
| ret void |
| } |