Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc     -mtriple=arm64-apple-darwin -mcpu=cyclone -enable-misched=false < %s | FileCheck %s
      2 ; RUN: llc -O0 -fast-isel -mtriple=arm64-apple-darwin                          < %s | FileCheck --check-prefix=FAST %s
      3 
      4 ; rdar://9932559
      5 define i64 @i8i16callee(i64 %a1, i64 %a2, i64 %a3, i8 signext %a4, i16 signext %a5, i64 %a6, i64 %a7, i64 %a8, i8 signext %b1, i16 signext %b2, i8 signext %b3, i8 signext %b4) nounwind readnone noinline {
      6 entry:
      7 ; CHECK-LABEL: i8i16callee:
      8 ; The 8th, 9th, 10th and 11th arguments are passed at sp, sp+2, sp+4, sp+5.
      9 ; They are i8, i16, i8 and i8.
     10 ; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp, #5]
     11 ; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp, #4]
     12 ; CHECK-DAG: ldrsh {{w[0-9]+}}, [sp, #2]
     13 ; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp]
     14 ; FAST-LABEL: i8i16callee:
     15 ; FAST-DAG: ldrsb  {{w[0-9]+}}, [sp, #5]
     16 ; FAST-DAG: ldrsb  {{w[0-9]+}}, [sp, #4]
     17 ; FAST-DAG: ldrsh  {{w[0-9]+}}, [sp, #2]
     18 ; FAST-DAG: ldrsb  {{w[0-9]+}}, [sp]
     19   %conv = sext i8 %a4 to i64
     20   %conv3 = sext i16 %a5 to i64
     21   %conv8 = sext i8 %b1 to i64
     22   %conv9 = sext i16 %b2 to i64
     23   %conv11 = sext i8 %b3 to i64
     24   %conv13 = sext i8 %b4 to i64
     25   %add10 = add i64 %a2, %a1
     26   %add12 = add i64 %add10, %a3
     27   %add14 = add i64 %add12, %conv
     28   %add = add i64 %add14, %conv3
     29   %add1 = add i64 %add, %a6
     30   %add2 = add i64 %add1, %a7
     31   %add4 = add i64 %add2, %a8
     32   %add5 = add i64 %add4, %conv8
     33   %add6 = add i64 %add5, %conv9
     34   %add7 = add i64 %add6, %conv11
     35   %add15 = add i64 %add7, %conv13
     36   %sext = shl i64 %add15, 32
     37   %conv17 = ashr exact i64 %sext, 32
     38   ret i64 %conv17
     39 }
     40 
     41 define i32 @i8i16caller() nounwind readnone {
     42 entry:
     43 ; CHECK-LABEL: i8i16caller
     44 ; The 8th, 9th, 10th and 11th arguments are passed at sp, sp+2, sp+4, sp+5.
     45 ; They are i8, i16, i8 and i8.
     46 ; CHECK-DAG: stur {{w[0-9]+}}, [sp, #2]
     47 ; CHECK-DAG: strb {{w[0-9]+}}, [sp]
     48 ; CHECK: bl
     49 ; FAST-LABEL: i8i16caller
     50 ; FAST: strb {{w[0-9]+}}, [sp]
     51 ; FAST: strh {{w[0-9]+}}, [sp, #2]
     52 ; FAST: strb {{w[0-9]+}}, [sp, #4]
     53 ; FAST: strb {{w[0-9]+}}, [sp, #5]
     54 ; FAST: bl
     55   %call = tail call i64 @i8i16callee(i64 0, i64 1, i64 2, i8 signext 3, i16 signext 4, i64 5, i64 6, i64 7, i8 signext 97, i16 signext 98, i8 signext 99, i8 signext 100)
     56   %conv = trunc i64 %call to i32
     57   ret i32 %conv
     58 }
     59 
     60 ; rdar://12651543
     61 define double @circle_center([2 x float] %a) nounwind ssp {
     62   %call = tail call double @ext([2 x float] %a) nounwind
     63 ; CHECK-LABEL: circle_center
     64 ; CHECK: bl
     65   ret double %call
     66 }
     67 declare double @ext([2 x float])
     68 
     69 ; rdar://12656141
     70 ; 16-byte vector should be aligned at 16-byte when passing on stack.
     71 ; A double argument will be passed on stack, so vecotr should be at sp+16.
     72 define double @fixed_4i(<4 x i32>* nocapture %in) nounwind {
     73 entry:
     74 ; CHECK-LABEL: fixed_4i
     75 ; CHECK: str [[REG_1:q[0-9]+]], [sp, #16]
     76 ; FAST-LABEL: fixed_4i
     77 ; FAST: sub sp, sp
     78 ; FAST: mov x[[ADDR:[0-9]+]], sp
     79 ; FAST: str [[REG_1:q[0-9]+]], [x[[ADDR]], #16]
     80   %0 = load <4 x i32>, <4 x i32>* %in, align 16
     81   %call = tail call double @args_vec_4i(double 3.000000e+00, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, double 3.000000e+00, <4 x i32> %0, i8 signext 3)
     82   ret double %call
     83 }
     84 declare double @args_vec_4i(double, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, double, <4 x i32>, i8 signext)
     85 
     86 ; rdar://12695237
     87 ; d8 at sp, i in register w0.
     88 @g_d = common global double 0.000000e+00, align 8
     89 define void @test1(float %f1, double %d1, double %d2, double %d3, double %d4,
     90        double %d5, double %d6, double %d7, double %d8, i32 %i) nounwind ssp {
     91 entry:
     92 ; CHECK-LABEL: test1
     93 ; CHECK: ldr [[REG_1:d[0-9]+]], [sp]
     94 ; CHECK: scvtf [[REG_2:s[0-9]+]], w0
     95 ; CHECK: fadd s0, [[REG_2]], s0
     96   %conv = sitofp i32 %i to float
     97   %add = fadd float %conv, %f1
     98   %conv1 = fpext float %add to double
     99   %add2 = fadd double %conv1, %d7
    100   %add3 = fadd double %add2, %d8
    101   store double %add3, double* @g_d, align 8
    102   ret void
    103 }
    104 
    105 ; i9 at sp, d1 in register s0.
    106 define void @test2(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6,
    107             i32 %i7, i32 %i8, i32 %i9, float %d1) nounwind ssp {
    108 entry:
    109 ; CHECK-LABEL: test2
    110 ; CHECK: scvtf [[REG_2:s[0-9]+]], w0
    111 ; CHECK: fadd s0, [[REG_2]], s0
    112 ; CHECK: ldr [[REG_1:s[0-9]+]], [sp]
    113   %conv = sitofp i32 %i1 to float
    114   %add = fadd float %conv, %d1
    115   %conv1 = fpext float %add to double
    116   %conv2 = sitofp i32 %i8 to double
    117   %add3 = fadd double %conv2, %conv1
    118   %conv4 = sitofp i32 %i9 to double
    119   %add5 = fadd double %conv4, %add3
    120   store double %add5, double* @g_d, align 8
    121   ret void
    122 }
    123 
    124 ; rdar://12648441
    125 ; Check alignment on stack for v64, f64, i64, f32, i32.
    126 define double @test3(<2 x i32>* nocapture %in) nounwind {
    127 entry:
    128 ; CHECK-LABEL: test3
    129 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
    130 ; FAST-LABEL: test3
    131 ; FAST: sub sp, sp, #48
    132 ; FAST: mov x[[ADDR:[0-9]+]], sp
    133 ; FAST: str [[REG_1:d[0-9]+]], [x[[ADDR]], #8]
    134   %0 = load <2 x i32>, <2 x i32>* %in, align 8
    135   %call = tail call double @args_vec_2i(double 3.000000e+00, <2 x i32> %0,
    136           <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, <2 x i32> %0,
    137           <2 x i32> %0, float 3.000000e+00, <2 x i32> %0, i8 signext 3)
    138   ret double %call
    139 }
    140 declare double @args_vec_2i(double, <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>,
    141                <2 x i32>, <2 x i32>, <2 x i32>, float, <2 x i32>, i8 signext)
    142 
    143 define double @test4(double* nocapture %in) nounwind {
    144 entry:
    145 ; CHECK-LABEL: test4
    146 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
    147 ; CHECK: str [[REG_2:w[0-9]+]], [sp]
    148 ; CHECK: orr w0, wzr, #0x3
    149   %0 = load double, double* %in, align 8
    150   %call = tail call double @args_f64(double 3.000000e+00, double %0, double %0,
    151           double %0, double %0, double %0, double %0, double %0,
    152           float 3.000000e+00, double %0, i8 signext 3)
    153   ret double %call
    154 }
    155 declare double @args_f64(double, double, double, double, double, double, double,
    156                double, float, double, i8 signext)
    157 
    158 define i64 @test5(i64* nocapture %in) nounwind {
    159 entry:
    160 ; CHECK-LABEL: test5
    161 ; CHECK: strb [[REG_3:w[0-9]+]], [sp, #16]
    162 ; CHECK: str [[REG_1:x[0-9]+]], [sp, #8]
    163 ; CHECK: str [[REG_2:w[0-9]+]], [sp]
    164   %0 = load i64, i64* %in, align 8
    165   %call = tail call i64 @args_i64(i64 3, i64 %0, i64 %0, i64 %0, i64 %0, i64 %0,
    166                          i64 %0, i64 %0, i32 3, i64 %0, i8 signext 3)
    167   ret i64 %call
    168 }
    169 declare i64 @args_i64(i64, i64, i64, i64, i64, i64, i64, i64, i32, i64,
    170              i8 signext)
    171 
    172 define i32 @test6(float* nocapture %in) nounwind {
    173 entry:
    174 ; CHECK-LABEL: test6
    175 ; CHECK: strb [[REG_2:w[0-9]+]], [sp, #8]
    176 ; CHECK: str [[REG_1:s[0-9]+]], [sp, #4]
    177 ; CHECK: strh [[REG_3:w[0-9]+]], [sp]
    178   %0 = load float, float* %in, align 4
    179   %call = tail call i32 @args_f32(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6,
    180           i32 7, i32 8, float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
    181           float 6.0, float 7.0, float 8.0, i16 signext 3, float %0,
    182           i8 signext 3)
    183   ret i32 %call
    184 }
    185 declare i32 @args_f32(i32, i32, i32, i32, i32, i32, i32, i32,
    186                       float, float, float, float, float, float, float, float,
    187                       i16 signext, float, i8 signext)
    188 
    189 define i32 @test7(i32* nocapture %in) nounwind {
    190 entry:
    191 ; CHECK-LABEL: test7
    192 ; CHECK: strb [[REG_2:w[0-9]+]], [sp, #8]
    193 ; CHECK: str [[REG_1:w[0-9]+]], [sp, #4]
    194 ; CHECK: strh [[REG_3:w[0-9]+]], [sp]
    195   %0 = load i32, i32* %in, align 4
    196   %call = tail call i32 @args_i32(i32 3, i32 %0, i32 %0, i32 %0, i32 %0, i32 %0,
    197                          i32 %0, i32 %0, i16 signext 3, i32 %0, i8 signext 4)
    198   ret i32 %call
    199 }
    200 declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32,
    201              i8 signext)
    202 
    203 define i32 @test8(i32 %argc, i8** nocapture %argv) nounwind {
    204 entry:
    205 ; CHECK-LABEL: test8
    206 ; CHECK: str w8, [sp]
    207 ; CHECK: bl
    208 ; FAST-LABEL: test8
    209 ; FAST: strb {{w[0-9]+}}, [sp]
    210 ; FAST: strb {{w[0-9]+}}, [sp, #1]
    211 ; FAST: strb {{w[0-9]+}}, [sp, #2]
    212 ; FAST: strb {{w[0-9]+}}, [sp, #3]
    213 ; FAST: bl
    214   tail call void @args_i1(i1 zeroext false, i1 zeroext true, i1 zeroext false,
    215                   i1 zeroext true, i1 zeroext false, i1 zeroext true,
    216                   i1 zeroext false, i1 zeroext true, i1 zeroext false,
    217                   i1 zeroext true, i1 zeroext false, i1 zeroext true)
    218   ret i32 0
    219 }
    220 
    221 declare void @args_i1(i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext,
    222                       i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext,
    223                       i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext)
    224 
    225 define i32 @i1_stack_incoming(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f,
    226                                i64 %g, i64 %h, i64 %i, i1 zeroext %j) {
    227 ; CHECK-LABEL: i1_stack_incoming:
    228 ; CHECK: ldrb w0, [sp, #8]
    229 ; CHECK: ret
    230   %v = zext i1 %j to i32
    231   ret i32 %v
    232 }
    233