1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -target-abi ilp32f -mattr=+zfa,+zfh < %s \ 3; RUN: | FileCheck %s 4; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+zfa,+zfh < %s \ 5; RUN: | FileCheck %s 6; RUN: llc -mtriple=riscv32 -target-abi ilp32f -mattr=+zfa,+zfhmin < %s \ 7; RUN: | FileCheck %s --check-prefix=ZFHMIN 8; RUN: llc -mtriple=riscv64 -target-abi lp64f -mattr=+zfa,+zfhmin < %s \ 9; RUN: | FileCheck %s --check-prefix=ZFHMIN 10 11declare half @llvm.minimum.f16(half, half) 12 13define half @fminm_h(half %a, half %b) nounwind { 14; CHECK-LABEL: fminm_h: 15; CHECK: # %bb.0: 16; CHECK-NEXT: fminm.h fa0, fa0, fa1 17; CHECK-NEXT: ret 18; 19; ZFHMIN-LABEL: fminm_h: 20; ZFHMIN: # %bb.0: 21; ZFHMIN-NEXT: fcvt.s.h fa5, fa1 22; ZFHMIN-NEXT: fcvt.s.h fa4, fa0 23; ZFHMIN-NEXT: fminm.s fa5, fa4, fa5 24; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 25; ZFHMIN-NEXT: ret 26 %1 = call half @llvm.minimum.f16(half %a, half %b) 27 ret half %1 28} 29 30declare half @llvm.maximum.f16(half, half) 31 32define half @fmaxm_h(half %a, half %b) nounwind { 33; CHECK-LABEL: fmaxm_h: 34; CHECK: # %bb.0: 35; CHECK-NEXT: fmaxm.h fa0, fa0, fa1 36; CHECK-NEXT: ret 37; 38; ZFHMIN-LABEL: fmaxm_h: 39; ZFHMIN: # %bb.0: 40; ZFHMIN-NEXT: fcvt.s.h fa5, fa1 41; ZFHMIN-NEXT: fcvt.s.h fa4, fa0 42; ZFHMIN-NEXT: fmaxm.s fa5, fa4, fa5 43; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 44; ZFHMIN-NEXT: ret 45 %1 = tail call half @llvm.maximum.f16(half %a, half %b) 46 ret half %1 47} 48 49define half @fround_h_1(half %a) nounwind { 50; CHECK-LABEL: fround_h_1: 51; CHECK: # %bb.0: 52; CHECK-NEXT: fround.h fa0, fa0, rmm 53; CHECK-NEXT: ret 54; 55; ZFHMIN-LABEL: fround_h_1: 56; ZFHMIN: # %bb.0: 57; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 58; ZFHMIN-NEXT: fround.s fa5, fa5, rmm 59; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 60; ZFHMIN-NEXT: ret 61 %call = tail call half @llvm.round.f16(half %a) nounwind readnone 62 ret half %call 63} 64 65declare half @llvm.round.f16(half) nounwind readnone 66 67 68define half @fround_h_2(half %a) nounwind { 69; CHECK-LABEL: fround_h_2: 70; CHECK: # %bb.0: 71; CHECK-NEXT: fround.h fa0, fa0, rdn 72; CHECK-NEXT: ret 73; 74; ZFHMIN-LABEL: fround_h_2: 75; ZFHMIN: # %bb.0: 76; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 77; ZFHMIN-NEXT: fround.s fa5, fa5, rdn 78; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 79; ZFHMIN-NEXT: ret 80 %call = tail call half @llvm.floor.f16(half %a) nounwind readnone 81 ret half %call 82} 83 84declare half @llvm.floor.f16(half) nounwind readnone 85 86 87define half @fround_h_3(half %a) nounwind { 88; CHECK-LABEL: fround_h_3: 89; CHECK: # %bb.0: 90; CHECK-NEXT: fround.h fa0, fa0, rup 91; CHECK-NEXT: ret 92; 93; ZFHMIN-LABEL: fround_h_3: 94; ZFHMIN: # %bb.0: 95; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 96; ZFHMIN-NEXT: fround.s fa5, fa5, rup 97; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 98; ZFHMIN-NEXT: ret 99 %call = tail call half @llvm.ceil.f16(half %a) nounwind readnone 100 ret half %call 101} 102 103declare half @llvm.ceil.f16(half) nounwind readnone 104 105 106define half @fround_h_4(half %a) nounwind { 107; CHECK-LABEL: fround_h_4: 108; CHECK: # %bb.0: 109; CHECK-NEXT: fround.h fa0, fa0, rtz 110; CHECK-NEXT: ret 111; 112; ZFHMIN-LABEL: fround_h_4: 113; ZFHMIN: # %bb.0: 114; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 115; ZFHMIN-NEXT: fround.s fa5, fa5, rtz 116; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 117; ZFHMIN-NEXT: ret 118 %call = tail call half @llvm.trunc.f16(half %a) nounwind readnone 119 ret half %call 120} 121 122declare half @llvm.trunc.f16(half) nounwind readnone 123 124 125define half @fround_h_5(half %a) nounwind { 126; CHECK-LABEL: fround_h_5: 127; CHECK: # %bb.0: 128; CHECK-NEXT: fround.h fa0, fa0 129; CHECK-NEXT: ret 130; 131; ZFHMIN-LABEL: fround_h_5: 132; ZFHMIN: # %bb.0: 133; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 134; ZFHMIN-NEXT: fround.s fa5, fa5 135; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 136; ZFHMIN-NEXT: ret 137 %call = tail call half @llvm.nearbyint.f16(half %a) nounwind readnone 138 ret half %call 139} 140 141declare half @llvm.nearbyint.f16(half) nounwind readnone 142 143define half @fround_h_6(half %a) nounwind { 144; CHECK-LABEL: fround_h_6: 145; CHECK: # %bb.0: 146; CHECK-NEXT: fround.h fa0, fa0, rne 147; CHECK-NEXT: ret 148; 149; ZFHMIN-LABEL: fround_h_6: 150; ZFHMIN: # %bb.0: 151; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 152; ZFHMIN-NEXT: fround.s fa5, fa5, rne 153; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 154; ZFHMIN-NEXT: ret 155 %call = tail call half @llvm.roundeven.f16(half %a) nounwind readnone 156 ret half %call 157} 158 159declare half @llvm.roundeven.f16(half) nounwind readnone 160 161 162define half @froundnx_h(half %a) nounwind { 163; CHECK-LABEL: froundnx_h: 164; CHECK: # %bb.0: 165; CHECK-NEXT: froundnx.h fa0, fa0 166; CHECK-NEXT: ret 167; 168; ZFHMIN-LABEL: froundnx_h: 169; ZFHMIN: # %bb.0: 170; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 171; ZFHMIN-NEXT: froundnx.s fa5, fa5 172; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 173; ZFHMIN-NEXT: ret 174 %call = tail call half @llvm.rint.f16(half %a) nounwind readnone 175 ret half %call 176} 177 178declare half @llvm.rint.f16(half) nounwind readnone 179 180declare i1 @llvm.experimental.constrained.fcmp.f16(half, half, metadata, metadata) 181 182define i32 @fcmp_olt_q(half %a, half %b) nounwind strictfp { 183; CHECK-LABEL: fcmp_olt_q: 184; CHECK: # %bb.0: 185; CHECK-NEXT: fltq.h a0, fa0, fa1 186; CHECK-NEXT: ret 187; 188; ZFHMIN-LABEL: fcmp_olt_q: 189; ZFHMIN: # %bb.0: 190; ZFHMIN-NEXT: fcvt.s.h fa5, fa1 191; ZFHMIN-NEXT: fcvt.s.h fa4, fa0 192; ZFHMIN-NEXT: fltq.s a0, fa4, fa5 193; ZFHMIN-NEXT: ret 194 %1 = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"olt", metadata !"fpexcept.strict") strictfp 195 %2 = zext i1 %1 to i32 196 ret i32 %2 197} 198 199define i32 @fcmp_ole_q(half %a, half %b) nounwind strictfp { 200; CHECK-LABEL: fcmp_ole_q: 201; CHECK: # %bb.0: 202; CHECK-NEXT: fleq.h a0, fa0, fa1 203; CHECK-NEXT: ret 204; 205; ZFHMIN-LABEL: fcmp_ole_q: 206; ZFHMIN: # %bb.0: 207; ZFHMIN-NEXT: fcvt.s.h fa5, fa1 208; ZFHMIN-NEXT: fcvt.s.h fa4, fa0 209; ZFHMIN-NEXT: fleq.s a0, fa4, fa5 210; ZFHMIN-NEXT: ret 211 %1 = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"ole", metadata !"fpexcept.strict") strictfp 212 %2 = zext i1 %1 to i32 213 ret i32 %2 214} 215 216define i32 @fcmp_one_q(half %a, half %b) nounwind strictfp { 217; CHECK-LABEL: fcmp_one_q: 218; CHECK: # %bb.0: 219; CHECK-NEXT: fltq.h a0, fa0, fa1 220; CHECK-NEXT: fltq.h a1, fa1, fa0 221; CHECK-NEXT: or a0, a1, a0 222; CHECK-NEXT: ret 223; 224; ZFHMIN-LABEL: fcmp_one_q: 225; ZFHMIN: # %bb.0: 226; ZFHMIN-NEXT: fcvt.s.h fa5, fa1 227; ZFHMIN-NEXT: fcvt.s.h fa4, fa0 228; ZFHMIN-NEXT: fltq.s a0, fa4, fa5 229; ZFHMIN-NEXT: fltq.s a1, fa5, fa4 230; ZFHMIN-NEXT: or a0, a1, a0 231; ZFHMIN-NEXT: ret 232 %1 = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"one", metadata !"fpexcept.strict") strictfp 233 %2 = zext i1 %1 to i32 234 ret i32 %2 235} 236 237define i32 @fcmp_ueq_q(half %a, half %b) nounwind strictfp { 238; CHECK-LABEL: fcmp_ueq_q: 239; CHECK: # %bb.0: 240; CHECK-NEXT: fltq.h a0, fa0, fa1 241; CHECK-NEXT: fltq.h a1, fa1, fa0 242; CHECK-NEXT: or a0, a1, a0 243; CHECK-NEXT: xori a0, a0, 1 244; CHECK-NEXT: ret 245; 246; ZFHMIN-LABEL: fcmp_ueq_q: 247; ZFHMIN: # %bb.0: 248; ZFHMIN-NEXT: fcvt.s.h fa5, fa1 249; ZFHMIN-NEXT: fcvt.s.h fa4, fa0 250; ZFHMIN-NEXT: fltq.s a0, fa4, fa5 251; ZFHMIN-NEXT: fltq.s a1, fa5, fa4 252; ZFHMIN-NEXT: or a0, a1, a0 253; ZFHMIN-NEXT: xori a0, a0, 1 254; ZFHMIN-NEXT: ret 255 %1 = call i1 @llvm.experimental.constrained.fcmp.f16(half %a, half %b, metadata !"ueq", metadata !"fpexcept.strict") strictfp 256 %2 = zext i1 %1 to i32 257 ret i32 %2 258} 259 260define half @fadd_neg_0p5(half %x) { 261; CHECK-LABEL: fadd_neg_0p5: 262; CHECK: # %bb.0: 263; CHECK-NEXT: fli.h fa5, 0.5 264; CHECK-NEXT: fsub.h fa0, fa0, fa5 265; CHECK-NEXT: ret 266; 267; ZFHMIN-LABEL: fadd_neg_0p5: 268; ZFHMIN: # %bb.0: 269; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 270; ZFHMIN-NEXT: fli.s fa4, 0.5 271; ZFHMIN-NEXT: fsub.s fa5, fa5, fa4 272; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 273; ZFHMIN-NEXT: ret 274 %a = fadd half %x, -0.5 275 ret half %a 276} 277 278define half @fma_neg_addend(half %x, half %y) nounwind { 279; CHECK-LABEL: fma_neg_addend: 280; CHECK: # %bb.0: 281; CHECK-NEXT: fli.h fa5, 0.5 282; CHECK-NEXT: fmsub.h fa0, fa0, fa1, fa5 283; CHECK-NEXT: ret 284; 285; ZFHMIN-LABEL: fma_neg_addend: 286; ZFHMIN: # %bb.0: 287; ZFHMIN-NEXT: fcvt.s.h fa5, fa1 288; ZFHMIN-NEXT: fcvt.s.h fa4, fa0 289; ZFHMIN-NEXT: fli.s fa3, 0.5 290; ZFHMIN-NEXT: fmsub.s fa5, fa4, fa5, fa3 291; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 292; ZFHMIN-NEXT: ret 293 %a = call half @llvm.fma.f32(half %x, half %y, half -0.5) 294 ret half %a 295} 296 297define half @fma_neg_multiplicand(half %x, half %y) nounwind { 298; CHECK-LABEL: fma_neg_multiplicand: 299; CHECK: # %bb.0: 300; CHECK-NEXT: fli.h fa5, 0.125 301; CHECK-NEXT: fnmsub.h fa0, fa5, fa0, fa1 302; CHECK-NEXT: ret 303; 304; ZFHMIN-LABEL: fma_neg_multiplicand: 305; ZFHMIN: # %bb.0: 306; ZFHMIN-NEXT: fcvt.s.h fa5, fa1 307; ZFHMIN-NEXT: fcvt.s.h fa4, fa0 308; ZFHMIN-NEXT: fli.s fa3, 0.125 309; ZFHMIN-NEXT: fnmsub.s fa5, fa3, fa4, fa5 310; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 311; ZFHMIN-NEXT: ret 312 %a = call half @llvm.fma.f32(half %x, half -0.125, half %y) 313 ret half %a 314} 315 316define half @fma_neg_addend_multiplicand(half %x) nounwind { 317; CHECK-LABEL: fma_neg_addend_multiplicand: 318; CHECK: # %bb.0: 319; CHECK-NEXT: fli.h fa5, 0.25 320; CHECK-NEXT: fli.h fa4, 0.5 321; CHECK-NEXT: fnmadd.h fa0, fa4, fa0, fa5 322; CHECK-NEXT: ret 323; 324; ZFHMIN-LABEL: fma_neg_addend_multiplicand: 325; ZFHMIN: # %bb.0: 326; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 327; ZFHMIN-NEXT: fli.s fa4, 0.25 328; ZFHMIN-NEXT: fli.s fa3, 0.5 329; ZFHMIN-NEXT: fnmadd.s fa5, fa3, fa5, fa4 330; ZFHMIN-NEXT: fcvt.h.s fa0, fa5 331; ZFHMIN-NEXT: ret 332 %a = call half @llvm.fma.f32(half %x, half -0.5, half -0.25) 333 ret half %a 334} 335 336define half @select_loadfpimm(half %x) nounwind { 337; CHECK-LABEL: select_loadfpimm: 338; CHECK: # %bb.0: # %entry 339; CHECK-NEXT: fmv.h.x fa5, zero 340; CHECK-NEXT: fle.h a0, fa5, fa0 341; CHECK-NEXT: fli.h fa0, 0.5 342; CHECK-NEXT: bnez a0, .LBB17_2 343; CHECK-NEXT: # %bb.1: 344; CHECK-NEXT: fneg.h fa0, fa0 345; CHECK-NEXT: .LBB17_2: # %entry 346; CHECK-NEXT: ret 347; 348; ZFHMIN-LABEL: select_loadfpimm: 349; ZFHMIN: # %bb.0: # %entry 350; ZFHMIN-NEXT: fcvt.s.h fa5, fa0 351; ZFHMIN-NEXT: fmv.w.x fa4, zero 352; ZFHMIN-NEXT: fle.s a0, fa4, fa5 353; ZFHMIN-NEXT: xori a0, a0, 1 354; ZFHMIN-NEXT: slli a0, a0, 1 355; ZFHMIN-NEXT: lui a1, %hi(.LCPI17_0) 356; ZFHMIN-NEXT: addi a1, a1, %lo(.LCPI17_0) 357; ZFHMIN-NEXT: add a0, a1, a0 358; ZFHMIN-NEXT: flh fa0, 0(a0) 359; ZFHMIN-NEXT: ret 360entry: 361 %cmp = fcmp ult half %x, 0.000000e+00 362 %sel = select i1 %cmp, half -5.000000e-01, half 5.000000e-01 363 ret half %sel 364} 365