1 ; RUN: llc < %s -mtriple=thumbv7-none-eabi -mcpu=cortex-m3 | FileCheck %s -check-prefix=CHECK -check-prefix=SOFT -check-prefix=NONE 2 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-m4 | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=SP -check-prefix=VMLA 3 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-m7 | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=VFP -check-prefix=FP-ARMv8 -check-prefix=VMLA 4 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-m7 -mattr=+fp-only-sp | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=SP -check-prefix=FP-ARMv8 -check-prefix=VMLA 5 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-a7 | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=NEON -check-prefix=VFP4 -check-prefix=NO-VMLA 6 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-a57 | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=NEON -check-prefix=FP-ARMv8 -check-prefix=VMLA 7 8 declare float @llvm.sqrt.f32(float %Val) 9 define float @sqrt_f(float %a) { 10 ; CHECK-LABEL: sqrt_f: 11 ; SOFT: bl sqrtf 12 ; HARD: vsqrt.f32 s0, s0 13 %1 = call float @llvm.sqrt.f32(float %a) 14 ret float %1 15 } 16 17 declare float @llvm.powi.f32(float %Val, i32 %power) 18 define float @powi_f(float %a, i32 %b) { 19 ; CHECK-LABEL: powi_f: 20 ; SOFT: bl __powisf2 21 ; HARD: b __powisf2 22 %1 = call float @llvm.powi.f32(float %a, i32 %b) 23 ret float %1 24 } 25 26 declare float @llvm.sin.f32(float %Val) 27 define float @sin_f(float %a) { 28 ; CHECK-LABEL: sin_f: 29 ; SOFT: bl sinf 30 ; HARD: b sinf 31 %1 = call float @llvm.sin.f32(float %a) 32 ret float %1 33 } 34 35 declare float @llvm.cos.f32(float %Val) 36 define float @cos_f(float %a) { 37 ; CHECK-LABEL: cos_f: 38 ; SOFT: bl cosf 39 ; HARD: b cosf 40 %1 = call float @llvm.cos.f32(float %a) 41 ret float %1 42 } 43 44 declare float @llvm.pow.f32(float %Val, float %power) 45 define float @pow_f(float %a, float %b) { 46 ; CHECK-LABEL: pow_f: 47 ; SOFT: bl powf 48 ; HARD: b powf 49 %1 = call float @llvm.pow.f32(float %a, float %b) 50 ret float %1 51 } 52 53 declare float @llvm.exp.f32(float %Val) 54 define float @exp_f(float %a) { 55 ; CHECK-LABEL: exp_f: 56 ; SOFT: bl expf 57 ; HARD: b expf 58 %1 = call float @llvm.exp.f32(float %a) 59 ret float %1 60 } 61 62 declare float @llvm.exp2.f32(float %Val) 63 define float @exp2_f(float %a) { 64 ; CHECK-LABEL: exp2_f: 65 ; SOFT: bl exp2f 66 ; HARD: b exp2f 67 %1 = call float @llvm.exp2.f32(float %a) 68 ret float %1 69 } 70 71 declare float @llvm.log.f32(float %Val) 72 define float @log_f(float %a) { 73 ; CHECK-LABEL: log_f: 74 ; SOFT: bl logf 75 ; HARD: b logf 76 %1 = call float @llvm.log.f32(float %a) 77 ret float %1 78 } 79 80 declare float @llvm.log10.f32(float %Val) 81 define float @log10_f(float %a) { 82 ; CHECK-LABEL: log10_f: 83 ; SOFT: bl log10f 84 ; HARD: b log10f 85 %1 = call float @llvm.log10.f32(float %a) 86 ret float %1 87 } 88 89 declare float @llvm.log2.f32(float %Val) 90 define float @log2_f(float %a) { 91 ; CHECK-LABEL: log2_f: 92 ; SOFT: bl log2f 93 ; HARD: b log2f 94 %1 = call float @llvm.log2.f32(float %a) 95 ret float %1 96 } 97 98 declare float @llvm.fma.f32(float %a, float %b, float %c) 99 define float @fma_f(float %a, float %b, float %c) { 100 ; CHECK-LABEL: fma_f: 101 ; SOFT: bl fmaf 102 ; HARD: vfma.f32 103 %1 = call float @llvm.fma.f32(float %a, float %b, float %c) 104 ret float %1 105 } 106 107 declare float @llvm.fabs.f32(float %Val) 108 define float @abs_f(float %a) { 109 ; CHECK-LABEL: abs_f: 110 ; SOFT: bic r0, r0, #-2147483648 111 ; HARD: vabs.f32 112 %1 = call float @llvm.fabs.f32(float %a) 113 ret float %1 114 } 115 116 declare float @llvm.copysign.f32(float %Mag, float %Sgn) 117 define float @copysign_f(float %a, float %b) { 118 ; CHECK-LABEL: copysign_f: 119 ; NONE: lsrs [[REG:r[0-9]+]], r{{[0-9]+}}, #31 120 ; NONE: bfi r{{[0-9]+}}, [[REG]], #31, #1 121 ; SP: lsrs [[REG:r[0-9]+]], r{{[0-9]+}}, #31 122 ; SP: bfi r{{[0-9]+}}, [[REG]], #31, #1 123 ; VFP: lsrs [[REG:r[0-9]+]], r{{[0-9]+}}, #31 124 ; VFP: bfi r{{[0-9]+}}, [[REG]], #31, #1 125 ; NEON: vmov.i32 [[REG:d[0-9]+]], #0x80000000 126 ; NEON: vbsl [[REG]], d 127 %1 = call float @llvm.copysign.f32(float %a, float %b) 128 ret float %1 129 } 130 131 declare float @llvm.floor.f32(float %Val) 132 define float @floor_f(float %a) { 133 ; CHECK-LABEL: floor_f: 134 ; SOFT: bl floorf 135 ; VFP4: b floorf 136 ; FP-ARMv8: vrintm.f32 137 %1 = call float @llvm.floor.f32(float %a) 138 ret float %1 139 } 140 141 declare float @llvm.ceil.f32(float %Val) 142 define float @ceil_f(float %a) { 143 ; CHECK-LABEL: ceil_f: 144 ; SOFT: bl ceilf 145 ; VFP4: b ceilf 146 ; FP-ARMv8: vrintp.f32 147 %1 = call float @llvm.ceil.f32(float %a) 148 ret float %1 149 } 150 151 declare float @llvm.trunc.f32(float %Val) 152 define float @trunc_f(float %a) { 153 ; CHECK-LABEL: trunc_f: 154 ; SOFT: bl truncf 155 ; VFP4: b truncf 156 ; FP-ARMv8: vrintz.f32 157 %1 = call float @llvm.trunc.f32(float %a) 158 ret float %1 159 } 160 161 declare float @llvm.rint.f32(float %Val) 162 define float @rint_f(float %a) { 163 ; CHECK-LABEL: rint_f: 164 ; SOFT: bl rintf 165 ; VFP4: b rintf 166 ; FP-ARMv8: vrintx.f32 167 %1 = call float @llvm.rint.f32(float %a) 168 ret float %1 169 } 170 171 declare float @llvm.nearbyint.f32(float %Val) 172 define float @nearbyint_f(float %a) { 173 ; CHECK-LABEL: nearbyint_f: 174 ; SOFT: bl nearbyintf 175 ; VFP4: b nearbyintf 176 ; FP-ARMv8: vrintr.f32 177 %1 = call float @llvm.nearbyint.f32(float %a) 178 ret float %1 179 } 180 181 declare float @llvm.round.f32(float %Val) 182 define float @round_f(float %a) { 183 ; CHECK-LABEL: round_f: 184 ; SOFT: bl roundf 185 ; VFP4: b roundf 186 ; FP-ARMv8: vrinta.f32 187 %1 = call float @llvm.round.f32(float %a) 188 ret float %1 189 } 190 191 ; FIXME: why does cortex-m4 use vmla, while cortex-a7 uses vmul+vadd? 192 ; (these should be equivalent, even the rounding is the same) 193 declare float @llvm.fmuladd.f32(float %a, float %b, float %c) 194 define float @fmuladd_f(float %a, float %b, float %c) { 195 ; CHECK-LABEL: fmuladd_f: 196 ; SOFT: bl __aeabi_fmul 197 ; SOFT: bl __aeabi_fadd 198 ; VMLA: vmla.f32 199 ; NO-VMLA: vmul.f32 200 ; NO-VMLA: vadd.f32 201 %1 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) 202 ret float %1 203 } 204 205 declare i16 @llvm.convert.to.fp16.f32(float %a) 206 define i16 @f_to_h(float %a) { 207 ; CHECK-LABEL: f_to_h: 208 ; SOFT: bl __aeabi_f2h 209 ; HARD: vcvt{{[bt]}}.f16.f32 210 %1 = call i16 @llvm.convert.to.fp16.f32(float %a) 211 ret i16 %1 212 } 213 214 declare float @llvm.convert.from.fp16.f32(i16 %a) 215 define float @h_to_f(i16 %a) { 216 ; CHECK-LABEL: h_to_f: 217 ; SOFT: bl __aeabi_h2f 218 ; HARD: vcvt{{[bt]}}.f32.f16 219 %1 = call float @llvm.convert.from.fp16.f32(i16 %a) 220 ret float %1 221 } 222