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