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 6define float @add_f(float %a, float %b) { 7entry: 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 15define double @add_d(double %a, double %b) { 16entry: 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 25define float @sub_f(float %a, float %b) { 26entry: 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 34define double @sub_d(double %a, double %b) { 35entry: 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 44define float @mul_f(float %a, float %b) { 45entry: 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 53define double @mul_d(double %a, double %b) { 54entry: 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 63define float @div_f(float %a, float %b) { 64entry: 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 72define double @div_d(double %a, double %b) { 73entry: 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 82define float @rem_f(float %a, float %b) { 83entry: 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 91define double @rem_d(double %a, double %b) { 92entry: 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 100define float @load_f(float* %a) { 101entry: 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 109define double @load_d(double* %a) { 110entry: 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 118define void @store_f(float* %a, float %b) { 119entry: 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 127define void @store_d(double* %a, double %b) { 128entry: 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 138define 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 147define 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 156define 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 165define 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 176define 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 185define 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 196define 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 204define 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 213define 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 221define 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 230define 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 238define 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 246define 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 254define 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 262define 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 274define 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