| ;; RUN: llc -mtriple aarch64 -global-isel -O0 %s -o - | FileCheck -enable-var-scope %s --check-prefixes=CHECK,CHECK-NOP |
| ;; RUN: llc -mtriple aarch64 -mattr=+v8.3a -global-isel -O0 %s -o - | FileCheck -enable-var-scope %s --check-prefixes=CHECK,CHECK-V83 |
| declare void @g0() #1 |
| declare void @g1(i8*) #1 |
| declare void @g2(i32, i8*) #1 |
| |
| declare i8* @llvm.returnaddress(i32 immarg) #2 |
| |
| define i8* @f0() #0 { |
| entry: |
| %0 = call i8* @llvm.returnaddress(i32 0) |
| call void @g1(i8* %0) |
| %1 = call i8* @llvm.returnaddress(i32 1) |
| call void @g2(i32 1, i8* %1) |
| %2 = call i8* @llvm.returnaddress(i32 2) |
| ret i8* %2 |
| } |
| ;; CHECK-LABEL: f0: |
| ;; CHECK-NOT: {{(mov|ldr)}} x30 |
| ;; CHECK-NOP: hint #7 |
| ;; CHECK-V83: mov [[COPY_X30:x[0-9]+]], x30 |
| ;; CHECK-V83: xpaci [[COPY_X30]] |
| ;; CHECK: bl g1 |
| ;; CHECK: ldr x[[T0:[0-9]+]], [x29] |
| ;; CHECK-NOP-NEXT: ldr x30, [x[[T0]], #8] |
| ;; CHECK-NOP-NEXT: hint #7 |
| ;; CHECK-V83-NEXT: ldr x[[LD0:[0-9]+]], [x[[T0]], #8] |
| ;; CHECK-V83-NEXT: xpaci x[[LD0]] |
| ;; CHECK: bl g2 |
| ;; CHECK: ldr x[[T1:[0-9]+]], [x29] |
| ;; CHECK-NEXT: ldr x[[T1]], [x[[T1]]] |
| ;; CHECK-NOP-NEXT: ldr x30, [x[[T1]], #8] |
| ;; CHECK-NOP-NEXT: hint #7 |
| ;; CHECK-NOP-NEXT: mov x0, x30 |
| ;; CHECK-V83-NEXT: ldr x0, [x[[T1]], #8] |
| ;; CHECK-V83-NEXT: xpaci x0 |
| |
| define i8* @f1() #0 { |
| entry: |
| %0 = call i8* @llvm.returnaddress(i32 1) |
| call void @g1(i8* %0) |
| %1 = call i8* @llvm.returnaddress(i32 2) |
| call void @g2(i32 1, i8* %1) |
| %2 = call i8* @llvm.returnaddress(i32 0) |
| ret i8* %2 |
| } |
| ;; CHECK-LABEL: f1: |
| ;; CHECK-DAG: ldr x[[T0:[0-9]+]], [x29] |
| ;; CHECK-NOP-DAG: str x30, [sp, #[[OFF:[0-9]+]] |
| ;; CHECK-NOP: ldr x30, [x[[T0]], #8] |
| ;; CHECK-NOP-NEXT: hint #7 |
| ;; CHECK-V83-DAG: str x30, [sp, #[[OFF:[0-9]+]] |
| ;; CHECK-V83: ldr x[[T1:[0-9]+]], [x[[T0]], #8] |
| ;; CHECK-V83-NEXT: xpaci x[[T1]] |
| |
| ;; CHECK: bl g1 |
| ;; CHECK: ldr x[[T2:[0-9]+]], [x29] |
| ;; CHECK-NEXT: ldr x[[T2]], [x[[T2]]] |
| ;; CHECK-NOP-NEXT: ldr x30, [x[[T2]], #8] |
| ;; CHECK-NOP-NEXT: hint #7 |
| ;; CHECK-V83-NEXT: ldr x[[T3:[0-9]+]], [x[[T2]], #8] |
| ;; CHECK-V83-NEXT: xpaci x[[T3]] |
| ;; CHECK: bl g2 |
| |
| ;; CHECK-NOP: ldr x30, [sp, #[[OFF]]] |
| ;; CHECK-NOP-NEXT: hint #7 |
| ;; CHECK-NOP-NEXT: mov x0, x30 |
| |
| ;; CHECK-V83: ldr x0, [sp, #[[OFF]]] |
| ;; CHECK-V83-NEXT: xpaci x0 |
| ;; CHECK-NOT: x0 |
| ;; CHECK: ret |
| |
| define i8* @f2() #0 { |
| entry: |
| call void bitcast (void ()* @g0 to void ()*)() |
| %0 = call i8* @llvm.returnaddress(i32 0) |
| ret i8* %0 |
| } |
| ;; CHECK-LABEL: f2 |
| ;; CHECK: bl g0 |
| ;; CHECK-NOP: ldr x30, [sp, |
| ;; CHECK-NOP-NEXT: hint #7 |
| ;; CHECK-NOP-NEXT: mov x0, x30 |
| |
| ;; CHECK-V83: ldr x0, [sp, |
| ;; CHECK-V83-NEXT: xpaci x0 |
| ;; CHECK-NOT: x0 |
| ;; CHECK: ret |
| |
| define i8* @f3() #0 { |
| entry: |
| %0 = call i8* @llvm.returnaddress(i32 0) |
| ret i8* %0 |
| } |
| ;; CHECK-LABEL: f3: |
| ;; CHECK-NOP: str x30, [sp, |
| ;; CHECK-NOP-NEXT: hint #7 |
| ;; CHECK-NOP-NEXT: mov x0, x30 |
| |
| ;; CHECK-V83: mov x0, x30 |
| ;; CHECK-V83-NEXT: xpaci x0 |
| ;; CHECK-NOT: x0 |
| ;; CHECK: ret |
| attributes #0 = { nounwind } |
| attributes #1 = { nounwind } |
| attributes #2 = { nounwind readnone } |