430 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=thumbv8.1-m-none-eabi -mattr=+fullfp16 -fp-contract=fast | FileCheck %s3; RUN: llc < %s -mtriple=thumbv8.1-m-none-eabi -mattr=+fullfp16,+slowfpvfmx -fp-contract=fast | FileCheck %s -check-prefix=DONT-FUSE4 5; Check generated fp16 fused MAC and MLS.6 7define arm_aapcs_vfpcc void @fusedMACTest2(ptr %a1, ptr %a2, ptr %a3) {8; CHECK-LABEL: fusedMACTest2:9; CHECK: @ %bb.0:10; CHECK-NEXT: vldr.16 s0, [r1]11; CHECK-NEXT: vldr.16 s2, [r0]12; CHECK-NEXT: vldr.16 s4, [r2]13; CHECK-NEXT: vfma.f16 s4, s2, s014; CHECK-NEXT: vstr.16 s4, [r0]15; CHECK-NEXT: bx lr16;17; DONT-FUSE-LABEL: fusedMACTest2:18; DONT-FUSE: @ %bb.0:19; DONT-FUSE-NEXT: vldr.16 s0, [r1]20; DONT-FUSE-NEXT: vldr.16 s2, [r0]21; DONT-FUSE-NEXT: vmul.f16 s0, s2, s022; DONT-FUSE-NEXT: vldr.16 s2, [r2]23; DONT-FUSE-NEXT: vadd.f16 s0, s0, s224; DONT-FUSE-NEXT: vstr.16 s0, [r0]25; DONT-FUSE-NEXT: bx lr26 27 %f1 = load half, ptr %a1, align 228 %f2 = load half, ptr %a2, align 229 %f3 = load half, ptr %a3, align 230 %1 = fmul half %f1, %f231 %2 = fadd half %1, %f332 store half %2, ptr %a1, align 233 ret void34}35 36define arm_aapcs_vfpcc void @fusedMACTest4(ptr %a1, ptr %a2, ptr %a3) {37; CHECK-LABEL: fusedMACTest4:38; CHECK: @ %bb.0:39; CHECK-NEXT: vldr.16 s0, [r2]40; CHECK-NEXT: vldr.16 s2, [r1]41; CHECK-NEXT: vldr.16 s4, [r0]42; CHECK-NEXT: vfms.f16 s4, s2, s043; CHECK-NEXT: vstr.16 s4, [r0]44; CHECK-NEXT: bx lr45;46; DONT-FUSE-LABEL: fusedMACTest4:47; DONT-FUSE: @ %bb.0:48; DONT-FUSE-NEXT: vldr.16 s0, [r2]49; DONT-FUSE-NEXT: vldr.16 s2, [r1]50; DONT-FUSE-NEXT: vmul.f16 s0, s2, s051; DONT-FUSE-NEXT: vldr.16 s2, [r0]52; DONT-FUSE-NEXT: vsub.f16 s0, s2, s053; DONT-FUSE-NEXT: vstr.16 s0, [r0]54; DONT-FUSE-NEXT: bx lr55 56 %f1 = load half, ptr %a1, align 257 %f2 = load half, ptr %a2, align 258 %f3 = load half, ptr %a3, align 259 %1 = fmul half %f2, %f360 %2 = fsub half %f1, %161 store half %2, ptr %a1, align 262 ret void63}64 65define arm_aapcs_vfpcc void @fusedMACTest6(ptr %a1, ptr %a2, ptr %a3) {66; CHECK-LABEL: fusedMACTest6:67; CHECK: @ %bb.0:68; CHECK-NEXT: vldr.16 s0, [r1]69; CHECK-NEXT: vldr.16 s2, [r0]70; CHECK-NEXT: vldr.16 s4, [r2]71; CHECK-NEXT: vfnma.f16 s4, s2, s072; CHECK-NEXT: vstr.16 s4, [r0]73; CHECK-NEXT: bx lr74;75; DONT-FUSE-LABEL: fusedMACTest6:76; DONT-FUSE: @ %bb.0:77; DONT-FUSE-NEXT: vldr.16 s0, [r1]78; DONT-FUSE-NEXT: vldr.16 s2, [r0]79; DONT-FUSE-NEXT: vnmul.f16 s0, s2, s080; DONT-FUSE-NEXT: vldr.16 s2, [r2]81; DONT-FUSE-NEXT: vsub.f16 s0, s0, s282; DONT-FUSE-NEXT: vstr.16 s0, [r0]83; DONT-FUSE-NEXT: bx lr84 85 %f1 = load half, ptr %a1, align 286 %f2 = load half, ptr %a2, align 287 %f3 = load half, ptr %a3, align 288 %1 = fmul half %f1, %f289 %2 = fsub half -0.0, %190 %3 = fsub half %2, %f391 store half %3, ptr %a1, align 292 ret void93}94 95define arm_aapcs_vfpcc void @fusedMACTest8(ptr %a1, ptr %a2, ptr %a3) {96; CHECK-LABEL: fusedMACTest8:97; CHECK: @ %bb.0:98; CHECK-NEXT: vldr.16 s0, [r1]99; CHECK-NEXT: vldr.16 s2, [r0]100; CHECK-NEXT: vldr.16 s4, [r2]101; CHECK-NEXT: vfnms.f16 s4, s2, s0102; CHECK-NEXT: vstr.16 s4, [r0]103; CHECK-NEXT: bx lr104;105; DONT-FUSE-LABEL: fusedMACTest8:106; DONT-FUSE: @ %bb.0:107; DONT-FUSE-NEXT: vldr.16 s0, [r1]108; DONT-FUSE-NEXT: vldr.16 s2, [r0]109; DONT-FUSE-NEXT: vmul.f16 s0, s2, s0110; DONT-FUSE-NEXT: vldr.16 s2, [r2]111; DONT-FUSE-NEXT: vsub.f16 s0, s0, s2112; DONT-FUSE-NEXT: vstr.16 s0, [r0]113; DONT-FUSE-NEXT: bx lr114 115 %f1 = load half, ptr %a1, align 2116 %f2 = load half, ptr %a2, align 2117 %f3 = load half, ptr %a3, align 2118 %1 = fmul half %f1, %f2119 %2 = fsub half %1, %f3120 store half %2, ptr %a1, align 2121 ret void122}123 124define arm_aapcs_vfpcc void @test_fma_f16(ptr %aa, ptr %bb, ptr %cc) nounwind readnone ssp {125; CHECK-LABEL: test_fma_f16:126; CHECK: @ %bb.0: @ %entry127; CHECK-NEXT: vldr.16 s0, [r1]128; CHECK-NEXT: vldr.16 s2, [r0]129; CHECK-NEXT: vldr.16 s4, [r2]130; CHECK-NEXT: vfma.f16 s4, s2, s0131; CHECK-NEXT: vstr.16 s4, [r0]132; CHECK-NEXT: bx lr133;134; DONT-FUSE-LABEL: test_fma_f16:135; DONT-FUSE: @ %bb.0: @ %entry136; DONT-FUSE-NEXT: vldr.16 s0, [r1]137; DONT-FUSE-NEXT: vldr.16 s2, [r0]138; DONT-FUSE-NEXT: vldr.16 s4, [r2]139; DONT-FUSE-NEXT: vfma.f16 s4, s2, s0140; DONT-FUSE-NEXT: vstr.16 s4, [r0]141; DONT-FUSE-NEXT: bx lr142entry:143 %a = load half, ptr %aa, align 2144 %b = load half, ptr %bb, align 2145 %c = load half, ptr %cc, align 2146 %tmp1 = tail call half @llvm.fma.f16(half %a, half %b, half %c) nounwind readnone147 store half %tmp1, ptr %aa, align 2148 ret void149}150 151define arm_aapcs_vfpcc void @test_fnms_f16(ptr %aa, ptr %bb, ptr %cc) nounwind readnone ssp {152; CHECK-LABEL: test_fnms_f16:153; CHECK: @ %bb.0:154; CHECK-NEXT: vldr.16 s0, [r1]155; CHECK-NEXT: vldr.16 s2, [r0]156; CHECK-NEXT: vldr.16 s4, [r2]157; CHECK-NEXT: vfma.f16 s4, s2, s0158; CHECK-NEXT: vstr.16 s4, [r0]159; CHECK-NEXT: bx lr160;161; DONT-FUSE-LABEL: test_fnms_f16:162; DONT-FUSE: @ %bb.0:163; DONT-FUSE-NEXT: vldr.16 s0, [r1]164; DONT-FUSE-NEXT: vldr.16 s2, [r0]165; DONT-FUSE-NEXT: vldr.16 s4, [r2]166; DONT-FUSE-NEXT: vfma.f16 s4, s2, s0167; DONT-FUSE-NEXT: vstr.16 s4, [r0]168; DONT-FUSE-NEXT: bx lr169 170 %a = load half, ptr %aa, align 2171 %b = load half, ptr %bb, align 2172 %c = load half, ptr %cc, align 2173 %tmp2 = fsub half -0.0, %c174 %tmp3 = tail call half @llvm.fma.f16(half %a, half %b, half %c) nounwind readnone175 store half %tmp3, ptr %aa, align 2176 ret void177}178 179define arm_aapcs_vfpcc void @test_fma_const_fold(ptr %aa, ptr %bb) nounwind {180; CHECK-LABEL: test_fma_const_fold:181; CHECK: @ %bb.0:182; CHECK-NEXT: vldr.16 s0, [r1]183; CHECK-NEXT: vldr.16 s2, [r0]184; CHECK-NEXT: vadd.f16 s0, s2, s0185; CHECK-NEXT: vstr.16 s0, [r0]186; CHECK-NEXT: bx lr187;188; DONT-FUSE-LABEL: test_fma_const_fold:189; DONT-FUSE: @ %bb.0:190; DONT-FUSE-NEXT: vldr.16 s0, [r1]191; DONT-FUSE-NEXT: vldr.16 s2, [r0]192; DONT-FUSE-NEXT: vadd.f16 s0, s2, s0193; DONT-FUSE-NEXT: vstr.16 s0, [r0]194; DONT-FUSE-NEXT: bx lr195 196 %a = load half, ptr %aa, align 2197 %b = load half, ptr %bb, align 2198 %ret = call half @llvm.fma.f16(half %a, half 1.0, half %b)199 store half %ret, ptr %aa, align 2200 ret void201}202 203define arm_aapcs_vfpcc void @test_fma_canonicalize(ptr %aa, ptr %bb) nounwind {204; CHECK-LABEL: test_fma_canonicalize:205; CHECK: @ %bb.0:206; CHECK-NEXT: vldr.16 s0, [r0]207; CHECK-NEXT: vldr.16 s2, [r1]208; CHECK-NEXT: vmov.f16 s4, #2.000000e+00209; CHECK-NEXT: vfma.f16 s2, s0, s4210; CHECK-NEXT: vstr.16 s2, [r0]211; CHECK-NEXT: bx lr212;213; DONT-FUSE-LABEL: test_fma_canonicalize:214; DONT-FUSE: @ %bb.0:215; DONT-FUSE-NEXT: vldr.16 s0, [r0]216; DONT-FUSE-NEXT: vldr.16 s2, [r1]217; DONT-FUSE-NEXT: vmov.f16 s4, #2.000000e+00218; DONT-FUSE-NEXT: vfma.f16 s2, s0, s4219; DONT-FUSE-NEXT: vstr.16 s2, [r0]220; DONT-FUSE-NEXT: bx lr221 222 %a = load half, ptr %aa, align 2223 %b = load half, ptr %bb, align 2224 %ret = call half @llvm.fma.f16(half 2.0, half %a, half %b)225 store half %ret, ptr %aa, align 2226 ret void227}228 229define arm_aapcs_vfpcc void @fms1(ptr %a1, ptr %a2, ptr %a3) {230; CHECK-LABEL: fms1:231; CHECK: @ %bb.0:232; CHECK-NEXT: vldr.16 s0, [r1]233; CHECK-NEXT: vldr.16 s2, [r0]234; CHECK-NEXT: vldr.16 s4, [r2]235; CHECK-NEXT: vfms.f16 s4, s2, s0236; CHECK-NEXT: vstr.16 s4, [r0]237; CHECK-NEXT: bx lr238;239; DONT-FUSE-LABEL: fms1:240; DONT-FUSE: @ %bb.0:241; DONT-FUSE-NEXT: vldr.16 s0, [r1]242; DONT-FUSE-NEXT: vldr.16 s2, [r0]243; DONT-FUSE-NEXT: vldr.16 s4, [r2]244; DONT-FUSE-NEXT: vfms.f16 s4, s2, s0245; DONT-FUSE-NEXT: vstr.16 s4, [r0]246; DONT-FUSE-NEXT: bx lr247 248 %f1 = load half, ptr %a1, align 2249 %f2 = load half, ptr %a2, align 2250 %f3 = load half, ptr %a3, align 2251 %s = fsub half -0.0, %f1252 %ret = call half @llvm.fma.f16(half %s, half %f2, half %f3)253 store half %ret, ptr %a1, align 2254 ret void255}256 257define arm_aapcs_vfpcc void @fms2(ptr %a1, ptr %a2, ptr %a3) {258; CHECK-LABEL: fms2:259; CHECK: @ %bb.0:260; CHECK-NEXT: vldr.16 s0, [r1]261; CHECK-NEXT: vldr.16 s2, [r0]262; CHECK-NEXT: vldr.16 s4, [r2]263; CHECK-NEXT: vfms.f16 s4, s2, s0264; CHECK-NEXT: vstr.16 s4, [r0]265; CHECK-NEXT: bx lr266;267; DONT-FUSE-LABEL: fms2:268; DONT-FUSE: @ %bb.0:269; DONT-FUSE-NEXT: vldr.16 s0, [r1]270; DONT-FUSE-NEXT: vldr.16 s2, [r0]271; DONT-FUSE-NEXT: vldr.16 s4, [r2]272; DONT-FUSE-NEXT: vfms.f16 s4, s2, s0273; DONT-FUSE-NEXT: vstr.16 s4, [r0]274; DONT-FUSE-NEXT: bx lr275 276 %f1 = load half, ptr %a1, align 2277 %f2 = load half, ptr %a2, align 2278 %f3 = load half, ptr %a3, align 2279 %s = fsub half -0.0, %f1280 %ret = call half @llvm.fma.f16(half %f2, half %s, half %f3)281 store half %ret, ptr %a1, align 2282 ret void283}284 285define arm_aapcs_vfpcc void @fnma1(ptr %a1, ptr %a2, ptr %a3) {286; CHECK-LABEL: fnma1:287; CHECK: @ %bb.0:288; CHECK-NEXT: vldr.16 s0, [r1]289; CHECK-NEXT: vldr.16 s2, [r0]290; CHECK-NEXT: vldr.16 s4, [r2]291; CHECK-NEXT: vfnma.f16 s4, s2, s0292; CHECK-NEXT: vstr.16 s4, [r0]293; CHECK-NEXT: bx lr294;295; DONT-FUSE-LABEL: fnma1:296; DONT-FUSE: @ %bb.0:297; DONT-FUSE-NEXT: vldr.16 s0, [r1]298; DONT-FUSE-NEXT: vldr.16 s2, [r0]299; DONT-FUSE-NEXT: vldr.16 s4, [r2]300; DONT-FUSE-NEXT: vfnma.f16 s4, s2, s0301; DONT-FUSE-NEXT: vstr.16 s4, [r0]302; DONT-FUSE-NEXT: bx lr303 304 %f1 = load half, ptr %a1, align 2305 %f2 = load half, ptr %a2, align 2306 %f3 = load half, ptr %a3, align 2307 %fma = call half @llvm.fma.f16(half %f1, half %f2, half %f3)308 %n1 = fsub half -0.0, %fma309 store half %n1, ptr %a1, align 2310 ret void311}312 313define arm_aapcs_vfpcc void @fnma2(ptr %a1, ptr %a2, ptr %a3) {314; CHECK-LABEL: fnma2:315; CHECK: @ %bb.0:316; CHECK-NEXT: vldr.16 s0, [r1]317; CHECK-NEXT: vldr.16 s2, [r0]318; CHECK-NEXT: vldr.16 s4, [r2]319; CHECK-NEXT: vfnma.f16 s4, s2, s0320; CHECK-NEXT: vstr.16 s4, [r0]321; CHECK-NEXT: bx lr322;323; DONT-FUSE-LABEL: fnma2:324; DONT-FUSE: @ %bb.0:325; DONT-FUSE-NEXT: vldr.16 s0, [r1]326; DONT-FUSE-NEXT: vldr.16 s2, [r0]327; DONT-FUSE-NEXT: vldr.16 s4, [r2]328; DONT-FUSE-NEXT: vfnma.f16 s4, s2, s0329; DONT-FUSE-NEXT: vstr.16 s4, [r0]330; DONT-FUSE-NEXT: bx lr331 332 %f1 = load half, ptr %a1, align 2333 %f2 = load half, ptr %a2, align 2334 %f3 = load half, ptr %a3, align 2335 %n1 = fsub half -0.0, %f1336 %n3 = fsub half -0.0, %f3337 %ret = call half @llvm.fma.f16(half %n1, half %f2, half %n3)338 store half %ret, ptr %a1, align 2339 ret void340}341 342define arm_aapcs_vfpcc void @fnms1(ptr %a1, ptr %a2, ptr %a3) {343; CHECK-LABEL: fnms1:344; CHECK: @ %bb.0:345; CHECK-NEXT: vldr.16 s0, [r1]346; CHECK-NEXT: vldr.16 s2, [r0]347; CHECK-NEXT: vldr.16 s4, [r2]348; CHECK-NEXT: vfnms.f16 s4, s2, s0349; CHECK-NEXT: vstr.16 s4, [r0]350; CHECK-NEXT: bx lr351;352; DONT-FUSE-LABEL: fnms1:353; DONT-FUSE: @ %bb.0:354; DONT-FUSE-NEXT: vldr.16 s0, [r1]355; DONT-FUSE-NEXT: vldr.16 s2, [r0]356; DONT-FUSE-NEXT: vldr.16 s4, [r2]357; DONT-FUSE-NEXT: vfnms.f16 s4, s2, s0358; DONT-FUSE-NEXT: vstr.16 s4, [r0]359; DONT-FUSE-NEXT: bx lr360 361 %f1 = load half, ptr %a1, align 2362 %f2 = load half, ptr %a2, align 2363 %f3 = load half, ptr %a3, align 2364 %n3 = fsub half -0.0, %f3365 %ret = call half @llvm.fma.f16(half %f1, half %f2, half %n3)366 store half %ret, ptr %a1, align 2367 ret void368}369 370define arm_aapcs_vfpcc void @fnms2(ptr %a1, ptr %a2, ptr %a3) {371; CHECK-LABEL: fnms2:372; CHECK: @ %bb.0:373; CHECK-NEXT: vldr.16 s0, [r1]374; CHECK-NEXT: vldr.16 s2, [r0]375; CHECK-NEXT: vldr.16 s4, [r2]376; CHECK-NEXT: vfnms.f16 s4, s2, s0377; CHECK-NEXT: vstr.16 s4, [r0]378; CHECK-NEXT: bx lr379;380; DONT-FUSE-LABEL: fnms2:381; DONT-FUSE: @ %bb.0:382; DONT-FUSE-NEXT: vldr.16 s0, [r1]383; DONT-FUSE-NEXT: vldr.16 s2, [r0]384; DONT-FUSE-NEXT: vldr.16 s4, [r2]385; DONT-FUSE-NEXT: vfnms.f16 s4, s2, s0386; DONT-FUSE-NEXT: vstr.16 s4, [r0]387; DONT-FUSE-NEXT: bx lr388 389 %f1 = load half, ptr %a1, align 2390 %f2 = load half, ptr %a2, align 2391 %f3 = load half, ptr %a3, align 2392 %n1 = fsub half -0.0, %f1393 %fma = call half @llvm.fma.f16(half %n1, half %f2, half %f3)394 %n = fsub half -0.0, %fma395 store half %n, ptr %a1, align 2396 ret void397}398 399define arm_aapcs_vfpcc void @fnms3(ptr %a1, ptr %a2, ptr %a3) {400; CHECK-LABEL: fnms3:401; CHECK: @ %bb.0:402; CHECK-NEXT: vldr.16 s0, [r0]403; CHECK-NEXT: vldr.16 s2, [r1]404; CHECK-NEXT: vldr.16 s4, [r2]405; CHECK-NEXT: vfnms.f16 s4, s2, s0406; CHECK-NEXT: vstr.16 s4, [r0]407; CHECK-NEXT: bx lr408;409; DONT-FUSE-LABEL: fnms3:410; DONT-FUSE: @ %bb.0:411; DONT-FUSE-NEXT: vldr.16 s0, [r0]412; DONT-FUSE-NEXT: vldr.16 s2, [r1]413; DONT-FUSE-NEXT: vldr.16 s4, [r2]414; DONT-FUSE-NEXT: vfnms.f16 s4, s2, s0415; DONT-FUSE-NEXT: vstr.16 s4, [r0]416; DONT-FUSE-NEXT: bx lr417 418 %f1 = load half, ptr %a1, align 2419 %f2 = load half, ptr %a2, align 2420 %f3 = load half, ptr %a3, align 2421 %n2 = fsub half -0.0, %f2422 %fma = call half @llvm.fma.f16(half %f1, half %n2, half %f3)423 %n1 = fsub half -0.0, %fma424 store half %n1, ptr %a1, align 2425 ret void426}427 428 429declare half @llvm.fma.f16(half, half, half) nounwind readnone430