llvm/llvm/test/CodeGen/ARM/ha-alignstack-call.ll

; RUN: llc --mtriple=armv7-eabihf %s -o - | FileCheck %s --enable-var-scope 

%struct.S0 = type { [4 x float] }
%struct.S1 = type { [2 x float] }
%struct.S2 = type { [4 x float] }
%struct.D0 = type { [2 x double] }
%struct.D1 = type { [2 x double] }
%struct.D2 = type { [4 x double] }

; pass in regs
declare dso_local float @f0_0(double, double, double, double, double, double, %struct.S0) local_unnamed_addr #0
define dso_local float @f0_0_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f0_0(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, %struct.S0 { [4 x float] [float 0x3FE3333340000000, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f0_0_call:
; CHECK:       vldr s12, .L[[L:.*]]
; CHECK:       b    f0_0
; CHECK:      .L[[L]]:
; CHECK-NEXT: .long 0x3f19999a

; pass in memory, no split
declare dso_local float @f0_1(double, double, double, double, double, double, float, %struct.S0) local_unnamed_addr #0
define dso_local float @f0_1_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f0_1(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, float 0x3FE3333340000000, %struct.S0 { [4 x float] [float 0x3FE6666660000000, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f0_1_call:
; CHECK:       movw r1, #13107
; CHECK:       mov  r0, #0
; CHECK:       movt r1, #16179
; CHECK-DAG:   str  r1, [sp]
; CHECK-DAG:   str  r0, [sp, #4]
; CHECK-DAG:   str  r0, [sp, #8]
; CHECK-DAG:   str  r0, [sp, #12]
; CHECK:       bl   f0_1

; pass memory, alignment 4
declare dso_local float @f0_2(double, double, double, double, double, double, double, double, float, %struct.S0) local_unnamed_addr #0
define dso_local float @f0_2_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f0_2(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, double 0x3FE6666666666666, float 0x3FE99999A0000000, %struct.S0 { [4 x float] [float 0x3FECCCCCC0000000, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f0_2_call:
; CHECK:       movw r1, #26214
; CHECK:       movw r2, #52429
; CHECK:       mov  r0, #0
; CHECK:       movt r1, #16230
; CHECK:       movt r2, #16204
; CHECK-DAG:   str  r2, [sp]
; CHECK-DAG:   str  r1, [sp, #4]
; CHECK-DAG:   str  r0, [sp, #8]
; CHECK-DAG:   str  r0, [sp, #12]
; CHECK-DAG:   str  r0, [sp, #16]
; CHECK:       bl       f0_2

; pass in regs
declare dso_local float @f1_0(double, double, double, double, double, double, double, %struct.S1 alignstack(8)) local_unnamed_addr #0
define dso_local float @f1_0_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f1_0(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, %struct.S1 alignstack(8) { [2 x float] [float 0x3FE6666660000000, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f1_0_call:
; CHECK-DAG:   vldr s14, .L[[L0:.*]]
; CHECK-DAG:   vldr s15, .L[[L1:.*]]
; CHECK:       b    f1_0
; CHECK:       .L[[L0]]:
; CHECK-NEXT:  .long 0x3f333333
; CHECK:       .L[[L1:.*]]:
; CHECK-NEXT:  .long 0x00000000

; pass in memory, no split
declare dso_local float @f1_1(double, double, double, double, double, double, double, float, %struct.S1 alignstack(8)) local_unnamed_addr #0
define dso_local float @f1_1_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f1_1(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, float 0x3FE6666660000000, %struct.S1 alignstack(8) { [2 x float] [float 0x3FE99999A0000000, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f1_1_call:
; CHECK:       movw r0, #52429
; CHECK:       mov  r1, #0
; CHECK:       movt r0, #16204
; CHECK-DAG:   strd r0, r1, [sp]
; CHECK:       bl   f1_1

; pass in memory, alignment 8
declare dso_local float @f1_2(double, double, double, double, double, double, double, double, float, %struct.S1 alignstack(8)) local_unnamed_addr #0
define dso_local float @f1_2_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f1_2(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, double 0x3FE6666666666666, float 0x3FE99999A0000000, %struct.S1 alignstack(8) { [2 x float] [float 0x3FECCCCCC0000000, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f1_2_call:
; CHECK-DAG:   movw  r0, #26214
; CHECK-DAG:   mov   r1, #0
; CHECK:       movt  r0, #16230
; CHECK:       strd  r0, r1, [sp, #8]
; CHECK:       movw  r0, #52429
; CHECK:       movt  r0, #16204
; CHECK-DAG:   str   r0, [sp]
; CHECK:       bl    f1_2


; pass in registers
declare dso_local float @f2_0(double, double, double, double, double, double, %struct.S2 alignstack(8)) local_unnamed_addr #0
define dso_local float @f2_0_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f2_0(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, %struct.S2 alignstack(8) { [4 x float] [float 0x3FE3333340000000, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f2_0_call:
; CHECK-DAG:   vldr     s12, .L[[L0:.*]]
; CHECK-DAG:   vldr     s13, .L[[L1:.*]]
; CHECK-DAG:   vmov.f32 s14, s13
; CHECK-DAG:   vmov.f32 s15, s13
; CHECK:       b        f2_0
; CHECK:       .L[[L0]]:
; CHECK-NEXT:  .long 0x3f19999a
; CHECK:       .L[[L1]]:
; CHECK-NEXT:  .long 0x00000000

; pass in memory, no split
declare dso_local float @f2_1(double, double, double, double, double, double, float, %struct.S2 alignstack(8)) local_unnamed_addr #0
define dso_local float @f2_1_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f2_1(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, float 0x3FE3333340000000, %struct.S2 alignstack(8) { [4 x float] [float 0x3FE6666660000000, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f2_1_call:
; CHECK:       movw  r1, #13107
; CHECK:       mov   r0, #0
; CHECK:       movt  r1, #16179
; CHECK:       str   r1, [sp]
; CHECK:       str   r0, [sp, #4]
; CHECK:       vldr  s12, .L[[L:.*]]
; CHECK:       str   r0, [sp, #8]
; CHECK:       str   r0, [sp, #12]
; CHECK:       bl    f2_1
; CHECK:       .L[[L]]:
; CHECK-NEXT:  .long    0x3f19999a

; pass in memory, alignment 8
declare dso_local float @f2_2(double, double, double, double, double, double, double, double, float, %struct.S2 alignstack(8)) local_unnamed_addr #0
define dso_local float @f2_2_call() local_unnamed_addr #0 {
entry:
  %call = tail call float @f2_2(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, double 0x3FE6666666666666, float 0x3FE99999A0000000, %struct.S2 alignstack(8) { [4 x float] [float 0x3FECCCCCC0000000, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00] }) #0
  ret float %call
}
; CHECK-LABEL: f2_2_call:
; CHECK:       mov  r0, #0
; CHECK:       movw r1, #26214
; CHECK:       str  r0, [sp, #12]
; CHECK:       str  r0, [sp, #16]
; CHECK:       movt r1, #16230
; CHECK:       str  r0, [sp, #20]
; CHECK:       movw r0, #52429
; CHECK:       movt r0, #16204
; CHECK:       str  r1, [sp, #8]
; CHECK:       str  r0, [sp]
; CHECK:       bl   f2_2

; pass in registers
declare dso_local double @g0_0(double, double, double, double, double, double, %struct.D0) local_unnamed_addr #0
define dso_local double @g0_0_call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g0_0(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, %struct.D0 { [2 x double] [double 6.000000e-01, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g0_0_call:
; CHECK:       vldr    d6, .L[[L:.*]]
; CHECK:       b    g0_0
; CHECK:       .L[[L]]
; CHECK-NEXT:  long 858993459
; CHECK-NEXT:  long 1071854387

; pass in memory, no split
declare dso_local double @g0_1(double, double, double, double, double, double, double, %struct.D0) local_unnamed_addr #0
define dso_local double @g0_1_call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g0_1(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, %struct.D0 { [2 x double] [double 0x3FE6666666666666, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g0_1_call:
; CHECK:       movw  r0, #26214
; CHECK:       movw  r1, #26214
; CHECK:       mov   r2, #0
; CHECK:       movt  r0, #16358
; CHECK:       movt  r1, #26214
; CHECK:       str   r1, [sp]
; CHECK:       stmib sp, {r0, r2}
; CHECK:       str   r2, [sp, #12]
; CHECK:       bl    g0_1

; pass in memory, alignment 8
declare dso_local double @g0_2(double, double, double, double, double, double, double, double, float, %struct.D0) local_unnamed_addr #0
define dso_local double @g0_2_call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g0_2(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, double 0x3FE6666666666666, float 0x3FE99999A0000000, %struct.D0 { [2 x double] [double 9.000000e-01, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g0_2_call:
; CHECK:       movw r0, #52428
; CHECK:       movt r0, #16364
; CHECK:       movw r1, #52429
; CHECK:       str  r0, [sp, #12]
; CHECK:       movw r0, #52429
; CHECK:       mov  r2, #0
; CHECK:       movt r1, #52428
; CHECK:       movt r0, #16204
; CHECK:       str  r1, [sp, #8]
; CHECK:       str  r2, [sp, #16]
; CHECK:       str  r2, [sp, #20]
; CHECK:       str  r0, [sp]
; CHECK:       bl   g0_2

; pass in registers
declare dso_local double @g1_0(double, double, double, double, double, double, %struct.D1 alignstack(8)) local_unnamed_addr #0
define dso_local double @g1_0_call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g1_0(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, %struct.D1 alignstack(8) { [2 x double] [double 6.000000e-01, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g1_0_call:
; CHECK-DAG:   vmov.i32 d7, #0x0
; CHECK-DAG:   vldr     d6, .L[[L:.*]]
; CHECK:       b        g1_0
; CHECK:      .L[[L]]:
; CHECK-NEXT: .long    858993459
; CHECK-NEXT: .long    107185438

; pass in memory, no split
declare dso_local double @g1_1(double, double, double, double, double, double, double, %struct.D1 alignstack(8)) local_unnamed_addr #0
define dso_local double @g1_1_call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g1_1(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, %struct.D1 alignstack(8) { [2 x double] [double 0x3FE6666666666666, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g1_1_call:
; CHECK:       movw  r0, #26214
; CHECK:       movw  r1, #26214
; CHECK:       mov   r2, #0
; CHECK:       movt  r0, #16358
; CHECK:       movt  r1, #26214
; CHECK:       str   r1, [sp]
; CHECK:       stmib sp, {r0, r2}
; CHECK:       str   r2, [sp, #12]
; CHECK:       bl    g1_1

; pass in memory, alignment 8
declare dso_local double @g1_2(double, double, double, double, double, double, double, double, float, %struct.D1 alignstack(8)) local_unnamed_addr #0
define dso_local double @g1_2_call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g1_2(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, double 0x3FE6666666666666, float 0x3FE99999A0000000, %struct.D1 alignstack(8) { [2 x double] [double 9.000000e-01, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g1_2_call:
; CHECK:       movw r0, #52428
; CHECK:       movt r0, #16364
; CHECK:       movw r1, #52429
; CHECK:       str  r0, [sp, #12]
; CHECK:       movw r0, #52429
; CHECK:       mov  r2, #0
; CHECK:       movt r1, #52428
; CHECK:       movt r0, #16204
; CHECK:       str  r1, [sp, #8]
; CHECK:       str  r2, [sp, #16]
; CHECK:       str  r2, [sp, #20]
; CHECK:       str  r0, [sp]
; CHECK:       bl   g1_2

; pass in registers
declare dso_local double @g2_0(double, double, double, double, %struct.D2 alignstack(8)) local_unnamed_addr #0
define dso_local double @g2_0_call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g2_0(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, %struct.D2 alignstack(8) { [4 x double] [double 4.000000e-01, double 0.000000e+00, double 0.000000e+00, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g2_0_call:
; CHECK-DAG:   vldr     d4, .L[[L:.*]]
; CHECK-DAG:   vmov.i32 d5, #0x0
; CHECK-DAG:   vmov.i32 d6, #0x0
; CHECK-DAG:   vmov.i32 d7, #0x0
; CHECK:       b        g2_0
; CHECK:       .L[[L]]:
; CHECK-NEXT:  .long    2576980378
; CHECK-NEXT:  .long    1071225241

; pass in memory, no split
; [sp] [sp + 4] =  0x00000000 0x3fe00000 = .5
; [sp + 8] [sp + 12] = 0 0 = .0
; ...
declare dso_local double @g2_1(double, double, double, double, double, %struct.D2 alignstack(8)) local_unnamed_addr #0
define dso_local double @g2_1_call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g2_1(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, %struct.D2 alignstack(8) { [4 x double] [double 5.000000e-01, double 0.000000e+00, double 0.000000e+00, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g2_1_call:
; CHECK:       vmov.f64 d16, #5.000000e-01
; CHECK:       mov    r0, #0
; CHECK:       str    r0, [sp, #8]
; CHECK:       str    r0, [sp, #12]
; CHECK:       str    r0, [sp, #16]
; CHECK:       vmov.i32 d0, #0x0
; CHECK:       str    r0, [sp, #20]
; CHECK:       str    r0, [sp, #24]
; CHECK:       str    r0, [sp, #28]
; CHECK:       vstr   d16, [sp]
; CHECK:       bl    g2_1

; pass in memory, alignment 8
declare dso_local double @g2_2(double, double, double, double, double, double, double, double, float, %struct.D2 alignstack(8)) local_unnamed_addr #0
define dso_local double @g2_2call() local_unnamed_addr #0 {
entry:
  %call = tail call double @g2_2(double 0.000000e+00, double 1.000000e-01, double 2.000000e-01, double 3.000000e-01, double 4.000000e-01, double 5.000000e-01, double 6.000000e-01, double 0x3FE6666666666666, float 0x3FE99999A0000000, %struct.D2 alignstack(8) { [4 x double] [double 9.000000e-01, double 0.000000e+00, double 0.000000e+00, double 0.000000e+00] }) #0
  ret double %call
}
; CHECK-LABEL: g2_2call:
; CHECK:       movw r0, #52428
; CHECK:       movt r0, #16364
; CHECK:       movw r1, #52429
; CHECK:       str  r0, [sp, #12]
; CHECK:       movw r0, #52429
; CHECK:       mov  r2, #0
; CHECK:       movt r1, #52428
; CHECK:       movt r0, #16204
; CHECK:       str  r1, [sp, #8]
; CHECK:       str  r2, [sp, #16]
; CHECK:       str  r2, [sp, #20]
; CHECK:       str  r2, [sp, #24]
; CHECK:       str  r2, [sp, #28]
; CHECK:       str  r2, [sp, #32]
; CHECK:       str  r2, [sp, #36]
; CHECK:       str  r0, [sp]
; CHECK:       bl   g2_2

attributes #0 = { nounwind "target-cpu"="generic" "target-features"="+armv7-a,+d32,+dsp,+fp64,+neon,+strict-align,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,-thumb-mode" }