Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc < %s -mtriple=arm64-apple-ios7.0.0 -mcpu=cyclone -enable-misched=false | FileCheck %s
      2 
      3 ; rdar://13625505
      4 ; Here we have 9 fixed integer arguments the 9th argument in on stack, the
      5 ; varargs start right after at 8-byte alignment.
      6 define void @fn9(i32* %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8, i32 %a9, ...) nounwind noinline ssp {
      7 ; CHECK-LABEL: fn9:
      8 ; 9th fixed argument
      9 ; CHECK: ldr {{w[0-9]+}}, [sp, #64]
     10 ; CHECK: add [[ARGS:x[0-9]+]], sp, #72
     11 ; CHECK: add {{x[0-9]+}}, [[ARGS]], #8
     12 ; First vararg
     13 ; CHECK: ldr {{w[0-9]+}}, [sp, #72]
     14 ; Second vararg
     15 ; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}], #8
     16 ; Third vararg
     17 ; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}], #8
     18   %1 = alloca i32, align 4
     19   %2 = alloca i32, align 4
     20   %3 = alloca i32, align 4
     21   %4 = alloca i32, align 4
     22   %5 = alloca i32, align 4
     23   %6 = alloca i32, align 4
     24   %7 = alloca i32, align 4
     25   %8 = alloca i32, align 4
     26   %9 = alloca i32, align 4
     27   %args = alloca i8*, align 8
     28   %a10 = alloca i32, align 4
     29   %a11 = alloca i32, align 4
     30   %a12 = alloca i32, align 4
     31   store i32 %a2, i32* %2, align 4
     32   store i32 %a3, i32* %3, align 4
     33   store i32 %a4, i32* %4, align 4
     34   store i32 %a5, i32* %5, align 4
     35   store i32 %a6, i32* %6, align 4
     36   store i32 %a7, i32* %7, align 4
     37   store i32 %a8, i32* %8, align 4
     38   store i32 %a9, i32* %9, align 4
     39   store i32 %a9, i32* %a1
     40   %10 = bitcast i8** %args to i8*
     41   call void @llvm.va_start(i8* %10)
     42   %11 = va_arg i8** %args, i32
     43   store i32 %11, i32* %a10, align 4
     44   %12 = va_arg i8** %args, i32
     45   store i32 %12, i32* %a11, align 4
     46   %13 = va_arg i8** %args, i32
     47   store i32 %13, i32* %a12, align 4
     48   ret void
     49 }
     50 
     51 declare void @llvm.va_start(i8*) nounwind
     52 
     53 define i32 @main() nounwind ssp {
     54 ; CHECK-LABEL: main:
     55 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16]
     56 ; CHECK: str {{x[0-9]+}}, [sp, #8]
     57 ; CHECK: str {{w[0-9]+}}, [sp]
     58   %a1 = alloca i32, align 4
     59   %a2 = alloca i32, align 4
     60   %a3 = alloca i32, align 4
     61   %a4 = alloca i32, align 4
     62   %a5 = alloca i32, align 4
     63   %a6 = alloca i32, align 4
     64   %a7 = alloca i32, align 4
     65   %a8 = alloca i32, align 4
     66   %a9 = alloca i32, align 4
     67   %a10 = alloca i32, align 4
     68   %a11 = alloca i32, align 4
     69   %a12 = alloca i32, align 4
     70   store i32 1, i32* %a1, align 4
     71   store i32 2, i32* %a2, align 4
     72   store i32 3, i32* %a3, align 4
     73   store i32 4, i32* %a4, align 4
     74   store i32 5, i32* %a5, align 4
     75   store i32 6, i32* %a6, align 4
     76   store i32 7, i32* %a7, align 4
     77   store i32 8, i32* %a8, align 4
     78   store i32 9, i32* %a9, align 4
     79   store i32 10, i32* %a10, align 4
     80   store i32 11, i32* %a11, align 4
     81   store i32 12, i32* %a12, align 4
     82   %1 = load i32, i32* %a1, align 4
     83   %2 = load i32, i32* %a2, align 4
     84   %3 = load i32, i32* %a3, align 4
     85   %4 = load i32, i32* %a4, align 4
     86   %5 = load i32, i32* %a5, align 4
     87   %6 = load i32, i32* %a6, align 4
     88   %7 = load i32, i32* %a7, align 4
     89   %8 = load i32, i32* %a8, align 4
     90   %9 = load i32, i32* %a9, align 4
     91   %10 = load i32, i32* %a10, align 4
     92   %11 = load i32, i32* %a11, align 4
     93   %12 = load i32, i32* %a12, align 4
     94   call void (i32*, i32, i32, i32, i32, i32, i32, i32, i32, ...) @fn9(i32* %a1, i32 %2, i32 %3, i32 %4, i32 %5, i32 %6, i32 %7, i32 %8, i32 %9, i32 %10, i32 %11, i32 %12)
     95   ret i32 0
     96 }
     97 
     98 ;rdar://13668483
     99 @.str = private unnamed_addr constant [4 x i8] c"fmt\00", align 1
    100 define void @foo(i8* %fmt, ...) nounwind {
    101 entry:
    102 ; CHECK-LABEL: foo:
    103 ; CHECK: ldr {{w[0-9]+}}, [sp, #48]
    104 ; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #23
    105 ; CHECK: and x[[ADDR:[0-9]+]], {{x[0-9]+}}, #0xfffffffffffffff0
    106 ; CHECK: ldr {{q[0-9]+}}, [x[[ADDR]]]
    107   %fmt.addr = alloca i8*, align 8
    108   %args = alloca i8*, align 8
    109   %vc = alloca i32, align 4
    110   %vv = alloca <4 x i32>, align 16
    111   store i8* %fmt, i8** %fmt.addr, align 8
    112   %args1 = bitcast i8** %args to i8*
    113   call void @llvm.va_start(i8* %args1)
    114   %0 = va_arg i8** %args, i32
    115   store i32 %0, i32* %vc, align 4
    116   %1 = va_arg i8** %args, <4 x i32>
    117   store <4 x i32> %1, <4 x i32>* %vv, align 16
    118   ret void
    119 }
    120 
    121 define void @bar(i32 %x, <4 x i32> %y) nounwind {
    122 entry:
    123 ; CHECK-LABEL: bar:
    124 ; CHECK: stp {{q[0-9]+}}, {{q[0-9]+}}, [sp, #16]
    125 ; CHECK: str {{x[0-9]+}}, [sp]
    126   %x.addr = alloca i32, align 4
    127   %y.addr = alloca <4 x i32>, align 16
    128   store i32 %x, i32* %x.addr, align 4
    129   store <4 x i32> %y, <4 x i32>* %y.addr, align 16
    130   %0 = load i32, i32* %x.addr, align 4
    131   %1 = load <4 x i32>, <4 x i32>* %y.addr, align 16
    132   call void (i8*, ...) @foo(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %0, <4 x i32> %1)
    133   ret void
    134 }
    135 
    136 ; rdar://13668927
    137 ; When passing 16-byte aligned small structs as vararg, make sure the caller
    138 ; side is 16-byte aligned on stack.
    139 %struct.s41 = type { i32, i16, i32, i16 }
    140 define void @foo2(i8* %fmt, ...) nounwind {
    141 entry:
    142 ; CHECK-LABEL: foo2:
    143 ; CHECK: ldr {{w[0-9]+}}, [sp, #48]
    144 ; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, #23
    145 ; CHECK: and x[[ADDR:[0-9]+]], {{x[0-9]+}}, #0xfffffffffffffff0
    146 ; CHECK: ldr {{q[0-9]+}}, [x[[ADDR]]]
    147   %fmt.addr = alloca i8*, align 8
    148   %args = alloca i8*, align 8
    149   %vc = alloca i32, align 4
    150   %vs = alloca %struct.s41, align 16
    151   store i8* %fmt, i8** %fmt.addr, align 8
    152   %args1 = bitcast i8** %args to i8*
    153   call void @llvm.va_start(i8* %args1)
    154   %0 = va_arg i8** %args, i32
    155   store i32 %0, i32* %vc, align 4
    156   %ap.cur = load i8*, i8** %args
    157   %1 = getelementptr i8, i8* %ap.cur, i32 15
    158   %2 = ptrtoint i8* %1 to i64
    159   %3 = and i64 %2, -16
    160   %ap.align = inttoptr i64 %3 to i8*
    161   %ap.next = getelementptr i8, i8* %ap.align, i32 16
    162   store i8* %ap.next, i8** %args
    163   %4 = bitcast i8* %ap.align to %struct.s41*
    164   %5 = bitcast %struct.s41* %vs to i8*
    165   %6 = bitcast %struct.s41* %4 to i8*
    166   call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %5, i8* align 16 %6, i64 16, i1 false)
    167   ret void
    168 }
    169 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind
    170 
    171 define void @bar2(i32 %x, i128 %s41.coerce) nounwind {
    172 entry:
    173 ; CHECK-LABEL: bar2:
    174 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #16]
    175 ; CHECK: str {{x[0-9]+}}, [sp]
    176   %x.addr = alloca i32, align 4
    177   %s41 = alloca %struct.s41, align 16
    178   store i32 %x, i32* %x.addr, align 4
    179   %0 = bitcast %struct.s41* %s41 to i128*
    180   store i128 %s41.coerce, i128* %0, align 1
    181   %1 = load i32, i32* %x.addr, align 4
    182   %2 = bitcast %struct.s41* %s41 to i128*
    183   %3 = load i128, i128* %2, align 1
    184   call void (i8*, ...) @foo2(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %1, i128 %3)
    185   ret void
    186 }
    187