Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s
      2 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -mattr=-neon | FileCheck --check-prefix=CHECK-NONEON %s
      3 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -mattr=-fp-armv8 | FileCheck --check-prefix=CHECK-NOFP %s
      4 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64_be-none-linux-gnu | FileCheck --check-prefix=CHECK-BE %s
      5 
      6 %myStruct = type { i64 , i8, i32 }
      7 
      8 @var8 = global i8 0
      9 @var8_2 = global i8 0
     10 @var32 = global i32 0
     11 @var64 = global i64 0
     12 @var128 = global i128 0
     13 @varfloat = global float 0.0
     14 @varfloat_2 = global float 0.0
     15 @vardouble = global double 0.0
     16 @varstruct = global %myStruct zeroinitializer
     17 @varsmallstruct = global [2 x i64] zeroinitializer
     18 
     19 declare void @take_i8s(i8 %val1, i8 %val2)
     20 declare void @take_floats(float %val1, float %val2)
     21 
     22 define void @simple_args() {
     23 ; CHECK-LABEL: simple_args:
     24   %char1 = load i8, i8* @var8
     25   %char2 = load i8, i8* @var8_2
     26   call void @take_i8s(i8 %char1, i8 %char2)
     27 ; CHECK-DAG: ldrb w0, [{{x[0-9]+}}, {{#?}}:lo12:var8]
     28 ; CHECK-DAG: ldrb w1, [{{x[0-9]+}}, {{#?}}:lo12:var8_2]
     29 ; CHECK: bl take_i8s
     30 
     31   %float1 = load float, float* @varfloat
     32   %float2 = load float, float* @varfloat_2
     33   call void @take_floats(float %float1, float %float2)
     34 ; CHECK-DAG: ldr s1, [{{x[0-9]+}}, {{#?}}:lo12:varfloat_2]
     35 ; CHECK-DAG: ldr s0, [{{x[0-9]+}}, {{#?}}:lo12:varfloat]
     36 ; CHECK: bl take_floats
     37 ; CHECK-NOFP-NOT: ldr s1,
     38 ; CHECK-NOFP-NOT: ldr s0,
     39 
     40   ret void
     41 }
     42 
     43 declare i32 @return_int()
     44 declare double @return_double()
     45 declare [2 x i64] @return_smallstruct()
     46 declare void @return_large_struct(%myStruct* sret %retval)
     47 
     48 define void @simple_rets() {
     49 ; CHECK-LABEL: simple_rets:
     50 
     51   %int = call i32 @return_int()
     52   store i32 %int, i32* @var32
     53 ; CHECK: bl return_int
     54 ; CHECK: str w0, [{{x[0-9]+}}, {{#?}}:lo12:var32]
     55 
     56   %dbl = call double @return_double()
     57   store double %dbl, double* @vardouble
     58 ; CHECK: bl return_double
     59 ; CHECK: str d0, [{{x[0-9]+}}, {{#?}}:lo12:vardouble]
     60 ; CHECK-NOFP-NOT: str d0,
     61 
     62   %arr = call [2 x i64] @return_smallstruct()
     63   store [2 x i64] %arr, [2 x i64]* @varsmallstruct
     64 ; CHECK: bl return_smallstruct
     65 ; CHECK: add x[[VARSMALLSTRUCT:[0-9]+]], {{x[0-9]+}}, :lo12:varsmallstruct
     66 ; CHECK: stp x0, x1, [x[[VARSMALLSTRUCT]]]
     67 
     68   call void @return_large_struct(%myStruct* sret @varstruct)
     69 ; CHECK: add x8, {{x[0-9]+}}, {{#?}}:lo12:varstruct
     70 ; CHECK: bl return_large_struct
     71 
     72   ret void
     73 }
     74 
     75 
     76 declare i32 @struct_on_stack(i8 %var0, i16 %var1, i32 %var2, i64 %var3, i128 %var45,
     77                              i32* %var6, %myStruct* byval %struct, i32 %stacked,
     78                              double %notstacked)
     79 declare void @stacked_fpu(float %var0, double %var1, float %var2, float %var3,
     80                           float %var4, float %var5, float %var6, float %var7,
     81                           float %var8)
     82 
     83 define void @check_stack_args() {
     84 ; CHECK-LABEL: check_stack_args:
     85   call i32 @struct_on_stack(i8 0, i16 12, i32 42, i64 99, i128 1,
     86                             i32* @var32, %myStruct* byval @varstruct,
     87                             i32 999, double 1.0)
     88   ; Want to check that the final double is passed in registers and
     89   ; that varstruct is passed on the stack. Rather dependent on how a
     90   ; memcpy gets created, but the following works for now.
     91 
     92 ; CHECK-DAG: str {{q[0-9]+}}, [sp]
     93 ; CHECK-DAG: fmov d[[FINAL_DOUBLE:[0-9]+]], #1.0
     94 ; CHECK: mov v0.16b, v[[FINAL_DOUBLE]].16b
     95 
     96 ; CHECK-NONEON-DAG: str {{q[0-9]+}}, [sp]
     97 ; CHECK-NONEON-DAG: fmov d[[FINAL_DOUBLE:[0-9]+]], #1.0
     98 ; CHECK-NONEON: fmov d0, d[[FINAL_DOUBLE]]
     99 
    100 ; CHECK: bl struct_on_stack
    101 ; CHECK-NOFP-NOT: fmov
    102 
    103   call void @stacked_fpu(float -1.0, double 1.0, float 4.0, float 2.0,
    104                          float -2.0, float -8.0, float 16.0, float 1.0,
    105                          float 64.0)
    106 
    107 ; CHECK:  mov [[SIXTY_FOUR:w[0-9]+]], #1115684864
    108 ; CHECK: str [[SIXTY_FOUR]], [sp]
    109 
    110 ; CHECK-NONEON:  mov [[SIXTY_FOUR:w[0-9]+]], #1115684864
    111 ; CHECK-NONEON: str [[SIXTY_FOUR]], [sp]
    112 
    113 ; CHECK: bl stacked_fpu
    114   ret void
    115 }
    116 
    117 
    118 declare void @check_i128_stackalign(i32 %val0, i32 %val1, i32 %val2, i32 %val3,
    119                                     i32 %val4, i32 %val5, i32 %val6, i32 %val7,
    120                                     i32 %stack1, i128 %stack2)
    121 
    122 declare void @check_i128_regalign(i32 %val0, i128 %val1)
    123 
    124 
    125 define void @check_i128_align() {
    126 ; CHECK-LABEL: check_i128_align:
    127   %val = load i128, i128* @var128
    128   call void @check_i128_stackalign(i32 0, i32 1, i32 2, i32 3,
    129                                    i32 4, i32 5, i32 6, i32 7,
    130                                    i32 42, i128 %val)
    131 ; CHECK: add x[[VAR128:[0-9]+]], {{x[0-9]+}}, :lo12:var128
    132 ; CHECK: ldp [[I128LO:x[0-9]+]], [[I128HI:x[0-9]+]], [x[[VAR128]]]
    133 ; CHECK: stp [[I128LO]], [[I128HI]], [sp, #16]
    134 
    135 ; CHECK-NONEON: add x[[VAR128:[0-9]+]], {{x[0-9]+}}, :lo12:var128
    136 ; CHECK-NONEON: ldp [[I128LO:x[0-9]+]], [[I128HI:x[0-9]+]], [x[[VAR128]]]
    137 ; CHECK-NONEON: stp [[I128LO]], [[I128HI]], [sp, #16]
    138 ; CHECK: bl check_i128_stackalign
    139 
    140   call void @check_i128_regalign(i32 0, i128 42)
    141 ; CHECK-NOT: mov x1
    142 ; CHECK-LE: mov x2, #{{0x2a|42}}
    143 ; CHECK-LE: mov x3, xzr
    144 ; CHECK-BE: mov {{x|w}}3, #{{0x2a|42}}
    145 ; CHECK-BE: mov x2, xzr
    146 ; CHECK: bl check_i128_regalign
    147 
    148   ret void
    149 }
    150 
    151 @fptr = global void()* null
    152 
    153 define void @check_indirect_call() {
    154 ; CHECK-LABEL: check_indirect_call:
    155   %func = load void()*, void()** @fptr
    156   call void %func()
    157 ; CHECK: ldr [[FPTR:x[0-9]+]], [{{x[0-9]+}}, {{#?}}:lo12:fptr]
    158 ; CHECK: blr [[FPTR]]
    159 
    160   ret void
    161 }
    162