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