Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc < %s -mtriple=arm64-apple-ios -asm-verbose=false | FileCheck %s
      2 
      3 define float @load0(i16* nocapture readonly %a) nounwind {
      4 ; CHECK-LABEL: load0:
      5 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0]
      6 ; CHECK-NEXT: fcvt s0, [[HREG]]
      7 ; CHECK-NEXT: ret
      8 
      9   %tmp = load i16, i16* %a, align 2
     10   %tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
     11   ret float %tmp1
     12 }
     13 
     14 define double @load1(i16* nocapture readonly %a) nounwind {
     15 ; CHECK-LABEL: load1:
     16 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0]
     17 ; CHECK-NEXT: fcvt d0, [[HREG]]
     18 ; CHECK-NEXT: ret
     19 
     20   %tmp = load i16, i16* %a, align 2
     21   %conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
     22   ret double %conv
     23 }
     24 
     25 define float @load2(i16* nocapture readonly %a, i32 %i) nounwind {
     26 ; CHECK-LABEL: load2:
     27 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, w1, sxtw #1]
     28 ; CHECK-NEXT: fcvt s0, [[HREG]]
     29 ; CHECK-NEXT: ret
     30 
     31   %idxprom = sext i32 %i to i64
     32   %arrayidx = getelementptr inbounds i16, i16* %a, i64 %idxprom
     33   %tmp = load i16, i16* %arrayidx, align 2
     34   %tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
     35   ret float %tmp1
     36 }
     37 
     38 define double @load3(i16* nocapture readonly %a, i32 %i) nounwind {
     39 ; CHECK-LABEL: load3:
     40 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, w1, sxtw #1]
     41 ; CHECK-NEXT: fcvt d0, [[HREG]]
     42 ; CHECK-NEXT: ret
     43 
     44   %idxprom = sext i32 %i to i64
     45   %arrayidx = getelementptr inbounds i16, i16* %a, i64 %idxprom
     46   %tmp = load i16, i16* %arrayidx, align 2
     47   %conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
     48   ret double %conv
     49 }
     50 
     51 define float @load4(i16* nocapture readonly %a, i64 %i) nounwind {
     52 ; CHECK-LABEL: load4:
     53 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, x1, lsl #1]
     54 ; CHECK-NEXT: fcvt s0, [[HREG]]
     55 ; CHECK-NEXT: ret
     56 
     57   %arrayidx = getelementptr inbounds i16, i16* %a, i64 %i
     58   %tmp = load i16, i16* %arrayidx, align 2
     59   %tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
     60   ret float %tmp1
     61 }
     62 
     63 define double @load5(i16* nocapture readonly %a, i64 %i) nounwind {
     64 ; CHECK-LABEL: load5:
     65 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, x1, lsl #1]
     66 ; CHECK-NEXT: fcvt d0, [[HREG]]
     67 ; CHECK-NEXT: ret
     68 
     69   %arrayidx = getelementptr inbounds i16, i16* %a, i64 %i
     70   %tmp = load i16, i16* %arrayidx, align 2
     71   %conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
     72   ret double %conv
     73 }
     74 
     75 define float @load6(i16* nocapture readonly %a) nounwind {
     76 ; CHECK-LABEL: load6:
     77 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, #20]
     78 ; CHECK-NEXT: fcvt s0, [[HREG]]
     79 ; CHECK-NEXT: ret
     80 
     81   %arrayidx = getelementptr inbounds i16, i16* %a, i64 10
     82   %tmp = load i16, i16* %arrayidx, align 2
     83   %tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
     84   ret float %tmp1
     85 }
     86 
     87 define double @load7(i16* nocapture readonly %a) nounwind {
     88 ; CHECK-LABEL: load7:
     89 ; CHECK-NEXT: ldr [[HREG:h[0-9]+]], [x0, #20]
     90 ; CHECK-NEXT: fcvt d0, [[HREG]]
     91 ; CHECK-NEXT: ret
     92 
     93   %arrayidx = getelementptr inbounds i16, i16* %a, i64 10
     94   %tmp = load i16, i16* %arrayidx, align 2
     95   %conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
     96   ret double %conv
     97 }
     98 
     99 define float @load8(i16* nocapture readonly %a) nounwind {
    100 ; CHECK-LABEL: load8:
    101 ; CHECK-NEXT: ldur [[HREG:h[0-9]+]], [x0, #-20]
    102 ; CHECK-NEXT: fcvt s0, [[HREG]]
    103 ; CHECK-NEXT: ret
    104 
    105   %arrayidx = getelementptr inbounds i16, i16* %a, i64 -10
    106   %tmp = load i16, i16* %arrayidx, align 2
    107   %tmp1 = tail call float @llvm.convert.from.fp16.f32(i16 %tmp)
    108   ret float %tmp1
    109 }
    110 
    111 define double @load9(i16* nocapture readonly %a) nounwind {
    112 ; CHECK-LABEL: load9:
    113 ; CHECK-NEXT: ldur [[HREG:h[0-9]+]], [x0, #-20]
    114 ; CHECK-NEXT: fcvt d0, [[HREG]]
    115 ; CHECK-NEXT: ret
    116 
    117   %arrayidx = getelementptr inbounds i16, i16* %a, i64 -10
    118   %tmp = load i16, i16* %arrayidx, align 2
    119   %conv = tail call double @llvm.convert.from.fp16.f64(i16 %tmp)
    120   ret double %conv
    121 }
    122 
    123 define void @store0(i16* nocapture %a, float %val) nounwind {
    124 ; CHECK-LABEL: store0:
    125 ; CHECK-NEXT: fcvt h0, s0
    126 ; CHECK-NEXT: str  h0, [x0]
    127 ; CHECK-NEXT: ret
    128 
    129   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
    130   store i16 %tmp, i16* %a, align 2
    131   ret void
    132 }
    133 
    134 define void @store1(i16* nocapture %a, double %val) nounwind {
    135 ; CHECK-LABEL: store1:
    136 ; CHECK-NEXT: fcvt s0, d0
    137 ; CHECK-NEXT: fcvt h0, s0
    138 ; CHECK-NEXT: str  h0, [x0]
    139 ; CHECK-NEXT: ret
    140 
    141   %conv = fptrunc double %val to float
    142   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
    143   store i16 %tmp, i16* %a, align 2
    144   ret void
    145 }
    146 
    147 define void @store2(i16* nocapture %a, i32 %i, float %val) nounwind {
    148 ; CHECK-LABEL: store2:
    149 ; CHECK-NEXT: fcvt h0, s0
    150 ; CHECK-NEXT: str h0, [x0, w1, sxtw #1]
    151 ; CHECK-NEXT: ret
    152 
    153   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
    154   %idxprom = sext i32 %i to i64
    155   %arrayidx = getelementptr inbounds i16, i16* %a, i64 %idxprom
    156   store i16 %tmp, i16* %arrayidx, align 2
    157   ret void
    158 }
    159 
    160 define void @store3(i16* nocapture %a, i32 %i, double %val) nounwind {
    161 ; CHECK-LABEL: store3:
    162 ; CHECK-NEXT: fcvt s0, d0
    163 ; CHECK-NEXT: fcvt h0, s0
    164 ; CHECK-NEXT: str h0, [x0, w1, sxtw #1]
    165 ; CHECK-NEXT: ret
    166 
    167   %conv = fptrunc double %val to float
    168   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
    169   %idxprom = sext i32 %i to i64
    170   %arrayidx = getelementptr inbounds i16, i16* %a, i64 %idxprom
    171   store i16 %tmp, i16* %arrayidx, align 2
    172   ret void
    173 }
    174 
    175 define void @store4(i16* nocapture %a, i64 %i, float %val) nounwind {
    176 ; CHECK-LABEL: store4:
    177 ; CHECK-NEXT: fcvt h0, s0
    178 ; CHECK-NEXT: str h0, [x0, x1, lsl #1]
    179 ; CHECK-NEXT: ret
    180 
    181   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
    182   %arrayidx = getelementptr inbounds i16, i16* %a, i64 %i
    183   store i16 %tmp, i16* %arrayidx, align 2
    184   ret void
    185 }
    186 
    187 define void @store5(i16* nocapture %a, i64 %i, double %val) nounwind {
    188 ; CHECK-LABEL: store5:
    189 ; CHECK-NEXT: fcvt s0, d0
    190 ; CHECK-NEXT: fcvt h0, s0
    191 ; CHECK-NEXT: str h0, [x0, x1, lsl #1]
    192 ; CHECK-NEXT: ret
    193 
    194   %conv = fptrunc double %val to float
    195   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
    196   %arrayidx = getelementptr inbounds i16, i16* %a, i64 %i
    197   store i16 %tmp, i16* %arrayidx, align 2
    198   ret void
    199 }
    200 
    201 define void @store6(i16* nocapture %a, float %val) nounwind {
    202 ; CHECK-LABEL: store6:
    203 ; CHECK-NEXT: fcvt h0, s0
    204 ; CHECK-NEXT: str h0, [x0, #20]
    205 ; CHECK-NEXT: ret
    206 
    207   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
    208   %arrayidx = getelementptr inbounds i16, i16* %a, i64 10
    209   store i16 %tmp, i16* %arrayidx, align 2
    210   ret void
    211 }
    212 
    213 define void @store7(i16* nocapture %a, double %val) nounwind {
    214 ; CHECK-LABEL: store7:
    215 ; CHECK-NEXT: fcvt s0, d0
    216 ; CHECK-NEXT: fcvt h0, s0
    217 ; CHECK-NEXT: str h0, [x0, #20]
    218 ; CHECK-NEXT: ret
    219 
    220   %conv = fptrunc double %val to float
    221   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
    222   %arrayidx = getelementptr inbounds i16, i16* %a, i64 10
    223   store i16 %tmp, i16* %arrayidx, align 2
    224   ret void
    225 }
    226 
    227 define void @store8(i16* nocapture %a, float %val) nounwind {
    228 ; CHECK-LABEL: store8:
    229 ; CHECK-NEXT: fcvt h0, s0
    230 ; CHECK-NEXT: stur h0, [x0, #-20]
    231 ; CHECK-NEXT: ret
    232 
    233   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %val)
    234   %arrayidx = getelementptr inbounds i16, i16* %a, i64 -10
    235   store i16 %tmp, i16* %arrayidx, align 2
    236   ret void
    237 }
    238 
    239 define void @store9(i16* nocapture %a, double %val) nounwind {
    240 ; CHECK-LABEL: store9:
    241 ; CHECK-NEXT: fcvt s0, d0
    242 ; CHECK-NEXT: fcvt h0, s0
    243 ; CHECK-NEXT: stur h0, [x0, #-20]
    244 ; CHECK-NEXT: ret
    245 
    246   %conv = fptrunc double %val to float
    247   %tmp = tail call i16 @llvm.convert.to.fp16.f32(float %conv)
    248   %arrayidx = getelementptr inbounds i16, i16* %a, i64 -10
    249   store i16 %tmp, i16* %arrayidx, align 2
    250   ret void
    251 }
    252 
    253 declare i16 @llvm.convert.to.fp16.f32(float) nounwind readnone
    254 declare float @llvm.convert.from.fp16.f32(i16) nounwind readnone
    255 declare i16 @llvm.convert.to.fp16.f64(double) nounwind readnone
    256 declare double @llvm.convert.from.fp16.f64(i16) nounwind readnone
    257