| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s --check-prefixes=CHECK,CHECK-SD |
| ; RUN: llc < %s -mtriple=arm64-eabi -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI |
| |
| %struct.A = type { i8 } |
| %struct.B = type { i32 } |
| %struct.C = type { %struct.B } |
| %struct.D = type { %struct.B } |
| %struct.E = type { %struct.B, %struct.B } |
| |
| declare ptr @A_ctor_base(ptr returned) |
| declare ptr @B_ctor_base(ptr returned, i32) |
| declare ptr @B_ctor_complete(ptr returned, i32) |
| |
| declare ptr @A_ctor_base_nothisret(ptr) |
| declare ptr @B_ctor_base_nothisret(ptr, i32) |
| declare ptr @B_ctor_complete_nothisret(ptr, i32) |
| |
| define ptr @C_ctor_base(ptr returned %this, i32 %x) { |
| ; CHECK-LABEL: C_ctor_base: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| ; CHECK-NEXT: .cfi_offset w19, -8 |
| ; CHECK-NEXT: .cfi_offset w30, -16 |
| ; CHECK-NEXT: mov w19, w1 |
| ; CHECK-NEXT: bl A_ctor_base |
| ; CHECK-NEXT: mov w1, w19 |
| ; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload |
| ; CHECK-NEXT: b B_ctor_base |
| entry: |
| %call = tail call ptr @A_ctor_base(ptr returned %this) |
| %call2 = tail call ptr @B_ctor_base(ptr returned %this, i32 %x) |
| ret ptr %this |
| } |
| |
| define ptr @C_ctor_base_nothisret(ptr %this, i32 %x) { |
| ; CHECK-SD-LABEL: C_ctor_base_nothisret: |
| ; CHECK-SD: // %bb.0: // %entry |
| ; CHECK-SD-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill |
| ; CHECK-SD-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill |
| ; CHECK-SD-NEXT: .cfi_def_cfa_offset 32 |
| ; CHECK-SD-NEXT: .cfi_offset w19, -8 |
| ; CHECK-SD-NEXT: .cfi_offset w20, -16 |
| ; CHECK-SD-NEXT: .cfi_offset w30, -32 |
| ; CHECK-SD-NEXT: mov w19, w1 |
| ; CHECK-SD-NEXT: mov x20, x0 |
| ; CHECK-SD-NEXT: bl A_ctor_base_nothisret |
| ; CHECK-SD-NEXT: mov x0, x20 |
| ; CHECK-SD-NEXT: mov w1, w19 |
| ; CHECK-SD-NEXT: bl B_ctor_base_nothisret |
| ; CHECK-SD-NEXT: mov x0, x20 |
| ; CHECK-SD-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload |
| ; CHECK-SD-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload |
| ; CHECK-SD-NEXT: ret |
| ; |
| ; CHECK-GI-LABEL: C_ctor_base_nothisret: |
| ; CHECK-GI: // %bb.0: // %entry |
| ; CHECK-GI-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill |
| ; CHECK-GI-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill |
| ; CHECK-GI-NEXT: .cfi_def_cfa_offset 32 |
| ; CHECK-GI-NEXT: .cfi_offset w19, -8 |
| ; CHECK-GI-NEXT: .cfi_offset w20, -16 |
| ; CHECK-GI-NEXT: .cfi_offset w30, -32 |
| ; CHECK-GI-NEXT: mov x19, x0 |
| ; CHECK-GI-NEXT: mov w20, w1 |
| ; CHECK-GI-NEXT: bl A_ctor_base_nothisret |
| ; CHECK-GI-NEXT: mov x0, x19 |
| ; CHECK-GI-NEXT: mov w1, w20 |
| ; CHECK-GI-NEXT: bl B_ctor_base_nothisret |
| ; CHECK-GI-NEXT: mov x0, x19 |
| ; CHECK-GI-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload |
| ; CHECK-GI-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload |
| ; CHECK-GI-NEXT: ret |
| entry: |
| %call = tail call ptr @A_ctor_base_nothisret(ptr %this) |
| %call2 = tail call ptr @B_ctor_base_nothisret(ptr %this, i32 %x) |
| ret ptr %this |
| } |
| |
| define ptr @C_ctor_complete(ptr %this, i32 %x) { |
| ; CHECK-LABEL: C_ctor_complete: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: b C_ctor_base |
| entry: |
| %call = tail call ptr @C_ctor_base(ptr returned %this, i32 %x) |
| ret ptr %this |
| } |
| |
| define ptr @C_ctor_complete_nothisret(ptr %this, i32 %x) { |
| ; CHECK-LABEL: C_ctor_complete_nothisret: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| ; CHECK-NEXT: .cfi_offset w19, -8 |
| ; CHECK-NEXT: .cfi_offset w30, -16 |
| ; CHECK-NEXT: mov x19, x0 |
| ; CHECK-NEXT: bl C_ctor_base_nothisret |
| ; CHECK-NEXT: mov x0, x19 |
| ; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload |
| ; CHECK-NEXT: ret |
| entry: |
| %call = tail call ptr @C_ctor_base_nothisret(ptr %this, i32 %x) |
| ret ptr %this |
| } |
| |
| define ptr @D_ctor_base(ptr %this, i32 %x) { |
| ; CHECK-LABEL: D_ctor_base: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 |
| ; CHECK-NEXT: .cfi_offset w19, -8 |
| ; CHECK-NEXT: .cfi_offset w30, -16 |
| ; CHECK-NEXT: mov w19, w1 |
| ; CHECK-NEXT: bl B_ctor_complete |
| ; CHECK-NEXT: mov w1, w19 |
| ; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload |
| ; CHECK-NEXT: b B_ctor_complete |
| entry: |
| %call = tail call ptr @B_ctor_complete(ptr returned %this, i32 %x) |
| %call2 = tail call ptr @B_ctor_complete(ptr returned %this, i32 %x) |
| ret ptr %this |
| } |
| |
| define ptr @E_ctor_base(ptr %this, i32 %x) { |
| ; CHECK-SD-LABEL: E_ctor_base: |
| ; CHECK-SD: // %bb.0: // %entry |
| ; CHECK-SD-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill |
| ; CHECK-SD-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill |
| ; CHECK-SD-NEXT: .cfi_def_cfa_offset 32 |
| ; CHECK-SD-NEXT: .cfi_offset w19, -8 |
| ; CHECK-SD-NEXT: .cfi_offset w20, -16 |
| ; CHECK-SD-NEXT: .cfi_offset w30, -32 |
| ; CHECK-SD-NEXT: mov w19, w1 |
| ; CHECK-SD-NEXT: mov x20, x0 |
| ; CHECK-SD-NEXT: bl B_ctor_complete |
| ; CHECK-SD-NEXT: add x0, x0, #4 |
| ; CHECK-SD-NEXT: mov w1, w19 |
| ; CHECK-SD-NEXT: bl B_ctor_complete |
| ; CHECK-SD-NEXT: mov x0, x20 |
| ; CHECK-SD-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload |
| ; CHECK-SD-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload |
| ; CHECK-SD-NEXT: ret |
| ; |
| ; CHECK-GI-LABEL: E_ctor_base: |
| ; CHECK-GI: // %bb.0: // %entry |
| ; CHECK-GI-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill |
| ; CHECK-GI-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill |
| ; CHECK-GI-NEXT: .cfi_def_cfa_offset 32 |
| ; CHECK-GI-NEXT: .cfi_offset w19, -8 |
| ; CHECK-GI-NEXT: .cfi_offset w20, -16 |
| ; CHECK-GI-NEXT: .cfi_offset w30, -32 |
| ; CHECK-GI-NEXT: mov x19, x0 |
| ; CHECK-GI-NEXT: mov w20, w1 |
| ; CHECK-GI-NEXT: bl B_ctor_complete |
| ; CHECK-GI-NEXT: add x0, x0, #4 |
| ; CHECK-GI-NEXT: mov w1, w20 |
| ; CHECK-GI-NEXT: bl B_ctor_complete |
| ; CHECK-GI-NEXT: mov x0, x19 |
| ; CHECK-GI-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload |
| ; CHECK-GI-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload |
| ; CHECK-GI-NEXT: ret |
| entry: |
| %call = tail call ptr @B_ctor_complete(ptr returned %this, i32 %x) |
| %b2 = getelementptr inbounds %struct.E, ptr %this, i32 0, i32 1 |
| %call2 = tail call ptr @B_ctor_complete(ptr returned %b2, i32 %x) |
| ret ptr %this |
| } |