1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -mattr=+zfh -verify-machineinstrs \ 3; RUN: -target-abi ilp32f < %s | FileCheck -check-prefix=RV32IZFH %s 4; RUN: llc -mtriple=riscv64 -mattr=+zfh -verify-machineinstrs \ 5; RUN: -target-abi lp64f < %s | FileCheck -check-prefix=RV64IZFH %s 6; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 7; RUN: | FileCheck -check-prefix=RV32I %s 8; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ 9; RUN: | FileCheck -check-prefix=RV64I %s 10 11; These tests are each targeted at a particular RISC-V FPU instruction. 12; Compares and conversions can be found in half-fcmp.ll and half-convert.ll 13; respectively. Some other half-*.ll files in this folder exercise LLVM IR 14; instructions that don't directly match a RISC-V instruction. 15 16define half @fadd_s(half %a, half %b) nounwind { 17; RV32IZFH-LABEL: fadd_s: 18; RV32IZFH: # %bb.0: 19; RV32IZFH-NEXT: fadd.h fa0, fa0, fa1 20; RV32IZFH-NEXT: ret 21; 22; RV64IZFH-LABEL: fadd_s: 23; RV64IZFH: # %bb.0: 24; RV64IZFH-NEXT: fadd.h fa0, fa0, fa1 25; RV64IZFH-NEXT: ret 26; 27; RV32I-LABEL: fadd_s: 28; RV32I: # %bb.0: 29; RV32I-NEXT: addi sp, sp, -16 30; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 31; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 32; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 33; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 34; RV32I-NEXT: mv s2, a1 35; RV32I-NEXT: lui a1, 16 36; RV32I-NEXT: addi s0, a1, -1 37; RV32I-NEXT: and a0, a0, s0 38; RV32I-NEXT: call __gnu_h2f_ieee@plt 39; RV32I-NEXT: mv s1, a0 40; RV32I-NEXT: and a0, s2, s0 41; RV32I-NEXT: call __gnu_h2f_ieee@plt 42; RV32I-NEXT: mv a1, a0 43; RV32I-NEXT: mv a0, s1 44; RV32I-NEXT: call __addsf3@plt 45; RV32I-NEXT: call __gnu_f2h_ieee@plt 46; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 47; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 48; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 49; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 50; RV32I-NEXT: addi sp, sp, 16 51; RV32I-NEXT: ret 52; 53; RV64I-LABEL: fadd_s: 54; RV64I: # %bb.0: 55; RV64I-NEXT: addi sp, sp, -32 56; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 57; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 58; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 59; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 60; RV64I-NEXT: mv s2, a1 61; RV64I-NEXT: lui a1, 16 62; RV64I-NEXT: addiw s0, a1, -1 63; RV64I-NEXT: and a0, a0, s0 64; RV64I-NEXT: call __gnu_h2f_ieee@plt 65; RV64I-NEXT: mv s1, a0 66; RV64I-NEXT: and a0, s2, s0 67; RV64I-NEXT: call __gnu_h2f_ieee@plt 68; RV64I-NEXT: mv a1, a0 69; RV64I-NEXT: mv a0, s1 70; RV64I-NEXT: call __addsf3@plt 71; RV64I-NEXT: call __gnu_f2h_ieee@plt 72; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 73; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 74; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 75; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 76; RV64I-NEXT: addi sp, sp, 32 77; RV64I-NEXT: ret 78 %1 = fadd half %a, %b 79 ret half %1 80} 81 82define half @fsub_s(half %a, half %b) nounwind { 83; RV32IZFH-LABEL: fsub_s: 84; RV32IZFH: # %bb.0: 85; RV32IZFH-NEXT: fsub.h fa0, fa0, fa1 86; RV32IZFH-NEXT: ret 87; 88; RV64IZFH-LABEL: fsub_s: 89; RV64IZFH: # %bb.0: 90; RV64IZFH-NEXT: fsub.h fa0, fa0, fa1 91; RV64IZFH-NEXT: ret 92; 93; RV32I-LABEL: fsub_s: 94; RV32I: # %bb.0: 95; RV32I-NEXT: addi sp, sp, -16 96; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 97; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 98; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 99; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 100; RV32I-NEXT: mv s2, a1 101; RV32I-NEXT: lui a1, 16 102; RV32I-NEXT: addi s0, a1, -1 103; RV32I-NEXT: and a0, a0, s0 104; RV32I-NEXT: call __gnu_h2f_ieee@plt 105; RV32I-NEXT: mv s1, a0 106; RV32I-NEXT: and a0, s2, s0 107; RV32I-NEXT: call __gnu_h2f_ieee@plt 108; RV32I-NEXT: mv a1, a0 109; RV32I-NEXT: mv a0, s1 110; RV32I-NEXT: call __subsf3@plt 111; RV32I-NEXT: call __gnu_f2h_ieee@plt 112; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 113; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 114; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 115; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 116; RV32I-NEXT: addi sp, sp, 16 117; RV32I-NEXT: ret 118; 119; RV64I-LABEL: fsub_s: 120; RV64I: # %bb.0: 121; RV64I-NEXT: addi sp, sp, -32 122; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 123; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 124; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 125; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 126; RV64I-NEXT: mv s2, a1 127; RV64I-NEXT: lui a1, 16 128; RV64I-NEXT: addiw s0, a1, -1 129; RV64I-NEXT: and a0, a0, s0 130; RV64I-NEXT: call __gnu_h2f_ieee@plt 131; RV64I-NEXT: mv s1, a0 132; RV64I-NEXT: and a0, s2, s0 133; RV64I-NEXT: call __gnu_h2f_ieee@plt 134; RV64I-NEXT: mv a1, a0 135; RV64I-NEXT: mv a0, s1 136; RV64I-NEXT: call __subsf3@plt 137; RV64I-NEXT: call __gnu_f2h_ieee@plt 138; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 139; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 140; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 141; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 142; RV64I-NEXT: addi sp, sp, 32 143; RV64I-NEXT: ret 144 %1 = fsub half %a, %b 145 ret half %1 146} 147 148define half @fmul_s(half %a, half %b) nounwind { 149; RV32IZFH-LABEL: fmul_s: 150; RV32IZFH: # %bb.0: 151; RV32IZFH-NEXT: fmul.h fa0, fa0, fa1 152; RV32IZFH-NEXT: ret 153; 154; RV64IZFH-LABEL: fmul_s: 155; RV64IZFH: # %bb.0: 156; RV64IZFH-NEXT: fmul.h fa0, fa0, fa1 157; RV64IZFH-NEXT: ret 158; 159; RV32I-LABEL: fmul_s: 160; RV32I: # %bb.0: 161; RV32I-NEXT: addi sp, sp, -16 162; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 163; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 164; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 165; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 166; RV32I-NEXT: mv s2, a1 167; RV32I-NEXT: lui a1, 16 168; RV32I-NEXT: addi s0, a1, -1 169; RV32I-NEXT: and a0, a0, s0 170; RV32I-NEXT: call __gnu_h2f_ieee@plt 171; RV32I-NEXT: mv s1, a0 172; RV32I-NEXT: and a0, s2, s0 173; RV32I-NEXT: call __gnu_h2f_ieee@plt 174; RV32I-NEXT: mv a1, a0 175; RV32I-NEXT: mv a0, s1 176; RV32I-NEXT: call __mulsf3@plt 177; RV32I-NEXT: call __gnu_f2h_ieee@plt 178; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 179; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 180; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 181; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 182; RV32I-NEXT: addi sp, sp, 16 183; RV32I-NEXT: ret 184; 185; RV64I-LABEL: fmul_s: 186; RV64I: # %bb.0: 187; RV64I-NEXT: addi sp, sp, -32 188; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 189; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 190; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 191; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 192; RV64I-NEXT: mv s2, a1 193; RV64I-NEXT: lui a1, 16 194; RV64I-NEXT: addiw s0, a1, -1 195; RV64I-NEXT: and a0, a0, s0 196; RV64I-NEXT: call __gnu_h2f_ieee@plt 197; RV64I-NEXT: mv s1, a0 198; RV64I-NEXT: and a0, s2, s0 199; RV64I-NEXT: call __gnu_h2f_ieee@plt 200; RV64I-NEXT: mv a1, a0 201; RV64I-NEXT: mv a0, s1 202; RV64I-NEXT: call __mulsf3@plt 203; RV64I-NEXT: call __gnu_f2h_ieee@plt 204; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 205; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 206; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 207; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 208; RV64I-NEXT: addi sp, sp, 32 209; RV64I-NEXT: ret 210 %1 = fmul half %a, %b 211 ret half %1 212} 213 214define half @fdiv_s(half %a, half %b) nounwind { 215; RV32IZFH-LABEL: fdiv_s: 216; RV32IZFH: # %bb.0: 217; RV32IZFH-NEXT: fdiv.h fa0, fa0, fa1 218; RV32IZFH-NEXT: ret 219; 220; RV64IZFH-LABEL: fdiv_s: 221; RV64IZFH: # %bb.0: 222; RV64IZFH-NEXT: fdiv.h fa0, fa0, fa1 223; RV64IZFH-NEXT: ret 224; 225; RV32I-LABEL: fdiv_s: 226; RV32I: # %bb.0: 227; RV32I-NEXT: addi sp, sp, -16 228; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 229; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 230; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 231; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 232; RV32I-NEXT: mv s2, a1 233; RV32I-NEXT: lui a1, 16 234; RV32I-NEXT: addi s0, a1, -1 235; RV32I-NEXT: and a0, a0, s0 236; RV32I-NEXT: call __gnu_h2f_ieee@plt 237; RV32I-NEXT: mv s1, a0 238; RV32I-NEXT: and a0, s2, s0 239; RV32I-NEXT: call __gnu_h2f_ieee@plt 240; RV32I-NEXT: mv a1, a0 241; RV32I-NEXT: mv a0, s1 242; RV32I-NEXT: call __divsf3@plt 243; RV32I-NEXT: call __gnu_f2h_ieee@plt 244; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 245; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 246; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 247; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 248; RV32I-NEXT: addi sp, sp, 16 249; RV32I-NEXT: ret 250; 251; RV64I-LABEL: fdiv_s: 252; RV64I: # %bb.0: 253; RV64I-NEXT: addi sp, sp, -32 254; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 255; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 256; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 257; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 258; RV64I-NEXT: mv s2, a1 259; RV64I-NEXT: lui a1, 16 260; RV64I-NEXT: addiw s0, a1, -1 261; RV64I-NEXT: and a0, a0, s0 262; RV64I-NEXT: call __gnu_h2f_ieee@plt 263; RV64I-NEXT: mv s1, a0 264; RV64I-NEXT: and a0, s2, s0 265; RV64I-NEXT: call __gnu_h2f_ieee@plt 266; RV64I-NEXT: mv a1, a0 267; RV64I-NEXT: mv a0, s1 268; RV64I-NEXT: call __divsf3@plt 269; RV64I-NEXT: call __gnu_f2h_ieee@plt 270; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 271; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 272; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 273; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 274; RV64I-NEXT: addi sp, sp, 32 275; RV64I-NEXT: ret 276 %1 = fdiv half %a, %b 277 ret half %1 278} 279 280declare half @llvm.sqrt.f16(half) 281 282define half @fsqrt_s(half %a) nounwind { 283; RV32IZFH-LABEL: fsqrt_s: 284; RV32IZFH: # %bb.0: 285; RV32IZFH-NEXT: fsqrt.h fa0, fa0 286; RV32IZFH-NEXT: ret 287; 288; RV64IZFH-LABEL: fsqrt_s: 289; RV64IZFH: # %bb.0: 290; RV64IZFH-NEXT: fsqrt.h fa0, fa0 291; RV64IZFH-NEXT: ret 292; 293; RV32I-LABEL: fsqrt_s: 294; RV32I: # %bb.0: 295; RV32I-NEXT: addi sp, sp, -16 296; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 297; RV32I-NEXT: slli a0, a0, 16 298; RV32I-NEXT: srli a0, a0, 16 299; RV32I-NEXT: call __gnu_h2f_ieee@plt 300; RV32I-NEXT: call sqrtf@plt 301; RV32I-NEXT: call __gnu_f2h_ieee@plt 302; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 303; RV32I-NEXT: addi sp, sp, 16 304; RV32I-NEXT: ret 305; 306; RV64I-LABEL: fsqrt_s: 307; RV64I: # %bb.0: 308; RV64I-NEXT: addi sp, sp, -16 309; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 310; RV64I-NEXT: slli a0, a0, 48 311; RV64I-NEXT: srli a0, a0, 48 312; RV64I-NEXT: call __gnu_h2f_ieee@plt 313; RV64I-NEXT: call sqrtf@plt 314; RV64I-NEXT: call __gnu_f2h_ieee@plt 315; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 316; RV64I-NEXT: addi sp, sp, 16 317; RV64I-NEXT: ret 318 %1 = call half @llvm.sqrt.f16(half %a) 319 ret half %1 320} 321 322declare half @llvm.copysign.f16(half, half) 323 324define half @fsgnj_s(half %a, half %b) nounwind { 325; RV32IZFH-LABEL: fsgnj_s: 326; RV32IZFH: # %bb.0: 327; RV32IZFH-NEXT: fsgnj.h fa0, fa0, fa1 328; RV32IZFH-NEXT: ret 329; 330; RV64IZFH-LABEL: fsgnj_s: 331; RV64IZFH: # %bb.0: 332; RV64IZFH-NEXT: fsgnj.h fa0, fa0, fa1 333; RV64IZFH-NEXT: ret 334; 335; RV32I-LABEL: fsgnj_s: 336; RV32I: # %bb.0: 337; RV32I-NEXT: lui a2, 1048568 338; RV32I-NEXT: and a1, a1, a2 339; RV32I-NEXT: slli a0, a0, 17 340; RV32I-NEXT: srli a0, a0, 17 341; RV32I-NEXT: or a0, a0, a1 342; RV32I-NEXT: ret 343; 344; RV64I-LABEL: fsgnj_s: 345; RV64I: # %bb.0: 346; RV64I-NEXT: lui a2, 1048568 347; RV64I-NEXT: and a1, a1, a2 348; RV64I-NEXT: slli a0, a0, 49 349; RV64I-NEXT: srli a0, a0, 49 350; RV64I-NEXT: or a0, a0, a1 351; RV64I-NEXT: ret 352 %1 = call half @llvm.copysign.f16(half %a, half %b) 353 ret half %1 354} 355 356; This function performs extra work to ensure that 357; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor. 358define i32 @fneg_s(half %a, half %b) nounwind { 359; RV32IZFH-LABEL: fneg_s: 360; RV32IZFH: # %bb.0: 361; RV32IZFH-NEXT: fadd.h ft0, fa0, fa0 362; RV32IZFH-NEXT: fneg.h ft1, ft0 363; RV32IZFH-NEXT: feq.h a0, ft0, ft1 364; RV32IZFH-NEXT: ret 365; 366; RV64IZFH-LABEL: fneg_s: 367; RV64IZFH: # %bb.0: 368; RV64IZFH-NEXT: fadd.h ft0, fa0, fa0 369; RV64IZFH-NEXT: fneg.h ft1, ft0 370; RV64IZFH-NEXT: feq.h a0, ft0, ft1 371; RV64IZFH-NEXT: ret 372; 373; RV32I-LABEL: fneg_s: 374; RV32I: # %bb.0: 375; RV32I-NEXT: addi sp, sp, -16 376; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 377; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 378; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 379; RV32I-NEXT: lui a1, 16 380; RV32I-NEXT: addi s1, a1, -1 381; RV32I-NEXT: and a0, a0, s1 382; RV32I-NEXT: call __gnu_h2f_ieee@plt 383; RV32I-NEXT: mv a1, a0 384; RV32I-NEXT: call __addsf3@plt 385; RV32I-NEXT: call __gnu_f2h_ieee@plt 386; RV32I-NEXT: and a0, a0, s1 387; RV32I-NEXT: call __gnu_h2f_ieee@plt 388; RV32I-NEXT: mv s0, a0 389; RV32I-NEXT: lui a0, 524288 390; RV32I-NEXT: xor a0, s0, a0 391; RV32I-NEXT: call __gnu_f2h_ieee@plt 392; RV32I-NEXT: and a0, a0, s1 393; RV32I-NEXT: call __gnu_h2f_ieee@plt 394; RV32I-NEXT: mv a1, a0 395; RV32I-NEXT: mv a0, s0 396; RV32I-NEXT: call __eqsf2@plt 397; RV32I-NEXT: seqz a0, a0 398; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 399; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 400; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 401; RV32I-NEXT: addi sp, sp, 16 402; RV32I-NEXT: ret 403; 404; RV64I-LABEL: fneg_s: 405; RV64I: # %bb.0: 406; RV64I-NEXT: addi sp, sp, -32 407; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 408; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 409; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 410; RV64I-NEXT: lui a1, 16 411; RV64I-NEXT: addiw s1, a1, -1 412; RV64I-NEXT: and a0, a0, s1 413; RV64I-NEXT: call __gnu_h2f_ieee@plt 414; RV64I-NEXT: mv a1, a0 415; RV64I-NEXT: call __addsf3@plt 416; RV64I-NEXT: call __gnu_f2h_ieee@plt 417; RV64I-NEXT: and a0, a0, s1 418; RV64I-NEXT: call __gnu_h2f_ieee@plt 419; RV64I-NEXT: mv s0, a0 420; RV64I-NEXT: lui a0, 524288 421; RV64I-NEXT: xor a0, s0, a0 422; RV64I-NEXT: call __gnu_f2h_ieee@plt 423; RV64I-NEXT: and a0, a0, s1 424; RV64I-NEXT: call __gnu_h2f_ieee@plt 425; RV64I-NEXT: mv a1, a0 426; RV64I-NEXT: mv a0, s0 427; RV64I-NEXT: call __eqsf2@plt 428; RV64I-NEXT: seqz a0, a0 429; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 430; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 431; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 432; RV64I-NEXT: addi sp, sp, 32 433; RV64I-NEXT: ret 434 %1 = fadd half %a, %a 435 %2 = fneg half %1 436 %3 = fcmp oeq half %1, %2 437 %4 = zext i1 %3 to i32 438 ret i32 %4 439} 440 441; This function performs extra work to ensure that 442; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor. 443define half @fsgnjn_s(half %a, half %b) nounwind { 444; RV32IZFH-LABEL: fsgnjn_s: 445; RV32IZFH: # %bb.0: 446; RV32IZFH-NEXT: fadd.h ft0, fa0, fa1 447; RV32IZFH-NEXT: fsgnjn.h fa0, fa0, ft0 448; RV32IZFH-NEXT: ret 449; 450; RV64IZFH-LABEL: fsgnjn_s: 451; RV64IZFH: # %bb.0: 452; RV64IZFH-NEXT: fadd.h ft0, fa0, fa1 453; RV64IZFH-NEXT: fsgnjn.h fa0, fa0, ft0 454; RV64IZFH-NEXT: ret 455; 456; RV32I-LABEL: fsgnjn_s: 457; RV32I: # %bb.0: 458; RV32I-NEXT: addi sp, sp, -32 459; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 460; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 461; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 462; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 463; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 464; RV32I-NEXT: mv s3, a1 465; RV32I-NEXT: mv s2, a0 466; RV32I-NEXT: lui a0, 16 467; RV32I-NEXT: addi s0, a0, -1 468; RV32I-NEXT: and a0, s2, s0 469; RV32I-NEXT: call __gnu_h2f_ieee@plt 470; RV32I-NEXT: mv s1, a0 471; RV32I-NEXT: and a0, s3, s0 472; RV32I-NEXT: call __gnu_h2f_ieee@plt 473; RV32I-NEXT: mv a1, a0 474; RV32I-NEXT: mv a0, s1 475; RV32I-NEXT: call __addsf3@plt 476; RV32I-NEXT: call __gnu_f2h_ieee@plt 477; RV32I-NEXT: and a0, a0, s0 478; RV32I-NEXT: call __gnu_h2f_ieee@plt 479; RV32I-NEXT: lui a1, 524288 480; RV32I-NEXT: xor a0, a0, a1 481; RV32I-NEXT: call __gnu_f2h_ieee@plt 482; RV32I-NEXT: lui a1, 1048568 483; RV32I-NEXT: and a0, a0, a1 484; RV32I-NEXT: slli a1, s2, 17 485; RV32I-NEXT: srli a1, a1, 17 486; RV32I-NEXT: or a0, a1, a0 487; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 488; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 489; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 490; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 491; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 492; RV32I-NEXT: addi sp, sp, 32 493; RV32I-NEXT: ret 494; 495; RV64I-LABEL: fsgnjn_s: 496; RV64I: # %bb.0: 497; RV64I-NEXT: addi sp, sp, -48 498; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 499; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 500; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 501; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 502; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 503; RV64I-NEXT: mv s3, a1 504; RV64I-NEXT: mv s2, a0 505; RV64I-NEXT: lui a0, 16 506; RV64I-NEXT: addiw s0, a0, -1 507; RV64I-NEXT: and a0, s2, s0 508; RV64I-NEXT: call __gnu_h2f_ieee@plt 509; RV64I-NEXT: mv s1, a0 510; RV64I-NEXT: and a0, s3, s0 511; RV64I-NEXT: call __gnu_h2f_ieee@plt 512; RV64I-NEXT: mv a1, a0 513; RV64I-NEXT: mv a0, s1 514; RV64I-NEXT: call __addsf3@plt 515; RV64I-NEXT: call __gnu_f2h_ieee@plt 516; RV64I-NEXT: and a0, a0, s0 517; RV64I-NEXT: call __gnu_h2f_ieee@plt 518; RV64I-NEXT: lui a1, 524288 519; RV64I-NEXT: xor a0, a0, a1 520; RV64I-NEXT: call __gnu_f2h_ieee@plt 521; RV64I-NEXT: lui a1, 1048568 522; RV64I-NEXT: and a0, a0, a1 523; RV64I-NEXT: slli a1, s2, 49 524; RV64I-NEXT: srli a1, a1, 49 525; RV64I-NEXT: or a0, a1, a0 526; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 527; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 528; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 529; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 530; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 531; RV64I-NEXT: addi sp, sp, 48 532; RV64I-NEXT: ret 533 %1 = fadd half %a, %b 534 %2 = fneg half %1 535 %3 = call half @llvm.copysign.f16(half %a, half %2) 536 ret half %3 537} 538 539declare half @llvm.fabs.f16(half) 540 541; This function performs extra work to ensure that 542; DAGCombiner::visitBITCAST doesn't replace the fabs with an and. 543define half @fabs_s(half %a, half %b) nounwind { 544; RV32IZFH-LABEL: fabs_s: 545; RV32IZFH: # %bb.0: 546; RV32IZFH-NEXT: fadd.h ft0, fa0, fa1 547; RV32IZFH-NEXT: fabs.h ft1, ft0 548; RV32IZFH-NEXT: fadd.h fa0, ft1, ft0 549; RV32IZFH-NEXT: ret 550; 551; RV64IZFH-LABEL: fabs_s: 552; RV64IZFH: # %bb.0: 553; RV64IZFH-NEXT: fadd.h ft0, fa0, fa1 554; RV64IZFH-NEXT: fabs.h ft1, ft0 555; RV64IZFH-NEXT: fadd.h fa0, ft1, ft0 556; RV64IZFH-NEXT: ret 557; 558; RV32I-LABEL: fabs_s: 559; RV32I: # %bb.0: 560; RV32I-NEXT: addi sp, sp, -16 561; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 562; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 563; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 564; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 565; RV32I-NEXT: mv s2, a1 566; RV32I-NEXT: lui a1, 16 567; RV32I-NEXT: addi s1, a1, -1 568; RV32I-NEXT: and a0, a0, s1 569; RV32I-NEXT: call __gnu_h2f_ieee@plt 570; RV32I-NEXT: mv s0, a0 571; RV32I-NEXT: and a0, s2, s1 572; RV32I-NEXT: call __gnu_h2f_ieee@plt 573; RV32I-NEXT: mv a1, a0 574; RV32I-NEXT: mv a0, s0 575; RV32I-NEXT: call __addsf3@plt 576; RV32I-NEXT: call __gnu_f2h_ieee@plt 577; RV32I-NEXT: and a0, a0, s1 578; RV32I-NEXT: call __gnu_h2f_ieee@plt 579; RV32I-NEXT: mv s0, a0 580; RV32I-NEXT: slli a0, a0, 1 581; RV32I-NEXT: srli a0, a0, 1 582; RV32I-NEXT: call __gnu_f2h_ieee@plt 583; RV32I-NEXT: and a0, a0, s1 584; RV32I-NEXT: call __gnu_h2f_ieee@plt 585; RV32I-NEXT: mv a1, s0 586; RV32I-NEXT: call __addsf3@plt 587; RV32I-NEXT: call __gnu_f2h_ieee@plt 588; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 589; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 590; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 591; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 592; RV32I-NEXT: addi sp, sp, 16 593; RV32I-NEXT: ret 594; 595; RV64I-LABEL: fabs_s: 596; RV64I: # %bb.0: 597; RV64I-NEXT: addi sp, sp, -32 598; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 599; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 600; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 601; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 602; RV64I-NEXT: mv s2, a1 603; RV64I-NEXT: lui a1, 16 604; RV64I-NEXT: addiw s1, a1, -1 605; RV64I-NEXT: and a0, a0, s1 606; RV64I-NEXT: call __gnu_h2f_ieee@plt 607; RV64I-NEXT: mv s0, a0 608; RV64I-NEXT: and a0, s2, s1 609; RV64I-NEXT: call __gnu_h2f_ieee@plt 610; RV64I-NEXT: mv a1, a0 611; RV64I-NEXT: mv a0, s0 612; RV64I-NEXT: call __addsf3@plt 613; RV64I-NEXT: call __gnu_f2h_ieee@plt 614; RV64I-NEXT: and a0, a0, s1 615; RV64I-NEXT: call __gnu_h2f_ieee@plt 616; RV64I-NEXT: mv s0, a0 617; RV64I-NEXT: slli a0, a0, 33 618; RV64I-NEXT: srli a0, a0, 33 619; RV64I-NEXT: call __gnu_f2h_ieee@plt 620; RV64I-NEXT: and a0, a0, s1 621; RV64I-NEXT: call __gnu_h2f_ieee@plt 622; RV64I-NEXT: mv a1, s0 623; RV64I-NEXT: call __addsf3@plt 624; RV64I-NEXT: call __gnu_f2h_ieee@plt 625; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 626; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 627; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 628; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 629; RV64I-NEXT: addi sp, sp, 32 630; RV64I-NEXT: ret 631 %1 = fadd half %a, %b 632 %2 = call half @llvm.fabs.f16(half %1) 633 %3 = fadd half %2, %1 634 ret half %3 635} 636 637declare half @llvm.minnum.f16(half, half) 638 639define half @fmin_s(half %a, half %b) nounwind { 640; RV32IZFH-LABEL: fmin_s: 641; RV32IZFH: # %bb.0: 642; RV32IZFH-NEXT: fmin.h fa0, fa0, fa1 643; RV32IZFH-NEXT: ret 644; 645; RV64IZFH-LABEL: fmin_s: 646; RV64IZFH: # %bb.0: 647; RV64IZFH-NEXT: fmin.h fa0, fa0, fa1 648; RV64IZFH-NEXT: ret 649; 650; RV32I-LABEL: fmin_s: 651; RV32I: # %bb.0: 652; RV32I-NEXT: addi sp, sp, -16 653; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 654; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 655; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 656; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 657; RV32I-NEXT: mv s2, a1 658; RV32I-NEXT: lui a1, 16 659; RV32I-NEXT: addi s0, a1, -1 660; RV32I-NEXT: and a0, a0, s0 661; RV32I-NEXT: call __gnu_h2f_ieee@plt 662; RV32I-NEXT: mv s1, a0 663; RV32I-NEXT: and a0, s2, s0 664; RV32I-NEXT: call __gnu_h2f_ieee@plt 665; RV32I-NEXT: mv a1, a0 666; RV32I-NEXT: mv a0, s1 667; RV32I-NEXT: call fminf@plt 668; RV32I-NEXT: call __gnu_f2h_ieee@plt 669; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 670; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 671; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 672; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 673; RV32I-NEXT: addi sp, sp, 16 674; RV32I-NEXT: ret 675; 676; RV64I-LABEL: fmin_s: 677; RV64I: # %bb.0: 678; RV64I-NEXT: addi sp, sp, -32 679; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 680; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 681; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 682; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 683; RV64I-NEXT: mv s2, a1 684; RV64I-NEXT: lui a1, 16 685; RV64I-NEXT: addiw s0, a1, -1 686; RV64I-NEXT: and a0, a0, s0 687; RV64I-NEXT: call __gnu_h2f_ieee@plt 688; RV64I-NEXT: mv s1, a0 689; RV64I-NEXT: and a0, s2, s0 690; RV64I-NEXT: call __gnu_h2f_ieee@plt 691; RV64I-NEXT: mv a1, a0 692; RV64I-NEXT: mv a0, s1 693; RV64I-NEXT: call fminf@plt 694; RV64I-NEXT: call __gnu_f2h_ieee@plt 695; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 696; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 697; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 698; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 699; RV64I-NEXT: addi sp, sp, 32 700; RV64I-NEXT: ret 701 %1 = call half @llvm.minnum.f16(half %a, half %b) 702 ret half %1 703} 704 705declare half @llvm.maxnum.f16(half, half) 706 707define half @fmax_s(half %a, half %b) nounwind { 708; RV32IZFH-LABEL: fmax_s: 709; RV32IZFH: # %bb.0: 710; RV32IZFH-NEXT: fmax.h fa0, fa0, fa1 711; RV32IZFH-NEXT: ret 712; 713; RV64IZFH-LABEL: fmax_s: 714; RV64IZFH: # %bb.0: 715; RV64IZFH-NEXT: fmax.h fa0, fa0, fa1 716; RV64IZFH-NEXT: ret 717; 718; RV32I-LABEL: fmax_s: 719; RV32I: # %bb.0: 720; RV32I-NEXT: addi sp, sp, -16 721; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 722; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 723; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 724; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 725; RV32I-NEXT: mv s2, a1 726; RV32I-NEXT: lui a1, 16 727; RV32I-NEXT: addi s0, a1, -1 728; RV32I-NEXT: and a0, a0, s0 729; RV32I-NEXT: call __gnu_h2f_ieee@plt 730; RV32I-NEXT: mv s1, a0 731; RV32I-NEXT: and a0, s2, s0 732; RV32I-NEXT: call __gnu_h2f_ieee@plt 733; RV32I-NEXT: mv a1, a0 734; RV32I-NEXT: mv a0, s1 735; RV32I-NEXT: call fmaxf@plt 736; RV32I-NEXT: call __gnu_f2h_ieee@plt 737; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 738; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 739; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 740; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 741; RV32I-NEXT: addi sp, sp, 16 742; RV32I-NEXT: ret 743; 744; RV64I-LABEL: fmax_s: 745; RV64I: # %bb.0: 746; RV64I-NEXT: addi sp, sp, -32 747; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 748; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 749; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 750; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 751; RV64I-NEXT: mv s2, a1 752; RV64I-NEXT: lui a1, 16 753; RV64I-NEXT: addiw s0, a1, -1 754; RV64I-NEXT: and a0, a0, s0 755; RV64I-NEXT: call __gnu_h2f_ieee@plt 756; RV64I-NEXT: mv s1, a0 757; RV64I-NEXT: and a0, s2, s0 758; RV64I-NEXT: call __gnu_h2f_ieee@plt 759; RV64I-NEXT: mv a1, a0 760; RV64I-NEXT: mv a0, s1 761; RV64I-NEXT: call fmaxf@plt 762; RV64I-NEXT: call __gnu_f2h_ieee@plt 763; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 764; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 765; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 766; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 767; RV64I-NEXT: addi sp, sp, 32 768; RV64I-NEXT: ret 769 %1 = call half @llvm.maxnum.f16(half %a, half %b) 770 ret half %1 771} 772 773declare half @llvm.fma.f16(half, half, half) 774 775define half @fmadd_s(half %a, half %b, half %c) nounwind { 776; RV32IZFH-LABEL: fmadd_s: 777; RV32IZFH: # %bb.0: 778; RV32IZFH-NEXT: fmadd.h fa0, fa0, fa1, fa2 779; RV32IZFH-NEXT: ret 780; 781; RV64IZFH-LABEL: fmadd_s: 782; RV64IZFH: # %bb.0: 783; RV64IZFH-NEXT: fmadd.h fa0, fa0, fa1, fa2 784; RV64IZFH-NEXT: ret 785; 786; RV32I-LABEL: fmadd_s: 787; RV32I: # %bb.0: 788; RV32I-NEXT: addi sp, sp, -32 789; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 790; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 791; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 792; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 793; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 794; RV32I-NEXT: mv s2, a2 795; RV32I-NEXT: mv s1, a1 796; RV32I-NEXT: lui a1, 16 797; RV32I-NEXT: addi s0, a1, -1 798; RV32I-NEXT: and a0, a0, s0 799; RV32I-NEXT: call __gnu_h2f_ieee@plt 800; RV32I-NEXT: mv s3, a0 801; RV32I-NEXT: and a0, s1, s0 802; RV32I-NEXT: call __gnu_h2f_ieee@plt 803; RV32I-NEXT: mv s1, a0 804; RV32I-NEXT: and a0, s2, s0 805; RV32I-NEXT: call __gnu_h2f_ieee@plt 806; RV32I-NEXT: mv a2, a0 807; RV32I-NEXT: mv a0, s3 808; RV32I-NEXT: mv a1, s1 809; RV32I-NEXT: call fmaf@plt 810; RV32I-NEXT: call __gnu_f2h_ieee@plt 811; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 812; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 813; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 814; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 815; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 816; RV32I-NEXT: addi sp, sp, 32 817; RV32I-NEXT: ret 818; 819; RV64I-LABEL: fmadd_s: 820; RV64I: # %bb.0: 821; RV64I-NEXT: addi sp, sp, -48 822; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 823; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 824; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 825; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 826; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 827; RV64I-NEXT: mv s2, a2 828; RV64I-NEXT: mv s1, a1 829; RV64I-NEXT: lui a1, 16 830; RV64I-NEXT: addiw s0, a1, -1 831; RV64I-NEXT: and a0, a0, s0 832; RV64I-NEXT: call __gnu_h2f_ieee@plt 833; RV64I-NEXT: mv s3, a0 834; RV64I-NEXT: and a0, s1, s0 835; RV64I-NEXT: call __gnu_h2f_ieee@plt 836; RV64I-NEXT: mv s1, a0 837; RV64I-NEXT: and a0, s2, s0 838; RV64I-NEXT: call __gnu_h2f_ieee@plt 839; RV64I-NEXT: mv a2, a0 840; RV64I-NEXT: mv a0, s3 841; RV64I-NEXT: mv a1, s1 842; RV64I-NEXT: call fmaf@plt 843; RV64I-NEXT: call __gnu_f2h_ieee@plt 844; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 845; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 846; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 847; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 848; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 849; RV64I-NEXT: addi sp, sp, 48 850; RV64I-NEXT: ret 851 %1 = call half @llvm.fma.f16(half %a, half %b, half %c) 852 ret half %1 853} 854 855define half @fmsub_s(half %a, half %b, half %c) nounwind { 856; RV32IZFH-LABEL: fmsub_s: 857; RV32IZFH: # %bb.0: 858; RV32IZFH-NEXT: fmv.h.x ft0, zero 859; RV32IZFH-NEXT: fadd.h ft0, fa2, ft0 860; RV32IZFH-NEXT: fmsub.h fa0, fa0, fa1, ft0 861; RV32IZFH-NEXT: ret 862; 863; RV64IZFH-LABEL: fmsub_s: 864; RV64IZFH: # %bb.0: 865; RV64IZFH-NEXT: fmv.h.x ft0, zero 866; RV64IZFH-NEXT: fadd.h ft0, fa2, ft0 867; RV64IZFH-NEXT: fmsub.h fa0, fa0, fa1, ft0 868; RV64IZFH-NEXT: ret 869; 870; RV32I-LABEL: fmsub_s: 871; RV32I: # %bb.0: 872; RV32I-NEXT: addi sp, sp, -32 873; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 874; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 875; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 876; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 877; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 878; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill 879; RV32I-NEXT: mv s2, a1 880; RV32I-NEXT: mv s1, a0 881; RV32I-NEXT: lui a0, 16 882; RV32I-NEXT: addi s0, a0, -1 883; RV32I-NEXT: and a0, a2, s0 884; RV32I-NEXT: call __gnu_h2f_ieee@plt 885; RV32I-NEXT: li a1, 0 886; RV32I-NEXT: call __addsf3@plt 887; RV32I-NEXT: call __gnu_f2h_ieee@plt 888; RV32I-NEXT: and a0, a0, s0 889; RV32I-NEXT: call __gnu_h2f_ieee@plt 890; RV32I-NEXT: lui a1, 524288 891; RV32I-NEXT: xor a0, a0, a1 892; RV32I-NEXT: call __gnu_f2h_ieee@plt 893; RV32I-NEXT: mv s4, a0 894; RV32I-NEXT: and a0, s1, s0 895; RV32I-NEXT: call __gnu_h2f_ieee@plt 896; RV32I-NEXT: mv s3, a0 897; RV32I-NEXT: and a0, s2, s0 898; RV32I-NEXT: call __gnu_h2f_ieee@plt 899; RV32I-NEXT: mv s1, a0 900; RV32I-NEXT: and a0, s4, s0 901; RV32I-NEXT: call __gnu_h2f_ieee@plt 902; RV32I-NEXT: mv a2, a0 903; RV32I-NEXT: mv a0, s3 904; RV32I-NEXT: mv a1, s1 905; RV32I-NEXT: call fmaf@plt 906; RV32I-NEXT: call __gnu_f2h_ieee@plt 907; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 908; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 909; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 910; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 911; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 912; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload 913; RV32I-NEXT: addi sp, sp, 32 914; RV32I-NEXT: ret 915; 916; RV64I-LABEL: fmsub_s: 917; RV64I: # %bb.0: 918; RV64I-NEXT: addi sp, sp, -48 919; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 920; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 921; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 922; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 923; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 924; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill 925; RV64I-NEXT: mv s2, a1 926; RV64I-NEXT: mv s1, a0 927; RV64I-NEXT: lui a0, 16 928; RV64I-NEXT: addiw s0, a0, -1 929; RV64I-NEXT: and a0, a2, s0 930; RV64I-NEXT: call __gnu_h2f_ieee@plt 931; RV64I-NEXT: li a1, 0 932; RV64I-NEXT: call __addsf3@plt 933; RV64I-NEXT: call __gnu_f2h_ieee@plt 934; RV64I-NEXT: and a0, a0, s0 935; RV64I-NEXT: call __gnu_h2f_ieee@plt 936; RV64I-NEXT: lui a1, 524288 937; RV64I-NEXT: xor a0, a0, a1 938; RV64I-NEXT: call __gnu_f2h_ieee@plt 939; RV64I-NEXT: mv s4, a0 940; RV64I-NEXT: and a0, s1, s0 941; RV64I-NEXT: call __gnu_h2f_ieee@plt 942; RV64I-NEXT: mv s3, a0 943; RV64I-NEXT: and a0, s2, s0 944; RV64I-NEXT: call __gnu_h2f_ieee@plt 945; RV64I-NEXT: mv s1, a0 946; RV64I-NEXT: and a0, s4, s0 947; RV64I-NEXT: call __gnu_h2f_ieee@plt 948; RV64I-NEXT: mv a2, a0 949; RV64I-NEXT: mv a0, s3 950; RV64I-NEXT: mv a1, s1 951; RV64I-NEXT: call fmaf@plt 952; RV64I-NEXT: call __gnu_f2h_ieee@plt 953; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 954; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 955; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 956; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 957; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 958; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload 959; RV64I-NEXT: addi sp, sp, 48 960; RV64I-NEXT: ret 961 %c_ = fadd half 0.0, %c ; avoid negation using xor 962 %negc = fsub half -0.0, %c_ 963 %1 = call half @llvm.fma.f16(half %a, half %b, half %negc) 964 ret half %1 965} 966 967define half @fnmadd_s(half %a, half %b, half %c) nounwind { 968; RV32IZFH-LABEL: fnmadd_s: 969; RV32IZFH: # %bb.0: 970; RV32IZFH-NEXT: fmv.h.x ft0, zero 971; RV32IZFH-NEXT: fadd.h ft1, fa0, ft0 972; RV32IZFH-NEXT: fadd.h ft0, fa2, ft0 973; RV32IZFH-NEXT: fnmadd.h fa0, ft1, fa1, ft0 974; RV32IZFH-NEXT: ret 975; 976; RV64IZFH-LABEL: fnmadd_s: 977; RV64IZFH: # %bb.0: 978; RV64IZFH-NEXT: fmv.h.x ft0, zero 979; RV64IZFH-NEXT: fadd.h ft1, fa0, ft0 980; RV64IZFH-NEXT: fadd.h ft0, fa2, ft0 981; RV64IZFH-NEXT: fnmadd.h fa0, ft1, fa1, ft0 982; RV64IZFH-NEXT: ret 983; 984; RV32I-LABEL: fnmadd_s: 985; RV32I: # %bb.0: 986; RV32I-NEXT: addi sp, sp, -32 987; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 988; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 989; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 990; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 991; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 992; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill 993; RV32I-NEXT: mv s3, a2 994; RV32I-NEXT: mv s2, a1 995; RV32I-NEXT: lui a1, 16 996; RV32I-NEXT: addi s1, a1, -1 997; RV32I-NEXT: and a0, a0, s1 998; RV32I-NEXT: call __gnu_h2f_ieee@plt 999; RV32I-NEXT: li a1, 0 1000; RV32I-NEXT: call __addsf3@plt 1001; RV32I-NEXT: call __gnu_f2h_ieee@plt 1002; RV32I-NEXT: mv s4, a0 1003; RV32I-NEXT: and a0, s3, s1 1004; RV32I-NEXT: call __gnu_h2f_ieee@plt 1005; RV32I-NEXT: li a1, 0 1006; RV32I-NEXT: call __addsf3@plt 1007; RV32I-NEXT: call __gnu_f2h_ieee@plt 1008; RV32I-NEXT: mv s0, a0 1009; RV32I-NEXT: and a0, s4, s1 1010; RV32I-NEXT: call __gnu_h2f_ieee@plt 1011; RV32I-NEXT: lui s4, 524288 1012; RV32I-NEXT: xor a0, a0, s4 1013; RV32I-NEXT: call __gnu_f2h_ieee@plt 1014; RV32I-NEXT: mv s3, a0 1015; RV32I-NEXT: and a0, s0, s1 1016; RV32I-NEXT: call __gnu_h2f_ieee@plt 1017; RV32I-NEXT: xor a0, a0, s4 1018; RV32I-NEXT: call __gnu_f2h_ieee@plt 1019; RV32I-NEXT: mv s4, a0 1020; RV32I-NEXT: and a0, s2, s1 1021; RV32I-NEXT: call __gnu_h2f_ieee@plt 1022; RV32I-NEXT: mv s2, a0 1023; RV32I-NEXT: and a0, s3, s1 1024; RV32I-NEXT: call __gnu_h2f_ieee@plt 1025; RV32I-NEXT: mv s0, a0 1026; RV32I-NEXT: and a0, s4, s1 1027; RV32I-NEXT: call __gnu_h2f_ieee@plt 1028; RV32I-NEXT: mv a2, a0 1029; RV32I-NEXT: mv a0, s0 1030; RV32I-NEXT: mv a1, s2 1031; RV32I-NEXT: call fmaf@plt 1032; RV32I-NEXT: call __gnu_f2h_ieee@plt 1033; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1034; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1035; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1036; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1037; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1038; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload 1039; RV32I-NEXT: addi sp, sp, 32 1040; RV32I-NEXT: ret 1041; 1042; RV64I-LABEL: fnmadd_s: 1043; RV64I: # %bb.0: 1044; RV64I-NEXT: addi sp, sp, -48 1045; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1046; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1047; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1048; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1049; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1050; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill 1051; RV64I-NEXT: mv s3, a2 1052; RV64I-NEXT: mv s2, a1 1053; RV64I-NEXT: lui a1, 16 1054; RV64I-NEXT: addiw s1, a1, -1 1055; RV64I-NEXT: and a0, a0, s1 1056; RV64I-NEXT: call __gnu_h2f_ieee@plt 1057; RV64I-NEXT: li a1, 0 1058; RV64I-NEXT: call __addsf3@plt 1059; RV64I-NEXT: call __gnu_f2h_ieee@plt 1060; RV64I-NEXT: mv s4, a0 1061; RV64I-NEXT: and a0, s3, s1 1062; RV64I-NEXT: call __gnu_h2f_ieee@plt 1063; RV64I-NEXT: li a1, 0 1064; RV64I-NEXT: call __addsf3@plt 1065; RV64I-NEXT: call __gnu_f2h_ieee@plt 1066; RV64I-NEXT: mv s0, a0 1067; RV64I-NEXT: and a0, s4, s1 1068; RV64I-NEXT: call __gnu_h2f_ieee@plt 1069; RV64I-NEXT: lui s4, 524288 1070; RV64I-NEXT: xor a0, a0, s4 1071; RV64I-NEXT: call __gnu_f2h_ieee@plt 1072; RV64I-NEXT: mv s3, a0 1073; RV64I-NEXT: and a0, s0, s1 1074; RV64I-NEXT: call __gnu_h2f_ieee@plt 1075; RV64I-NEXT: xor a0, a0, s4 1076; RV64I-NEXT: call __gnu_f2h_ieee@plt 1077; RV64I-NEXT: mv s4, a0 1078; RV64I-NEXT: and a0, s2, s1 1079; RV64I-NEXT: call __gnu_h2f_ieee@plt 1080; RV64I-NEXT: mv s2, a0 1081; RV64I-NEXT: and a0, s3, s1 1082; RV64I-NEXT: call __gnu_h2f_ieee@plt 1083; RV64I-NEXT: mv s0, a0 1084; RV64I-NEXT: and a0, s4, s1 1085; RV64I-NEXT: call __gnu_h2f_ieee@plt 1086; RV64I-NEXT: mv a2, a0 1087; RV64I-NEXT: mv a0, s0 1088; RV64I-NEXT: mv a1, s2 1089; RV64I-NEXT: call fmaf@plt 1090; RV64I-NEXT: call __gnu_f2h_ieee@plt 1091; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1092; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1093; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1094; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1095; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1096; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload 1097; RV64I-NEXT: addi sp, sp, 48 1098; RV64I-NEXT: ret 1099 %a_ = fadd half 0.0, %a 1100 %c_ = fadd half 0.0, %c 1101 %nega = fsub half -0.0, %a_ 1102 %negc = fsub half -0.0, %c_ 1103 %1 = call half @llvm.fma.f16(half %nega, half %b, half %negc) 1104 ret half %1 1105} 1106 1107define half @fnmadd_s_2(half %a, half %b, half %c) nounwind { 1108; RV32IZFH-LABEL: fnmadd_s_2: 1109; RV32IZFH: # %bb.0: 1110; RV32IZFH-NEXT: fmv.h.x ft0, zero 1111; RV32IZFH-NEXT: fadd.h ft1, fa1, ft0 1112; RV32IZFH-NEXT: fadd.h ft0, fa2, ft0 1113; RV32IZFH-NEXT: fnmadd.h fa0, ft1, fa0, ft0 1114; RV32IZFH-NEXT: ret 1115; 1116; RV64IZFH-LABEL: fnmadd_s_2: 1117; RV64IZFH: # %bb.0: 1118; RV64IZFH-NEXT: fmv.h.x ft0, zero 1119; RV64IZFH-NEXT: fadd.h ft1, fa1, ft0 1120; RV64IZFH-NEXT: fadd.h ft0, fa2, ft0 1121; RV64IZFH-NEXT: fnmadd.h fa0, ft1, fa0, ft0 1122; RV64IZFH-NEXT: ret 1123; 1124; RV32I-LABEL: fnmadd_s_2: 1125; RV32I: # %bb.0: 1126; RV32I-NEXT: addi sp, sp, -32 1127; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 1128; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 1129; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 1130; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 1131; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 1132; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill 1133; RV32I-NEXT: mv s3, a2 1134; RV32I-NEXT: mv s2, a0 1135; RV32I-NEXT: lui a0, 16 1136; RV32I-NEXT: addi s1, a0, -1 1137; RV32I-NEXT: and a0, a1, s1 1138; RV32I-NEXT: call __gnu_h2f_ieee@plt 1139; RV32I-NEXT: li a1, 0 1140; RV32I-NEXT: call __addsf3@plt 1141; RV32I-NEXT: call __gnu_f2h_ieee@plt 1142; RV32I-NEXT: mv s4, a0 1143; RV32I-NEXT: and a0, s3, s1 1144; RV32I-NEXT: call __gnu_h2f_ieee@plt 1145; RV32I-NEXT: li a1, 0 1146; RV32I-NEXT: call __addsf3@plt 1147; RV32I-NEXT: call __gnu_f2h_ieee@plt 1148; RV32I-NEXT: mv s0, a0 1149; RV32I-NEXT: and a0, s4, s1 1150; RV32I-NEXT: call __gnu_h2f_ieee@plt 1151; RV32I-NEXT: lui s4, 524288 1152; RV32I-NEXT: xor a0, a0, s4 1153; RV32I-NEXT: call __gnu_f2h_ieee@plt 1154; RV32I-NEXT: mv s3, a0 1155; RV32I-NEXT: and a0, s0, s1 1156; RV32I-NEXT: call __gnu_h2f_ieee@plt 1157; RV32I-NEXT: xor a0, a0, s4 1158; RV32I-NEXT: call __gnu_f2h_ieee@plt 1159; RV32I-NEXT: mv s4, a0 1160; RV32I-NEXT: and a0, s2, s1 1161; RV32I-NEXT: call __gnu_h2f_ieee@plt 1162; RV32I-NEXT: mv s2, a0 1163; RV32I-NEXT: and a0, s3, s1 1164; RV32I-NEXT: call __gnu_h2f_ieee@plt 1165; RV32I-NEXT: mv s0, a0 1166; RV32I-NEXT: and a0, s4, s1 1167; RV32I-NEXT: call __gnu_h2f_ieee@plt 1168; RV32I-NEXT: mv a2, a0 1169; RV32I-NEXT: mv a0, s2 1170; RV32I-NEXT: mv a1, s0 1171; RV32I-NEXT: call fmaf@plt 1172; RV32I-NEXT: call __gnu_f2h_ieee@plt 1173; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1174; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1175; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1176; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1177; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1178; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload 1179; RV32I-NEXT: addi sp, sp, 32 1180; RV32I-NEXT: ret 1181; 1182; RV64I-LABEL: fnmadd_s_2: 1183; RV64I: # %bb.0: 1184; RV64I-NEXT: addi sp, sp, -48 1185; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1186; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1187; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1188; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1189; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1190; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill 1191; RV64I-NEXT: mv s3, a2 1192; RV64I-NEXT: mv s2, a0 1193; RV64I-NEXT: lui a0, 16 1194; RV64I-NEXT: addiw s1, a0, -1 1195; RV64I-NEXT: and a0, a1, s1 1196; RV64I-NEXT: call __gnu_h2f_ieee@plt 1197; RV64I-NEXT: li a1, 0 1198; RV64I-NEXT: call __addsf3@plt 1199; RV64I-NEXT: call __gnu_f2h_ieee@plt 1200; RV64I-NEXT: mv s4, a0 1201; RV64I-NEXT: and a0, s3, s1 1202; RV64I-NEXT: call __gnu_h2f_ieee@plt 1203; RV64I-NEXT: li a1, 0 1204; RV64I-NEXT: call __addsf3@plt 1205; RV64I-NEXT: call __gnu_f2h_ieee@plt 1206; RV64I-NEXT: mv s0, a0 1207; RV64I-NEXT: and a0, s4, s1 1208; RV64I-NEXT: call __gnu_h2f_ieee@plt 1209; RV64I-NEXT: lui s4, 524288 1210; RV64I-NEXT: xor a0, a0, s4 1211; RV64I-NEXT: call __gnu_f2h_ieee@plt 1212; RV64I-NEXT: mv s3, a0 1213; RV64I-NEXT: and a0, s0, s1 1214; RV64I-NEXT: call __gnu_h2f_ieee@plt 1215; RV64I-NEXT: xor a0, a0, s4 1216; RV64I-NEXT: call __gnu_f2h_ieee@plt 1217; RV64I-NEXT: mv s4, a0 1218; RV64I-NEXT: and a0, s2, s1 1219; RV64I-NEXT: call __gnu_h2f_ieee@plt 1220; RV64I-NEXT: mv s2, a0 1221; RV64I-NEXT: and a0, s3, s1 1222; RV64I-NEXT: call __gnu_h2f_ieee@plt 1223; RV64I-NEXT: mv s0, a0 1224; RV64I-NEXT: and a0, s4, s1 1225; RV64I-NEXT: call __gnu_h2f_ieee@plt 1226; RV64I-NEXT: mv a2, a0 1227; RV64I-NEXT: mv a0, s2 1228; RV64I-NEXT: mv a1, s0 1229; RV64I-NEXT: call fmaf@plt 1230; RV64I-NEXT: call __gnu_f2h_ieee@plt 1231; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1232; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1233; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1234; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1235; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1236; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload 1237; RV64I-NEXT: addi sp, sp, 48 1238; RV64I-NEXT: ret 1239 %b_ = fadd half 0.0, %b 1240 %c_ = fadd half 0.0, %c 1241 %negb = fsub half -0.0, %b_ 1242 %negc = fsub half -0.0, %c_ 1243 %1 = call half @llvm.fma.f16(half %a, half %negb, half %negc) 1244 ret half %1 1245} 1246 1247define half @fnmsub_s(half %a, half %b, half %c) nounwind { 1248; RV32IZFH-LABEL: fnmsub_s: 1249; RV32IZFH: # %bb.0: 1250; RV32IZFH-NEXT: fmv.h.x ft0, zero 1251; RV32IZFH-NEXT: fadd.h ft0, fa0, ft0 1252; RV32IZFH-NEXT: fnmsub.h fa0, ft0, fa1, fa2 1253; RV32IZFH-NEXT: ret 1254; 1255; RV64IZFH-LABEL: fnmsub_s: 1256; RV64IZFH: # %bb.0: 1257; RV64IZFH-NEXT: fmv.h.x ft0, zero 1258; RV64IZFH-NEXT: fadd.h ft0, fa0, ft0 1259; RV64IZFH-NEXT: fnmsub.h fa0, ft0, fa1, fa2 1260; RV64IZFH-NEXT: ret 1261; 1262; RV32I-LABEL: fnmsub_s: 1263; RV32I: # %bb.0: 1264; RV32I-NEXT: addi sp, sp, -32 1265; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 1266; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 1267; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 1268; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 1269; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 1270; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill 1271; RV32I-NEXT: mv s2, a2 1272; RV32I-NEXT: mv s1, a1 1273; RV32I-NEXT: lui a1, 16 1274; RV32I-NEXT: addi s0, a1, -1 1275; RV32I-NEXT: and a0, a0, s0 1276; RV32I-NEXT: call __gnu_h2f_ieee@plt 1277; RV32I-NEXT: li a1, 0 1278; RV32I-NEXT: call __addsf3@plt 1279; RV32I-NEXT: call __gnu_f2h_ieee@plt 1280; RV32I-NEXT: and a0, a0, s0 1281; RV32I-NEXT: call __gnu_h2f_ieee@plt 1282; RV32I-NEXT: lui a1, 524288 1283; RV32I-NEXT: xor a0, a0, a1 1284; RV32I-NEXT: call __gnu_f2h_ieee@plt 1285; RV32I-NEXT: mv s4, a0 1286; RV32I-NEXT: and a0, s1, s0 1287; RV32I-NEXT: call __gnu_h2f_ieee@plt 1288; RV32I-NEXT: mv s3, a0 1289; RV32I-NEXT: and a0, s2, s0 1290; RV32I-NEXT: call __gnu_h2f_ieee@plt 1291; RV32I-NEXT: mv s1, a0 1292; RV32I-NEXT: and a0, s4, s0 1293; RV32I-NEXT: call __gnu_h2f_ieee@plt 1294; RV32I-NEXT: mv a1, s3 1295; RV32I-NEXT: mv a2, s1 1296; RV32I-NEXT: call fmaf@plt 1297; RV32I-NEXT: call __gnu_f2h_ieee@plt 1298; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1299; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1300; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1301; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1302; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1303; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload 1304; RV32I-NEXT: addi sp, sp, 32 1305; RV32I-NEXT: ret 1306; 1307; RV64I-LABEL: fnmsub_s: 1308; RV64I: # %bb.0: 1309; RV64I-NEXT: addi sp, sp, -48 1310; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1311; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1312; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1313; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1314; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1315; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill 1316; RV64I-NEXT: mv s2, a2 1317; RV64I-NEXT: mv s1, a1 1318; RV64I-NEXT: lui a1, 16 1319; RV64I-NEXT: addiw s0, a1, -1 1320; RV64I-NEXT: and a0, a0, s0 1321; RV64I-NEXT: call __gnu_h2f_ieee@plt 1322; RV64I-NEXT: li a1, 0 1323; RV64I-NEXT: call __addsf3@plt 1324; RV64I-NEXT: call __gnu_f2h_ieee@plt 1325; RV64I-NEXT: and a0, a0, s0 1326; RV64I-NEXT: call __gnu_h2f_ieee@plt 1327; RV64I-NEXT: lui a1, 524288 1328; RV64I-NEXT: xor a0, a0, a1 1329; RV64I-NEXT: call __gnu_f2h_ieee@plt 1330; RV64I-NEXT: mv s4, a0 1331; RV64I-NEXT: and a0, s1, s0 1332; RV64I-NEXT: call __gnu_h2f_ieee@plt 1333; RV64I-NEXT: mv s3, a0 1334; RV64I-NEXT: and a0, s2, s0 1335; RV64I-NEXT: call __gnu_h2f_ieee@plt 1336; RV64I-NEXT: mv s1, a0 1337; RV64I-NEXT: and a0, s4, s0 1338; RV64I-NEXT: call __gnu_h2f_ieee@plt 1339; RV64I-NEXT: mv a1, s3 1340; RV64I-NEXT: mv a2, s1 1341; RV64I-NEXT: call fmaf@plt 1342; RV64I-NEXT: call __gnu_f2h_ieee@plt 1343; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1344; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1345; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1346; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1347; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1348; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload 1349; RV64I-NEXT: addi sp, sp, 48 1350; RV64I-NEXT: ret 1351 %a_ = fadd half 0.0, %a 1352 %nega = fsub half -0.0, %a_ 1353 %1 = call half @llvm.fma.f16(half %nega, half %b, half %c) 1354 ret half %1 1355} 1356 1357define half @fnmsub_s_2(half %a, half %b, half %c) nounwind { 1358; RV32IZFH-LABEL: fnmsub_s_2: 1359; RV32IZFH: # %bb.0: 1360; RV32IZFH-NEXT: fmv.h.x ft0, zero 1361; RV32IZFH-NEXT: fadd.h ft0, fa1, ft0 1362; RV32IZFH-NEXT: fnmsub.h fa0, ft0, fa0, fa2 1363; RV32IZFH-NEXT: ret 1364; 1365; RV64IZFH-LABEL: fnmsub_s_2: 1366; RV64IZFH: # %bb.0: 1367; RV64IZFH-NEXT: fmv.h.x ft0, zero 1368; RV64IZFH-NEXT: fadd.h ft0, fa1, ft0 1369; RV64IZFH-NEXT: fnmsub.h fa0, ft0, fa0, fa2 1370; RV64IZFH-NEXT: ret 1371; 1372; RV32I-LABEL: fnmsub_s_2: 1373; RV32I: # %bb.0: 1374; RV32I-NEXT: addi sp, sp, -32 1375; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 1376; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 1377; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 1378; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 1379; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 1380; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill 1381; RV32I-NEXT: mv s2, a2 1382; RV32I-NEXT: mv s1, a0 1383; RV32I-NEXT: lui a0, 16 1384; RV32I-NEXT: addi s0, a0, -1 1385; RV32I-NEXT: and a0, a1, s0 1386; RV32I-NEXT: call __gnu_h2f_ieee@plt 1387; RV32I-NEXT: li a1, 0 1388; RV32I-NEXT: call __addsf3@plt 1389; RV32I-NEXT: call __gnu_f2h_ieee@plt 1390; RV32I-NEXT: and a0, a0, s0 1391; RV32I-NEXT: call __gnu_h2f_ieee@plt 1392; RV32I-NEXT: lui a1, 524288 1393; RV32I-NEXT: xor a0, a0, a1 1394; RV32I-NEXT: call __gnu_f2h_ieee@plt 1395; RV32I-NEXT: mv s4, a0 1396; RV32I-NEXT: and a0, s1, s0 1397; RV32I-NEXT: call __gnu_h2f_ieee@plt 1398; RV32I-NEXT: mv s3, a0 1399; RV32I-NEXT: and a0, s2, s0 1400; RV32I-NEXT: call __gnu_h2f_ieee@plt 1401; RV32I-NEXT: mv s1, a0 1402; RV32I-NEXT: and a0, s4, s0 1403; RV32I-NEXT: call __gnu_h2f_ieee@plt 1404; RV32I-NEXT: mv a1, a0 1405; RV32I-NEXT: mv a0, s3 1406; RV32I-NEXT: mv a2, s1 1407; RV32I-NEXT: call fmaf@plt 1408; RV32I-NEXT: call __gnu_f2h_ieee@plt 1409; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1410; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1411; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1412; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1413; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1414; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload 1415; RV32I-NEXT: addi sp, sp, 32 1416; RV32I-NEXT: ret 1417; 1418; RV64I-LABEL: fnmsub_s_2: 1419; RV64I: # %bb.0: 1420; RV64I-NEXT: addi sp, sp, -48 1421; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1422; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1423; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1424; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1425; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1426; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill 1427; RV64I-NEXT: mv s2, a2 1428; RV64I-NEXT: mv s1, a0 1429; RV64I-NEXT: lui a0, 16 1430; RV64I-NEXT: addiw s0, a0, -1 1431; RV64I-NEXT: and a0, a1, s0 1432; RV64I-NEXT: call __gnu_h2f_ieee@plt 1433; RV64I-NEXT: li a1, 0 1434; RV64I-NEXT: call __addsf3@plt 1435; RV64I-NEXT: call __gnu_f2h_ieee@plt 1436; RV64I-NEXT: and a0, a0, s0 1437; RV64I-NEXT: call __gnu_h2f_ieee@plt 1438; RV64I-NEXT: lui a1, 524288 1439; RV64I-NEXT: xor a0, a0, a1 1440; RV64I-NEXT: call __gnu_f2h_ieee@plt 1441; RV64I-NEXT: mv s4, a0 1442; RV64I-NEXT: and a0, s1, s0 1443; RV64I-NEXT: call __gnu_h2f_ieee@plt 1444; RV64I-NEXT: mv s3, a0 1445; RV64I-NEXT: and a0, s2, s0 1446; RV64I-NEXT: call __gnu_h2f_ieee@plt 1447; RV64I-NEXT: mv s1, a0 1448; RV64I-NEXT: and a0, s4, s0 1449; RV64I-NEXT: call __gnu_h2f_ieee@plt 1450; RV64I-NEXT: mv a1, a0 1451; RV64I-NEXT: mv a0, s3 1452; RV64I-NEXT: mv a2, s1 1453; RV64I-NEXT: call fmaf@plt 1454; RV64I-NEXT: call __gnu_f2h_ieee@plt 1455; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1456; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1457; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1458; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1459; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1460; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload 1461; RV64I-NEXT: addi sp, sp, 48 1462; RV64I-NEXT: ret 1463 %b_ = fadd half 0.0, %b 1464 %negb = fsub half -0.0, %b_ 1465 %1 = call half @llvm.fma.f16(half %a, half %negb, half %c) 1466 ret half %1 1467} 1468 1469define half @fmadd_s_contract(half %a, half %b, half %c) nounwind { 1470; RV32IZFH-LABEL: fmadd_s_contract: 1471; RV32IZFH: # %bb.0: 1472; RV32IZFH-NEXT: fmadd.h fa0, fa0, fa1, fa2 1473; RV32IZFH-NEXT: ret 1474; 1475; RV64IZFH-LABEL: fmadd_s_contract: 1476; RV64IZFH: # %bb.0: 1477; RV64IZFH-NEXT: fmadd.h fa0, fa0, fa1, fa2 1478; RV64IZFH-NEXT: ret 1479; 1480; RV32I-LABEL: fmadd_s_contract: 1481; RV32I: # %bb.0: 1482; RV32I-NEXT: addi sp, sp, -32 1483; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 1484; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 1485; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 1486; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 1487; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 1488; RV32I-NEXT: mv s2, a2 1489; RV32I-NEXT: mv s3, a1 1490; RV32I-NEXT: lui a1, 16 1491; RV32I-NEXT: addi s1, a1, -1 1492; RV32I-NEXT: and a0, a0, s1 1493; RV32I-NEXT: call __gnu_h2f_ieee@plt 1494; RV32I-NEXT: mv s0, a0 1495; RV32I-NEXT: and a0, s3, s1 1496; RV32I-NEXT: call __gnu_h2f_ieee@plt 1497; RV32I-NEXT: mv a1, a0 1498; RV32I-NEXT: mv a0, s0 1499; RV32I-NEXT: call __mulsf3@plt 1500; RV32I-NEXT: call __gnu_f2h_ieee@plt 1501; RV32I-NEXT: mv s0, a0 1502; RV32I-NEXT: and a0, s2, s1 1503; RV32I-NEXT: call __gnu_h2f_ieee@plt 1504; RV32I-NEXT: mv s2, a0 1505; RV32I-NEXT: and a0, s0, s1 1506; RV32I-NEXT: call __gnu_h2f_ieee@plt 1507; RV32I-NEXT: mv a1, s2 1508; RV32I-NEXT: call __addsf3@plt 1509; RV32I-NEXT: call __gnu_f2h_ieee@plt 1510; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1511; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1512; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1513; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1514; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1515; RV32I-NEXT: addi sp, sp, 32 1516; RV32I-NEXT: ret 1517; 1518; RV64I-LABEL: fmadd_s_contract: 1519; RV64I: # %bb.0: 1520; RV64I-NEXT: addi sp, sp, -48 1521; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1522; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1523; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1524; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1525; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1526; RV64I-NEXT: mv s2, a2 1527; RV64I-NEXT: mv s3, a1 1528; RV64I-NEXT: lui a1, 16 1529; RV64I-NEXT: addiw s1, a1, -1 1530; RV64I-NEXT: and a0, a0, s1 1531; RV64I-NEXT: call __gnu_h2f_ieee@plt 1532; RV64I-NEXT: mv s0, a0 1533; RV64I-NEXT: and a0, s3, s1 1534; RV64I-NEXT: call __gnu_h2f_ieee@plt 1535; RV64I-NEXT: mv a1, a0 1536; RV64I-NEXT: mv a0, s0 1537; RV64I-NEXT: call __mulsf3@plt 1538; RV64I-NEXT: call __gnu_f2h_ieee@plt 1539; RV64I-NEXT: mv s0, a0 1540; RV64I-NEXT: and a0, s2, s1 1541; RV64I-NEXT: call __gnu_h2f_ieee@plt 1542; RV64I-NEXT: mv s2, a0 1543; RV64I-NEXT: and a0, s0, s1 1544; RV64I-NEXT: call __gnu_h2f_ieee@plt 1545; RV64I-NEXT: mv a1, s2 1546; RV64I-NEXT: call __addsf3@plt 1547; RV64I-NEXT: call __gnu_f2h_ieee@plt 1548; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1549; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1550; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1551; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1552; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1553; RV64I-NEXT: addi sp, sp, 48 1554; RV64I-NEXT: ret 1555 %1 = fmul contract half %a, %b 1556 %2 = fadd contract half %1, %c 1557 ret half %2 1558} 1559 1560define half @fmsub_s_contract(half %a, half %b, half %c) nounwind { 1561; RV32IZFH-LABEL: fmsub_s_contract: 1562; RV32IZFH: # %bb.0: 1563; RV32IZFH-NEXT: fmv.h.x ft0, zero 1564; RV32IZFH-NEXT: fadd.h ft0, fa2, ft0 1565; RV32IZFH-NEXT: fmsub.h fa0, fa0, fa1, ft0 1566; RV32IZFH-NEXT: ret 1567; 1568; RV64IZFH-LABEL: fmsub_s_contract: 1569; RV64IZFH: # %bb.0: 1570; RV64IZFH-NEXT: fmv.h.x ft0, zero 1571; RV64IZFH-NEXT: fadd.h ft0, fa2, ft0 1572; RV64IZFH-NEXT: fmsub.h fa0, fa0, fa1, ft0 1573; RV64IZFH-NEXT: ret 1574; 1575; RV32I-LABEL: fmsub_s_contract: 1576; RV32I: # %bb.0: 1577; RV32I-NEXT: addi sp, sp, -32 1578; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 1579; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 1580; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 1581; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 1582; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 1583; RV32I-NEXT: mv s3, a1 1584; RV32I-NEXT: mv s1, a0 1585; RV32I-NEXT: lui a0, 16 1586; RV32I-NEXT: addi s0, a0, -1 1587; RV32I-NEXT: and a0, a2, s0 1588; RV32I-NEXT: call __gnu_h2f_ieee@plt 1589; RV32I-NEXT: li a1, 0 1590; RV32I-NEXT: call __addsf3@plt 1591; RV32I-NEXT: call __gnu_f2h_ieee@plt 1592; RV32I-NEXT: mv s2, a0 1593; RV32I-NEXT: and a0, s1, s0 1594; RV32I-NEXT: call __gnu_h2f_ieee@plt 1595; RV32I-NEXT: mv s1, a0 1596; RV32I-NEXT: and a0, s3, s0 1597; RV32I-NEXT: call __gnu_h2f_ieee@plt 1598; RV32I-NEXT: mv a1, a0 1599; RV32I-NEXT: mv a0, s1 1600; RV32I-NEXT: call __mulsf3@plt 1601; RV32I-NEXT: call __gnu_f2h_ieee@plt 1602; RV32I-NEXT: and a0, a0, s0 1603; RV32I-NEXT: call __gnu_h2f_ieee@plt 1604; RV32I-NEXT: mv s1, a0 1605; RV32I-NEXT: and a0, s2, s0 1606; RV32I-NEXT: call __gnu_h2f_ieee@plt 1607; RV32I-NEXT: mv a1, a0 1608; RV32I-NEXT: mv a0, s1 1609; RV32I-NEXT: call __subsf3@plt 1610; RV32I-NEXT: call __gnu_f2h_ieee@plt 1611; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1612; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1613; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1614; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1615; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1616; RV32I-NEXT: addi sp, sp, 32 1617; RV32I-NEXT: ret 1618; 1619; RV64I-LABEL: fmsub_s_contract: 1620; RV64I: # %bb.0: 1621; RV64I-NEXT: addi sp, sp, -48 1622; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1623; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1624; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1625; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1626; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1627; RV64I-NEXT: mv s3, a1 1628; RV64I-NEXT: mv s1, a0 1629; RV64I-NEXT: lui a0, 16 1630; RV64I-NEXT: addiw s0, a0, -1 1631; RV64I-NEXT: and a0, a2, s0 1632; RV64I-NEXT: call __gnu_h2f_ieee@plt 1633; RV64I-NEXT: li a1, 0 1634; RV64I-NEXT: call __addsf3@plt 1635; RV64I-NEXT: call __gnu_f2h_ieee@plt 1636; RV64I-NEXT: mv s2, a0 1637; RV64I-NEXT: and a0, s1, s0 1638; RV64I-NEXT: call __gnu_h2f_ieee@plt 1639; RV64I-NEXT: mv s1, a0 1640; RV64I-NEXT: and a0, s3, s0 1641; RV64I-NEXT: call __gnu_h2f_ieee@plt 1642; RV64I-NEXT: mv a1, a0 1643; RV64I-NEXT: mv a0, s1 1644; RV64I-NEXT: call __mulsf3@plt 1645; RV64I-NEXT: call __gnu_f2h_ieee@plt 1646; RV64I-NEXT: and a0, a0, s0 1647; RV64I-NEXT: call __gnu_h2f_ieee@plt 1648; RV64I-NEXT: mv s1, a0 1649; RV64I-NEXT: and a0, s2, s0 1650; RV64I-NEXT: call __gnu_h2f_ieee@plt 1651; RV64I-NEXT: mv a1, a0 1652; RV64I-NEXT: mv a0, s1 1653; RV64I-NEXT: call __subsf3@plt 1654; RV64I-NEXT: call __gnu_f2h_ieee@plt 1655; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1656; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1657; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1658; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1659; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1660; RV64I-NEXT: addi sp, sp, 48 1661; RV64I-NEXT: ret 1662 %c_ = fadd half 0.0, %c ; avoid negation using xor 1663 %1 = fmul contract half %a, %b 1664 %2 = fsub contract half %1, %c_ 1665 ret half %2 1666} 1667 1668define half @fnmadd_s_contract(half %a, half %b, half %c) nounwind { 1669; RV32IZFH-LABEL: fnmadd_s_contract: 1670; RV32IZFH: # %bb.0: 1671; RV32IZFH-NEXT: fmv.h.x ft0, zero 1672; RV32IZFH-NEXT: fadd.h ft1, fa0, ft0 1673; RV32IZFH-NEXT: fadd.h ft2, fa1, ft0 1674; RV32IZFH-NEXT: fadd.h ft0, fa2, ft0 1675; RV32IZFH-NEXT: fnmadd.h fa0, ft1, ft2, ft0 1676; RV32IZFH-NEXT: ret 1677; 1678; RV64IZFH-LABEL: fnmadd_s_contract: 1679; RV64IZFH: # %bb.0: 1680; RV64IZFH-NEXT: fmv.h.x ft0, zero 1681; RV64IZFH-NEXT: fadd.h ft1, fa0, ft0 1682; RV64IZFH-NEXT: fadd.h ft2, fa1, ft0 1683; RV64IZFH-NEXT: fadd.h ft0, fa2, ft0 1684; RV64IZFH-NEXT: fnmadd.h fa0, ft1, ft2, ft0 1685; RV64IZFH-NEXT: ret 1686; 1687; RV32I-LABEL: fnmadd_s_contract: 1688; RV32I: # %bb.0: 1689; RV32I-NEXT: addi sp, sp, -32 1690; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 1691; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 1692; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 1693; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 1694; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 1695; RV32I-NEXT: sw s4, 8(sp) # 4-byte Folded Spill 1696; RV32I-NEXT: mv s2, a2 1697; RV32I-NEXT: mv s0, a1 1698; RV32I-NEXT: lui a1, 16 1699; RV32I-NEXT: addi s1, a1, -1 1700; RV32I-NEXT: and a0, a0, s1 1701; RV32I-NEXT: call __gnu_h2f_ieee@plt 1702; RV32I-NEXT: li a1, 0 1703; RV32I-NEXT: call __addsf3@plt 1704; RV32I-NEXT: call __gnu_f2h_ieee@plt 1705; RV32I-NEXT: mv s3, a0 1706; RV32I-NEXT: and a0, s0, s1 1707; RV32I-NEXT: call __gnu_h2f_ieee@plt 1708; RV32I-NEXT: li a1, 0 1709; RV32I-NEXT: call __addsf3@plt 1710; RV32I-NEXT: call __gnu_f2h_ieee@plt 1711; RV32I-NEXT: mv s4, a0 1712; RV32I-NEXT: and a0, s2, s1 1713; RV32I-NEXT: call __gnu_h2f_ieee@plt 1714; RV32I-NEXT: li a1, 0 1715; RV32I-NEXT: call __addsf3@plt 1716; RV32I-NEXT: call __gnu_f2h_ieee@plt 1717; RV32I-NEXT: mv s2, a0 1718; RV32I-NEXT: and a0, s3, s1 1719; RV32I-NEXT: call __gnu_h2f_ieee@plt 1720; RV32I-NEXT: mv s0, a0 1721; RV32I-NEXT: and a0, s4, s1 1722; RV32I-NEXT: call __gnu_h2f_ieee@plt 1723; RV32I-NEXT: mv a1, a0 1724; RV32I-NEXT: mv a0, s0 1725; RV32I-NEXT: call __mulsf3@plt 1726; RV32I-NEXT: call __gnu_f2h_ieee@plt 1727; RV32I-NEXT: and a0, a0, s1 1728; RV32I-NEXT: call __gnu_h2f_ieee@plt 1729; RV32I-NEXT: lui a1, 524288 1730; RV32I-NEXT: xor a0, a0, a1 1731; RV32I-NEXT: call __gnu_f2h_ieee@plt 1732; RV32I-NEXT: mv s0, a0 1733; RV32I-NEXT: and a0, s2, s1 1734; RV32I-NEXT: call __gnu_h2f_ieee@plt 1735; RV32I-NEXT: mv s2, a0 1736; RV32I-NEXT: and a0, s0, s1 1737; RV32I-NEXT: call __gnu_h2f_ieee@plt 1738; RV32I-NEXT: mv a1, s2 1739; RV32I-NEXT: call __subsf3@plt 1740; RV32I-NEXT: call __gnu_f2h_ieee@plt 1741; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1742; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1743; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1744; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1745; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1746; RV32I-NEXT: lw s4, 8(sp) # 4-byte Folded Reload 1747; RV32I-NEXT: addi sp, sp, 32 1748; RV32I-NEXT: ret 1749; 1750; RV64I-LABEL: fnmadd_s_contract: 1751; RV64I: # %bb.0: 1752; RV64I-NEXT: addi sp, sp, -48 1753; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1754; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1755; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1756; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1757; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1758; RV64I-NEXT: sd s4, 0(sp) # 8-byte Folded Spill 1759; RV64I-NEXT: mv s2, a2 1760; RV64I-NEXT: mv s0, a1 1761; RV64I-NEXT: lui a1, 16 1762; RV64I-NEXT: addiw s1, a1, -1 1763; RV64I-NEXT: and a0, a0, s1 1764; RV64I-NEXT: call __gnu_h2f_ieee@plt 1765; RV64I-NEXT: li a1, 0 1766; RV64I-NEXT: call __addsf3@plt 1767; RV64I-NEXT: call __gnu_f2h_ieee@plt 1768; RV64I-NEXT: mv s3, a0 1769; RV64I-NEXT: and a0, s0, s1 1770; RV64I-NEXT: call __gnu_h2f_ieee@plt 1771; RV64I-NEXT: li a1, 0 1772; RV64I-NEXT: call __addsf3@plt 1773; RV64I-NEXT: call __gnu_f2h_ieee@plt 1774; RV64I-NEXT: mv s4, a0 1775; RV64I-NEXT: and a0, s2, s1 1776; RV64I-NEXT: call __gnu_h2f_ieee@plt 1777; RV64I-NEXT: li a1, 0 1778; RV64I-NEXT: call __addsf3@plt 1779; RV64I-NEXT: call __gnu_f2h_ieee@plt 1780; RV64I-NEXT: mv s2, a0 1781; RV64I-NEXT: and a0, s3, s1 1782; RV64I-NEXT: call __gnu_h2f_ieee@plt 1783; RV64I-NEXT: mv s0, a0 1784; RV64I-NEXT: and a0, s4, s1 1785; RV64I-NEXT: call __gnu_h2f_ieee@plt 1786; RV64I-NEXT: mv a1, a0 1787; RV64I-NEXT: mv a0, s0 1788; RV64I-NEXT: call __mulsf3@plt 1789; RV64I-NEXT: call __gnu_f2h_ieee@plt 1790; RV64I-NEXT: and a0, a0, s1 1791; RV64I-NEXT: call __gnu_h2f_ieee@plt 1792; RV64I-NEXT: lui a1, 524288 1793; RV64I-NEXT: xor a0, a0, a1 1794; RV64I-NEXT: call __gnu_f2h_ieee@plt 1795; RV64I-NEXT: mv s0, a0 1796; RV64I-NEXT: and a0, s2, s1 1797; RV64I-NEXT: call __gnu_h2f_ieee@plt 1798; RV64I-NEXT: mv s2, a0 1799; RV64I-NEXT: and a0, s0, s1 1800; RV64I-NEXT: call __gnu_h2f_ieee@plt 1801; RV64I-NEXT: mv a1, s2 1802; RV64I-NEXT: call __subsf3@plt 1803; RV64I-NEXT: call __gnu_f2h_ieee@plt 1804; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1805; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1806; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1807; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1808; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1809; RV64I-NEXT: ld s4, 0(sp) # 8-byte Folded Reload 1810; RV64I-NEXT: addi sp, sp, 48 1811; RV64I-NEXT: ret 1812 %a_ = fadd half 0.0, %a ; avoid negation using xor 1813 %b_ = fadd half 0.0, %b ; avoid negation using xor 1814 %c_ = fadd half 0.0, %c ; avoid negation using xor 1815 %1 = fmul contract half %a_, %b_ 1816 %2 = fneg half %1 1817 %3 = fsub contract half %2, %c_ 1818 ret half %3 1819} 1820 1821define half @fnmsub_s_contract(half %a, half %b, half %c) nounwind { 1822; RV32IZFH-LABEL: fnmsub_s_contract: 1823; RV32IZFH: # %bb.0: 1824; RV32IZFH-NEXT: fmv.h.x ft0, zero 1825; RV32IZFH-NEXT: fadd.h ft1, fa0, ft0 1826; RV32IZFH-NEXT: fadd.h ft0, fa1, ft0 1827; RV32IZFH-NEXT: fnmsub.h fa0, ft1, ft0, fa2 1828; RV32IZFH-NEXT: ret 1829; 1830; RV64IZFH-LABEL: fnmsub_s_contract: 1831; RV64IZFH: # %bb.0: 1832; RV64IZFH-NEXT: fmv.h.x ft0, zero 1833; RV64IZFH-NEXT: fadd.h ft1, fa0, ft0 1834; RV64IZFH-NEXT: fadd.h ft0, fa1, ft0 1835; RV64IZFH-NEXT: fnmsub.h fa0, ft1, ft0, fa2 1836; RV64IZFH-NEXT: ret 1837; 1838; RV32I-LABEL: fnmsub_s_contract: 1839; RV32I: # %bb.0: 1840; RV32I-NEXT: addi sp, sp, -32 1841; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 1842; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 1843; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 1844; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 1845; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 1846; RV32I-NEXT: mv s2, a2 1847; RV32I-NEXT: mv s1, a1 1848; RV32I-NEXT: lui a1, 16 1849; RV32I-NEXT: addi s0, a1, -1 1850; RV32I-NEXT: and a0, a0, s0 1851; RV32I-NEXT: call __gnu_h2f_ieee@plt 1852; RV32I-NEXT: li a1, 0 1853; RV32I-NEXT: call __addsf3@plt 1854; RV32I-NEXT: call __gnu_f2h_ieee@plt 1855; RV32I-NEXT: mv s3, a0 1856; RV32I-NEXT: and a0, s1, s0 1857; RV32I-NEXT: call __gnu_h2f_ieee@plt 1858; RV32I-NEXT: li a1, 0 1859; RV32I-NEXT: call __addsf3@plt 1860; RV32I-NEXT: call __gnu_f2h_ieee@plt 1861; RV32I-NEXT: mv s1, a0 1862; RV32I-NEXT: and a0, s3, s0 1863; RV32I-NEXT: call __gnu_h2f_ieee@plt 1864; RV32I-NEXT: mv s3, a0 1865; RV32I-NEXT: and a0, s1, s0 1866; RV32I-NEXT: call __gnu_h2f_ieee@plt 1867; RV32I-NEXT: mv a1, a0 1868; RV32I-NEXT: mv a0, s3 1869; RV32I-NEXT: call __mulsf3@plt 1870; RV32I-NEXT: call __gnu_f2h_ieee@plt 1871; RV32I-NEXT: mv s1, a0 1872; RV32I-NEXT: and a0, s2, s0 1873; RV32I-NEXT: call __gnu_h2f_ieee@plt 1874; RV32I-NEXT: mv s2, a0 1875; RV32I-NEXT: and a0, s1, s0 1876; RV32I-NEXT: call __gnu_h2f_ieee@plt 1877; RV32I-NEXT: mv a1, a0 1878; RV32I-NEXT: mv a0, s2 1879; RV32I-NEXT: call __subsf3@plt 1880; RV32I-NEXT: call __gnu_f2h_ieee@plt 1881; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1882; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1883; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1884; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1885; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1886; RV32I-NEXT: addi sp, sp, 32 1887; RV32I-NEXT: ret 1888; 1889; RV64I-LABEL: fnmsub_s_contract: 1890; RV64I: # %bb.0: 1891; RV64I-NEXT: addi sp, sp, -48 1892; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1893; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1894; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1895; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1896; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1897; RV64I-NEXT: mv s2, a2 1898; RV64I-NEXT: mv s1, a1 1899; RV64I-NEXT: lui a1, 16 1900; RV64I-NEXT: addiw s0, a1, -1 1901; RV64I-NEXT: and a0, a0, s0 1902; RV64I-NEXT: call __gnu_h2f_ieee@plt 1903; RV64I-NEXT: li a1, 0 1904; RV64I-NEXT: call __addsf3@plt 1905; RV64I-NEXT: call __gnu_f2h_ieee@plt 1906; RV64I-NEXT: mv s3, a0 1907; RV64I-NEXT: and a0, s1, s0 1908; RV64I-NEXT: call __gnu_h2f_ieee@plt 1909; RV64I-NEXT: li a1, 0 1910; RV64I-NEXT: call __addsf3@plt 1911; RV64I-NEXT: call __gnu_f2h_ieee@plt 1912; RV64I-NEXT: mv s1, a0 1913; RV64I-NEXT: and a0, s3, s0 1914; RV64I-NEXT: call __gnu_h2f_ieee@plt 1915; RV64I-NEXT: mv s3, a0 1916; RV64I-NEXT: and a0, s1, s0 1917; RV64I-NEXT: call __gnu_h2f_ieee@plt 1918; RV64I-NEXT: mv a1, a0 1919; RV64I-NEXT: mv a0, s3 1920; RV64I-NEXT: call __mulsf3@plt 1921; RV64I-NEXT: call __gnu_f2h_ieee@plt 1922; RV64I-NEXT: mv s1, a0 1923; RV64I-NEXT: and a0, s2, s0 1924; RV64I-NEXT: call __gnu_h2f_ieee@plt 1925; RV64I-NEXT: mv s2, a0 1926; RV64I-NEXT: and a0, s1, s0 1927; RV64I-NEXT: call __gnu_h2f_ieee@plt 1928; RV64I-NEXT: mv a1, a0 1929; RV64I-NEXT: mv a0, s2 1930; RV64I-NEXT: call __subsf3@plt 1931; RV64I-NEXT: call __gnu_f2h_ieee@plt 1932; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1933; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1934; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1935; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1936; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1937; RV64I-NEXT: addi sp, sp, 48 1938; RV64I-NEXT: ret 1939 %a_ = fadd half 0.0, %a ; avoid negation using xor 1940 %b_ = fadd half 0.0, %b ; avoid negation using xor 1941 %1 = fmul contract half %a_, %b_ 1942 %2 = fsub contract half %c, %1 1943 ret half %2 1944} 1945