1 ; RUN: llc < %s -mtriple=thumbv7-none-eabi -mcpu=cortex-m3 | FileCheck %s -check-prefix=CHECK -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=VFP4-ALL 3 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-m7 | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=FP-ARMv8 4 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-a8 | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=VFP4-ALL -check-prefix=VFP4-DP 5 6 define float @add_f(float %a, float %b) { 7 entry: 8 ; CHECK-LABEL: add_f: 9 ; NONE: bl __aeabi_fadd 10 ; HARD: vadd.f32 s0, s0, s1 11 %0 = fadd float %a, %b 12 ret float %0 13 } 14 15 define double @add_d(double %a, double %b) { 16 entry: 17 ; CHECK-LABEL: add_d: 18 ; NONE: bl __aeabi_dadd 19 ; SP: bl __aeabi_dadd 20 ; DP: vadd.f64 d0, d0, d1 21 %0 = fadd double %a, %b 22 ret double %0 23 } 24 25 define float @sub_f(float %a, float %b) { 26 entry: 27 ; CHECK-LABEL: sub_f: 28 ; NONE: bl __aeabi_fsub 29 ; HARD: vsub.f32 s 30 %0 = fsub float %a, %b 31 ret float %0 32 } 33 34 define double @sub_d(double %a, double %b) { 35 entry: 36 ; CHECK-LABEL: sub_d: 37 ; NONE: bl __aeabi_dsub 38 ; SP: bl __aeabi_dsub 39 ; DP: vsub.f64 d0, d0, d1 40 %0 = fsub double %a, %b 41 ret double %0 42 } 43 44 define float @mul_f(float %a, float %b) { 45 entry: 46 ; CHECK-LABEL: mul_f: 47 ; NONE: bl __aeabi_fmul 48 ; HARD: vmul.f32 s 49 %0 = fmul float %a, %b 50 ret float %0 51 } 52 53 define double @mul_d(double %a, double %b) { 54 entry: 55 ; CHECK-LABEL: mul_d: 56 ; NONE: bl __aeabi_dmul 57 ; SP: bl __aeabi_dmul 58 ; DP: vmul.f64 d0, d0, d1 59 %0 = fmul double %a, %b 60 ret double %0 61 } 62 63 define float @div_f(float %a, float %b) { 64 entry: 65 ; CHECK-LABEL: div_f: 66 ; NONE: bl __aeabi_fdiv 67 ; HARD: vdiv.f32 s 68 %0 = fdiv float %a, %b 69 ret float %0 70 } 71 72 define double @div_d(double %a, double %b) { 73 entry: 74 ; CHECK-LABEL: div_d: 75 ; NONE: bl __aeabi_ddiv 76 ; SP: bl __aeabi_ddiv 77 ; DP: vdiv.f64 d0, d0, d1 78 %0 = fdiv double %a, %b 79 ret double %0 80 } 81 82 define float @rem_f(float %a, float %b) { 83 entry: 84 ; CHECK-LABEL: rem_f: 85 ; NONE: bl fmodf 86 ; HARD: b fmodf 87 %0 = frem float %a, %b 88 ret float %0 89 } 90 91 define double @rem_d(double %a, double %b) { 92 entry: 93 ; CHECK-LABEL: rem_d: 94 ; NONE: bl fmod 95 ; HARD: b fmod 96 %0 = frem double %a, %b 97 ret double %0 98 } 99 100 define float @load_f(float* %a) { 101 entry: 102 ; CHECK-LABEL: load_f: 103 ; NONE: ldr r0, [r0] 104 ; HARD: vldr s0, [r0] 105 %0 = load float, float* %a, align 4 106 ret float %0 107 } 108 109 define double @load_d(double* %a) { 110 entry: 111 ; CHECK-LABEL: load_d: 112 ; NONE: ldm.w r0, {r0, r1} 113 ; HARD: vldr d0, [r0] 114 %0 = load double, double* %a, align 8 115 ret double %0 116 } 117 118 define void @store_f(float* %a, float %b) { 119 entry: 120 ; CHECK-LABEL: store_f: 121 ; NONE: str r1, [r0] 122 ; HARD: vstr s0, [r0] 123 store float %b, float* %a, align 4 124 ret void 125 } 126 127 define void @store_d(double* %a, double %b) { 128 entry: 129 ; CHECK-LABEL: store_d: 130 ; NONE: mov r1, r3 131 ; NONE: str r2, [r0] 132 ; NONE: str r1, [r0, #4] 133 ; HARD: vstr d0, [r0] 134 store double %b, double* %a, align 8 135 ret void 136 } 137 138 define double @f_to_d(float %a) { 139 ; CHECK-LABEL: f_to_d: 140 ; NONE: bl __aeabi_f2d 141 ; SP: bl __aeabi_f2d 142 ; DP: vcvt.f64.f32 d0, s0 143 %1 = fpext float %a to double 144 ret double %1 145 } 146 147 define float @d_to_f(double %a) { 148 ; CHECK-LABEL: d_to_f: 149 ; NONE: bl __aeabi_d2f 150 ; SP: bl __aeabi_d2f 151 ; DP: vcvt.f32.f64 s0, d0 152 %1 = fptrunc double %a to float 153 ret float %1 154 } 155 156 define i32 @f_to_si(float %a) { 157 ; CHECK-LABEL: f_to_si: 158 ; NONE: bl __aeabi_f2iz 159 ; HARD: vcvt.s32.f32 s0, s0 160 ; HARD: vmov r0, s0 161 %1 = fptosi float %a to i32 162 ret i32 %1 163 } 164 165 define i32 @d_to_si(double %a) { 166 ; CHECK-LABEL: d_to_si: 167 ; NONE: bl __aeabi_d2iz 168 ; SP: vmov r0, r1, d0 169 ; SP: bl __aeabi_d2iz 170 ; DP: vcvt.s32.f64 s0, d0 171 ; DP: vmov r0, s0 172 %1 = fptosi double %a to i32 173 ret i32 %1 174 } 175 176 define i32 @f_to_ui(float %a) { 177 ; CHECK-LABEL: f_to_ui: 178 ; NONE: bl __aeabi_f2uiz 179 ; HARD: vcvt.u32.f32 s0, s0 180 ; HARD: vmov r0, s0 181 %1 = fptoui float %a to i32 182 ret i32 %1 183 } 184 185 define i32 @d_to_ui(double %a) { 186 ; CHECK-LABEL: d_to_ui: 187 ; NONE: bl __aeabi_d2uiz 188 ; SP: vmov r0, r1, d0 189 ; SP: bl __aeabi_d2uiz 190 ; DP: vcvt.u32.f64 s0, d0 191 ; DP: vmov r0, s0 192 %1 = fptoui double %a to i32 193 ret i32 %1 194 } 195 196 define float @si_to_f(i32 %a) { 197 ; CHECK-LABEL: si_to_f: 198 ; NONE: bl __aeabi_i2f 199 ; HARD: vcvt.f32.s32 s0, s0 200 %1 = sitofp i32 %a to float 201 ret float %1 202 } 203 204 define double @si_to_d(i32 %a) { 205 ; CHECK-LABEL: si_to_d: 206 ; NONE: bl __aeabi_i2d 207 ; SP: bl __aeabi_i2d 208 ; DP: vcvt.f64.s32 d0, s0 209 %1 = sitofp i32 %a to double 210 ret double %1 211 } 212 213 define float @ui_to_f(i32 %a) { 214 ; CHECK-LABEL: ui_to_f: 215 ; NONE: bl __aeabi_ui2f 216 ; HARD: vcvt.f32.u32 s0, s0 217 %1 = uitofp i32 %a to float 218 ret float %1 219 } 220 221 define double @ui_to_d(i32 %a) { 222 ; CHECK-LABEL: ui_to_d: 223 ; NONE: bl __aeabi_ui2d 224 ; SP: bl __aeabi_ui2d 225 ; DP: vcvt.f64.u32 d0, s0 226 %1 = uitofp i32 %a to double 227 ret double %1 228 } 229 230 define float @bitcast_i_to_f(i32 %a) { 231 ; CHECK-LABEL: bitcast_i_to_f: 232 ; NONE-NOT: mov 233 ; HARD: vmov s0, r0 234 %1 = bitcast i32 %a to float 235 ret float %1 236 } 237 238 define double @bitcast_i_to_d(i64 %a) { 239 ; CHECK-LABEL: bitcast_i_to_d: 240 ; NONE-NOT: mov 241 ; HARD: vmov d0, r0, r1 242 %1 = bitcast i64 %a to double 243 ret double %1 244 } 245 246 define i32 @bitcast_f_to_i(float %a) { 247 ; CHECK-LABEL: bitcast_f_to_i: 248 ; NONE-NOT: mov 249 ; HARD: vmov r0, s0 250 %1 = bitcast float %a to i32 251 ret i32 %1 252 } 253 254 define i64 @bitcast_d_to_i(double %a) { 255 ; CHECK-LABEL: bitcast_d_to_i: 256 ; NONE-NOT: mov 257 ; HARD: vmov r0, r1, d0 258 %1 = bitcast double %a to i64 259 ret i64 %1 260 } 261 262 define float @select_f(float %a, float %b, i1 %c) { 263 ; CHECK-LABEL: select_f: 264 ; NONE: tst.w r2, #1 265 ; NONE: moveq r0, r1 266 ; HARD: tst.w r0, #1 267 ; VFP4-ALL: vmovne.f32 s1, s0 268 ; VFP4-ALL: vmov.f32 s0, s1 269 ; FP-ARMv8: vseleq.f32 s0, s1, s0 270 %1 = select i1 %c, float %a, float %b 271 ret float %1 272 } 273 274 define double @select_d(double %a, double %b, i1 %c) { 275 ; CHECK-LABEL: select_d: 276 ; NONE: ldr.w [[REG:r[0-9]+]], [sp] 277 ; NONE: ands [[REG]], [[REG]], #1 278 ; NONE: moveq r0, r2 279 ; NONE: moveq r1, r3 280 ; SP: ands r0, r0, #1 281 ; SP-DAG: vmov [[ALO:r[0-9]+]], [[AHI:r[0-9]+]], d0 282 ; SP-DAG: vmov [[BLO:r[0-9]+]], [[BHI:r[0-9]+]], d1 283 ; SP: itt ne 284 ; SP-DAG: movne [[BLO]], [[ALO]] 285 ; SP-DAG: movne [[BHI]], [[AHI]] 286 ; SP: vmov d0, [[BLO]], [[BHI]] 287 ; DP: tst.w r0, #1 288 ; VFP4-DP: vmovne.f64 d1, d0 289 ; VFP4-DP: vmov.f64 d0, d1 290 ; FP-ARMV8: vseleq.f64 d0, d1, d0 291 %1 = select i1 %c, double %a, double %b 292 ret double %1 293 } 294