1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefix=RV32IF %s 4; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ 5; RUN: | FileCheck -check-prefix=RV64IF %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 float-fcmp.ll and float-convert.ll 13; respectively. Some other float-*.ll files in this folder exercise LLVM IR 14; instructions that don't directly match a RISC-V instruction. 15 16define float @fadd_s(float %a, float %b) nounwind { 17; RV32IF-LABEL: fadd_s: 18; RV32IF: # %bb.0: 19; RV32IF-NEXT: fmv.w.x ft0, a1 20; RV32IF-NEXT: fmv.w.x ft1, a0 21; RV32IF-NEXT: fadd.s ft0, ft1, ft0 22; RV32IF-NEXT: fmv.x.w a0, ft0 23; RV32IF-NEXT: ret 24; 25; RV64IF-LABEL: fadd_s: 26; RV64IF: # %bb.0: 27; RV64IF-NEXT: fmv.w.x ft0, a1 28; RV64IF-NEXT: fmv.w.x ft1, a0 29; RV64IF-NEXT: fadd.s ft0, ft1, ft0 30; RV64IF-NEXT: fmv.x.w a0, ft0 31; RV64IF-NEXT: ret 32; 33; RV32I-LABEL: fadd_s: 34; RV32I: # %bb.0: 35; RV32I-NEXT: addi sp, sp, -16 36; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 37; RV32I-NEXT: call __addsf3@plt 38; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 39; RV32I-NEXT: addi sp, sp, 16 40; RV32I-NEXT: ret 41; 42; RV64I-LABEL: fadd_s: 43; RV64I: # %bb.0: 44; RV64I-NEXT: addi sp, sp, -16 45; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 46; RV64I-NEXT: call __addsf3@plt 47; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 48; RV64I-NEXT: addi sp, sp, 16 49; RV64I-NEXT: ret 50 %1 = fadd float %a, %b 51 ret float %1 52} 53 54define float @fsub_s(float %a, float %b) nounwind { 55; RV32IF-LABEL: fsub_s: 56; RV32IF: # %bb.0: 57; RV32IF-NEXT: fmv.w.x ft0, a1 58; RV32IF-NEXT: fmv.w.x ft1, a0 59; RV32IF-NEXT: fsub.s ft0, ft1, ft0 60; RV32IF-NEXT: fmv.x.w a0, ft0 61; RV32IF-NEXT: ret 62; 63; RV64IF-LABEL: fsub_s: 64; RV64IF: # %bb.0: 65; RV64IF-NEXT: fmv.w.x ft0, a1 66; RV64IF-NEXT: fmv.w.x ft1, a0 67; RV64IF-NEXT: fsub.s ft0, ft1, ft0 68; RV64IF-NEXT: fmv.x.w a0, ft0 69; RV64IF-NEXT: ret 70; 71; RV32I-LABEL: fsub_s: 72; RV32I: # %bb.0: 73; RV32I-NEXT: addi sp, sp, -16 74; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 75; RV32I-NEXT: call __subsf3@plt 76; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 77; RV32I-NEXT: addi sp, sp, 16 78; RV32I-NEXT: ret 79; 80; RV64I-LABEL: fsub_s: 81; RV64I: # %bb.0: 82; RV64I-NEXT: addi sp, sp, -16 83; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 84; RV64I-NEXT: call __subsf3@plt 85; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 86; RV64I-NEXT: addi sp, sp, 16 87; RV64I-NEXT: ret 88 %1 = fsub float %a, %b 89 ret float %1 90} 91 92define float @fmul_s(float %a, float %b) nounwind { 93; RV32IF-LABEL: fmul_s: 94; RV32IF: # %bb.0: 95; RV32IF-NEXT: fmv.w.x ft0, a1 96; RV32IF-NEXT: fmv.w.x ft1, a0 97; RV32IF-NEXT: fmul.s ft0, ft1, ft0 98; RV32IF-NEXT: fmv.x.w a0, ft0 99; RV32IF-NEXT: ret 100; 101; RV64IF-LABEL: fmul_s: 102; RV64IF: # %bb.0: 103; RV64IF-NEXT: fmv.w.x ft0, a1 104; RV64IF-NEXT: fmv.w.x ft1, a0 105; RV64IF-NEXT: fmul.s ft0, ft1, ft0 106; RV64IF-NEXT: fmv.x.w a0, ft0 107; RV64IF-NEXT: ret 108; 109; RV32I-LABEL: fmul_s: 110; RV32I: # %bb.0: 111; RV32I-NEXT: addi sp, sp, -16 112; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 113; RV32I-NEXT: call __mulsf3@plt 114; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 115; RV32I-NEXT: addi sp, sp, 16 116; RV32I-NEXT: ret 117; 118; RV64I-LABEL: fmul_s: 119; RV64I: # %bb.0: 120; RV64I-NEXT: addi sp, sp, -16 121; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 122; RV64I-NEXT: call __mulsf3@plt 123; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 124; RV64I-NEXT: addi sp, sp, 16 125; RV64I-NEXT: ret 126 %1 = fmul float %a, %b 127 ret float %1 128} 129 130define float @fdiv_s(float %a, float %b) nounwind { 131; RV32IF-LABEL: fdiv_s: 132; RV32IF: # %bb.0: 133; RV32IF-NEXT: fmv.w.x ft0, a1 134; RV32IF-NEXT: fmv.w.x ft1, a0 135; RV32IF-NEXT: fdiv.s ft0, ft1, ft0 136; RV32IF-NEXT: fmv.x.w a0, ft0 137; RV32IF-NEXT: ret 138; 139; RV64IF-LABEL: fdiv_s: 140; RV64IF: # %bb.0: 141; RV64IF-NEXT: fmv.w.x ft0, a1 142; RV64IF-NEXT: fmv.w.x ft1, a0 143; RV64IF-NEXT: fdiv.s ft0, ft1, ft0 144; RV64IF-NEXT: fmv.x.w a0, ft0 145; RV64IF-NEXT: ret 146; 147; RV32I-LABEL: fdiv_s: 148; RV32I: # %bb.0: 149; RV32I-NEXT: addi sp, sp, -16 150; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 151; RV32I-NEXT: call __divsf3@plt 152; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 153; RV32I-NEXT: addi sp, sp, 16 154; RV32I-NEXT: ret 155; 156; RV64I-LABEL: fdiv_s: 157; RV64I: # %bb.0: 158; RV64I-NEXT: addi sp, sp, -16 159; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 160; RV64I-NEXT: call __divsf3@plt 161; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 162; RV64I-NEXT: addi sp, sp, 16 163; RV64I-NEXT: ret 164 %1 = fdiv float %a, %b 165 ret float %1 166} 167 168declare float @llvm.sqrt.f32(float) 169 170define float @fsqrt_s(float %a) nounwind { 171; RV32IF-LABEL: fsqrt_s: 172; RV32IF: # %bb.0: 173; RV32IF-NEXT: fmv.w.x ft0, a0 174; RV32IF-NEXT: fsqrt.s ft0, ft0 175; RV32IF-NEXT: fmv.x.w a0, ft0 176; RV32IF-NEXT: ret 177; 178; RV64IF-LABEL: fsqrt_s: 179; RV64IF: # %bb.0: 180; RV64IF-NEXT: fmv.w.x ft0, a0 181; RV64IF-NEXT: fsqrt.s ft0, ft0 182; RV64IF-NEXT: fmv.x.w a0, ft0 183; RV64IF-NEXT: ret 184; 185; RV32I-LABEL: fsqrt_s: 186; RV32I: # %bb.0: 187; RV32I-NEXT: addi sp, sp, -16 188; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 189; RV32I-NEXT: call sqrtf@plt 190; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 191; RV32I-NEXT: addi sp, sp, 16 192; RV32I-NEXT: ret 193; 194; RV64I-LABEL: fsqrt_s: 195; RV64I: # %bb.0: 196; RV64I-NEXT: addi sp, sp, -16 197; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 198; RV64I-NEXT: call sqrtf@plt 199; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 200; RV64I-NEXT: addi sp, sp, 16 201; RV64I-NEXT: ret 202 %1 = call float @llvm.sqrt.f32(float %a) 203 ret float %1 204} 205 206declare float @llvm.copysign.f32(float, float) 207 208define float @fsgnj_s(float %a, float %b) nounwind { 209; RV32IF-LABEL: fsgnj_s: 210; RV32IF: # %bb.0: 211; RV32IF-NEXT: fmv.w.x ft0, a1 212; RV32IF-NEXT: fmv.w.x ft1, a0 213; RV32IF-NEXT: fsgnj.s ft0, ft1, ft0 214; RV32IF-NEXT: fmv.x.w a0, ft0 215; RV32IF-NEXT: ret 216; 217; RV64IF-LABEL: fsgnj_s: 218; RV64IF: # %bb.0: 219; RV64IF-NEXT: fmv.w.x ft0, a1 220; RV64IF-NEXT: fmv.w.x ft1, a0 221; RV64IF-NEXT: fsgnj.s ft0, ft1, ft0 222; RV64IF-NEXT: fmv.x.w a0, ft0 223; RV64IF-NEXT: ret 224; 225; RV32I-LABEL: fsgnj_s: 226; RV32I: # %bb.0: 227; RV32I-NEXT: lui a2, 524288 228; RV32I-NEXT: and a1, a1, a2 229; RV32I-NEXT: addi a2, a2, -1 230; RV32I-NEXT: and a0, a0, a2 231; RV32I-NEXT: or a0, a0, a1 232; RV32I-NEXT: ret 233; 234; RV64I-LABEL: fsgnj_s: 235; RV64I: # %bb.0: 236; RV64I-NEXT: lui a2, 524288 237; RV64I-NEXT: and a1, a1, a2 238; RV64I-NEXT: addiw a2, a2, -1 239; RV64I-NEXT: and a0, a0, a2 240; RV64I-NEXT: or a0, a0, a1 241; RV64I-NEXT: ret 242 %1 = call float @llvm.copysign.f32(float %a, float %b) 243 ret float %1 244} 245 246; This function performs extra work to ensure that 247; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor. 248define i32 @fneg_s(float %a, float %b) nounwind { 249; RV32IF-LABEL: fneg_s: 250; RV32IF: # %bb.0: 251; RV32IF-NEXT: fmv.w.x ft0, a0 252; RV32IF-NEXT: fadd.s ft0, ft0, ft0 253; RV32IF-NEXT: fneg.s ft1, ft0 254; RV32IF-NEXT: feq.s a0, ft0, ft1 255; RV32IF-NEXT: ret 256; 257; RV64IF-LABEL: fneg_s: 258; RV64IF: # %bb.0: 259; RV64IF-NEXT: fmv.w.x ft0, a0 260; RV64IF-NEXT: fadd.s ft0, ft0, ft0 261; RV64IF-NEXT: fneg.s ft1, ft0 262; RV64IF-NEXT: feq.s a0, ft0, ft1 263; RV64IF-NEXT: ret 264; 265; RV32I-LABEL: fneg_s: 266; RV32I: # %bb.0: 267; RV32I-NEXT: addi sp, sp, -16 268; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 269; RV32I-NEXT: mv a1, a0 270; RV32I-NEXT: call __addsf3@plt 271; RV32I-NEXT: lui a1, 524288 272; RV32I-NEXT: xor a1, a0, a1 273; RV32I-NEXT: call __eqsf2@plt 274; RV32I-NEXT: seqz a0, a0 275; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 276; RV32I-NEXT: addi sp, sp, 16 277; RV32I-NEXT: ret 278; 279; RV64I-LABEL: fneg_s: 280; RV64I: # %bb.0: 281; RV64I-NEXT: addi sp, sp, -16 282; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 283; RV64I-NEXT: mv a1, a0 284; RV64I-NEXT: call __addsf3@plt 285; RV64I-NEXT: lui a1, 524288 286; RV64I-NEXT: xor a1, a0, a1 287; RV64I-NEXT: call __eqsf2@plt 288; RV64I-NEXT: seqz a0, a0 289; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 290; RV64I-NEXT: addi sp, sp, 16 291; RV64I-NEXT: ret 292 %1 = fadd float %a, %a 293 %2 = fneg float %1 294 %3 = fcmp oeq float %1, %2 295 %4 = zext i1 %3 to i32 296 ret i32 %4 297} 298 299; This function performs extra work to ensure that 300; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor. 301define float @fsgnjn_s(float %a, float %b) nounwind { 302; RV32IF-LABEL: fsgnjn_s: 303; RV32IF: # %bb.0: 304; RV32IF-NEXT: fmv.w.x ft0, a1 305; RV32IF-NEXT: fmv.w.x ft1, a0 306; RV32IF-NEXT: fadd.s ft0, ft1, ft0 307; RV32IF-NEXT: fsgnjn.s ft0, ft1, ft0 308; RV32IF-NEXT: fmv.x.w a0, ft0 309; RV32IF-NEXT: ret 310; 311; RV64IF-LABEL: fsgnjn_s: 312; RV64IF: # %bb.0: 313; RV64IF-NEXT: fmv.w.x ft0, a1 314; RV64IF-NEXT: fmv.w.x ft1, a0 315; RV64IF-NEXT: fadd.s ft0, ft1, ft0 316; RV64IF-NEXT: fsgnjn.s ft0, ft1, ft0 317; RV64IF-NEXT: fmv.x.w a0, ft0 318; RV64IF-NEXT: ret 319; 320; RV32I-LABEL: fsgnjn_s: 321; RV32I: # %bb.0: 322; RV32I-NEXT: addi sp, sp, -16 323; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 324; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 325; RV32I-NEXT: mv s0, a0 326; RV32I-NEXT: call __addsf3@plt 327; RV32I-NEXT: not a0, a0 328; RV32I-NEXT: lui a1, 524288 329; RV32I-NEXT: addi a2, a1, -1 330; RV32I-NEXT: and a2, s0, a2 331; RV32I-NEXT: and a0, a0, a1 332; RV32I-NEXT: or a0, a2, a0 333; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 334; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 335; RV32I-NEXT: addi sp, sp, 16 336; RV32I-NEXT: ret 337; 338; RV64I-LABEL: fsgnjn_s: 339; RV64I: # %bb.0: 340; RV64I-NEXT: addi sp, sp, -16 341; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 342; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill 343; RV64I-NEXT: mv s0, a0 344; RV64I-NEXT: call __addsf3@plt 345; RV64I-NEXT: not a0, a0 346; RV64I-NEXT: lui a1, 524288 347; RV64I-NEXT: addiw a2, a1, -1 348; RV64I-NEXT: and a2, s0, a2 349; RV64I-NEXT: and a0, a0, a1 350; RV64I-NEXT: or a0, a2, a0 351; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 352; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload 353; RV64I-NEXT: addi sp, sp, 16 354; RV64I-NEXT: ret 355 %1 = fadd float %a, %b 356 %2 = fneg float %1 357 %3 = call float @llvm.copysign.f32(float %a, float %2) 358 ret float %3 359} 360 361declare float @llvm.fabs.f32(float) 362 363; This function performs extra work to ensure that 364; DAGCombiner::visitBITCAST doesn't replace the fabs with an and. 365define float @fabs_s(float %a, float %b) nounwind { 366; RV32IF-LABEL: fabs_s: 367; RV32IF: # %bb.0: 368; RV32IF-NEXT: fmv.w.x ft0, a1 369; RV32IF-NEXT: fmv.w.x ft1, a0 370; RV32IF-NEXT: fadd.s ft0, ft1, ft0 371; RV32IF-NEXT: fabs.s ft1, ft0 372; RV32IF-NEXT: fadd.s ft0, ft1, ft0 373; RV32IF-NEXT: fmv.x.w a0, ft0 374; RV32IF-NEXT: ret 375; 376; RV64IF-LABEL: fabs_s: 377; RV64IF: # %bb.0: 378; RV64IF-NEXT: fmv.w.x ft0, a1 379; RV64IF-NEXT: fmv.w.x ft1, a0 380; RV64IF-NEXT: fadd.s ft0, ft1, ft0 381; RV64IF-NEXT: fabs.s ft1, ft0 382; RV64IF-NEXT: fadd.s ft0, ft1, ft0 383; RV64IF-NEXT: fmv.x.w a0, ft0 384; RV64IF-NEXT: ret 385; 386; RV32I-LABEL: fabs_s: 387; RV32I: # %bb.0: 388; RV32I-NEXT: addi sp, sp, -16 389; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 390; RV32I-NEXT: call __addsf3@plt 391; RV32I-NEXT: mv a1, a0 392; RV32I-NEXT: lui a0, 524288 393; RV32I-NEXT: addi a0, a0, -1 394; RV32I-NEXT: and a0, a1, a0 395; RV32I-NEXT: call __addsf3@plt 396; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 397; RV32I-NEXT: addi sp, sp, 16 398; RV32I-NEXT: ret 399; 400; RV64I-LABEL: fabs_s: 401; RV64I: # %bb.0: 402; RV64I-NEXT: addi sp, sp, -16 403; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 404; RV64I-NEXT: call __addsf3@plt 405; RV64I-NEXT: mv a1, a0 406; RV64I-NEXT: lui a0, 524288 407; RV64I-NEXT: addiw a0, a0, -1 408; RV64I-NEXT: and a0, a1, a0 409; RV64I-NEXT: call __addsf3@plt 410; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 411; RV64I-NEXT: addi sp, sp, 16 412; RV64I-NEXT: ret 413 %1 = fadd float %a, %b 414 %2 = call float @llvm.fabs.f32(float %1) 415 %3 = fadd float %2, %1 416 ret float %3 417} 418 419declare float @llvm.minnum.f32(float, float) 420 421define float @fmin_s(float %a, float %b) nounwind { 422; RV32IF-LABEL: fmin_s: 423; RV32IF: # %bb.0: 424; RV32IF-NEXT: fmv.w.x ft0, a1 425; RV32IF-NEXT: fmv.w.x ft1, a0 426; RV32IF-NEXT: fmin.s ft0, ft1, ft0 427; RV32IF-NEXT: fmv.x.w a0, ft0 428; RV32IF-NEXT: ret 429; 430; RV64IF-LABEL: fmin_s: 431; RV64IF: # %bb.0: 432; RV64IF-NEXT: fmv.w.x ft0, a1 433; RV64IF-NEXT: fmv.w.x ft1, a0 434; RV64IF-NEXT: fmin.s ft0, ft1, ft0 435; RV64IF-NEXT: fmv.x.w a0, ft0 436; RV64IF-NEXT: ret 437; 438; RV32I-LABEL: fmin_s: 439; RV32I: # %bb.0: 440; RV32I-NEXT: addi sp, sp, -16 441; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 442; RV32I-NEXT: call fminf@plt 443; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 444; RV32I-NEXT: addi sp, sp, 16 445; RV32I-NEXT: ret 446; 447; RV64I-LABEL: fmin_s: 448; RV64I: # %bb.0: 449; RV64I-NEXT: addi sp, sp, -16 450; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 451; RV64I-NEXT: call fminf@plt 452; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 453; RV64I-NEXT: addi sp, sp, 16 454; RV64I-NEXT: ret 455 %1 = call float @llvm.minnum.f32(float %a, float %b) 456 ret float %1 457} 458 459declare float @llvm.maxnum.f32(float, float) 460 461define float @fmax_s(float %a, float %b) nounwind { 462; RV32IF-LABEL: fmax_s: 463; RV32IF: # %bb.0: 464; RV32IF-NEXT: fmv.w.x ft0, a1 465; RV32IF-NEXT: fmv.w.x ft1, a0 466; RV32IF-NEXT: fmax.s ft0, ft1, ft0 467; RV32IF-NEXT: fmv.x.w a0, ft0 468; RV32IF-NEXT: ret 469; 470; RV64IF-LABEL: fmax_s: 471; RV64IF: # %bb.0: 472; RV64IF-NEXT: fmv.w.x ft0, a1 473; RV64IF-NEXT: fmv.w.x ft1, a0 474; RV64IF-NEXT: fmax.s ft0, ft1, ft0 475; RV64IF-NEXT: fmv.x.w a0, ft0 476; RV64IF-NEXT: ret 477; 478; RV32I-LABEL: fmax_s: 479; RV32I: # %bb.0: 480; RV32I-NEXT: addi sp, sp, -16 481; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 482; RV32I-NEXT: call fmaxf@plt 483; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 484; RV32I-NEXT: addi sp, sp, 16 485; RV32I-NEXT: ret 486; 487; RV64I-LABEL: fmax_s: 488; RV64I: # %bb.0: 489; RV64I-NEXT: addi sp, sp, -16 490; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 491; RV64I-NEXT: call fmaxf@plt 492; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 493; RV64I-NEXT: addi sp, sp, 16 494; RV64I-NEXT: ret 495 %1 = call float @llvm.maxnum.f32(float %a, float %b) 496 ret float %1 497} 498 499declare float @llvm.fma.f32(float, float, float) 500 501define float @fmadd_s(float %a, float %b, float %c) nounwind { 502; RV32IF-LABEL: fmadd_s: 503; RV32IF: # %bb.0: 504; RV32IF-NEXT: fmv.w.x ft0, a2 505; RV32IF-NEXT: fmv.w.x ft1, a1 506; RV32IF-NEXT: fmv.w.x ft2, a0 507; RV32IF-NEXT: fmadd.s ft0, ft2, ft1, ft0 508; RV32IF-NEXT: fmv.x.w a0, ft0 509; RV32IF-NEXT: ret 510; 511; RV64IF-LABEL: fmadd_s: 512; RV64IF: # %bb.0: 513; RV64IF-NEXT: fmv.w.x ft0, a2 514; RV64IF-NEXT: fmv.w.x ft1, a1 515; RV64IF-NEXT: fmv.w.x ft2, a0 516; RV64IF-NEXT: fmadd.s ft0, ft2, ft1, ft0 517; RV64IF-NEXT: fmv.x.w a0, ft0 518; RV64IF-NEXT: ret 519; 520; RV32I-LABEL: fmadd_s: 521; RV32I: # %bb.0: 522; RV32I-NEXT: addi sp, sp, -16 523; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 524; RV32I-NEXT: call fmaf@plt 525; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 526; RV32I-NEXT: addi sp, sp, 16 527; RV32I-NEXT: ret 528; 529; RV64I-LABEL: fmadd_s: 530; RV64I: # %bb.0: 531; RV64I-NEXT: addi sp, sp, -16 532; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 533; RV64I-NEXT: call fmaf@plt 534; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 535; RV64I-NEXT: addi sp, sp, 16 536; RV64I-NEXT: ret 537 %1 = call float @llvm.fma.f32(float %a, float %b, float %c) 538 ret float %1 539} 540 541define float @fmsub_s(float %a, float %b, float %c) nounwind { 542; RV32IF-LABEL: fmsub_s: 543; RV32IF: # %bb.0: 544; RV32IF-NEXT: fmv.w.x ft0, a1 545; RV32IF-NEXT: fmv.w.x ft1, a0 546; RV32IF-NEXT: fmv.w.x ft2, a2 547; RV32IF-NEXT: fmv.w.x ft3, zero 548; RV32IF-NEXT: fadd.s ft2, ft2, ft3 549; RV32IF-NEXT: fmsub.s ft0, ft1, ft0, ft2 550; RV32IF-NEXT: fmv.x.w a0, ft0 551; RV32IF-NEXT: ret 552; 553; RV64IF-LABEL: fmsub_s: 554; RV64IF: # %bb.0: 555; RV64IF-NEXT: fmv.w.x ft0, a1 556; RV64IF-NEXT: fmv.w.x ft1, a0 557; RV64IF-NEXT: fmv.w.x ft2, a2 558; RV64IF-NEXT: fmv.w.x ft3, zero 559; RV64IF-NEXT: fadd.s ft2, ft2, ft3 560; RV64IF-NEXT: fmsub.s ft0, ft1, ft0, ft2 561; RV64IF-NEXT: fmv.x.w a0, ft0 562; RV64IF-NEXT: ret 563; 564; RV32I-LABEL: fmsub_s: 565; RV32I: # %bb.0: 566; RV32I-NEXT: addi sp, sp, -16 567; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 568; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 569; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 570; RV32I-NEXT: mv s0, a1 571; RV32I-NEXT: mv s1, a0 572; RV32I-NEXT: mv a0, a2 573; RV32I-NEXT: li a1, 0 574; RV32I-NEXT: call __addsf3@plt 575; RV32I-NEXT: lui a1, 524288 576; RV32I-NEXT: xor a2, a0, a1 577; RV32I-NEXT: mv a0, s1 578; RV32I-NEXT: mv a1, s0 579; RV32I-NEXT: call fmaf@plt 580; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 581; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 582; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 583; RV32I-NEXT: addi sp, sp, 16 584; RV32I-NEXT: ret 585; 586; RV64I-LABEL: fmsub_s: 587; RV64I: # %bb.0: 588; RV64I-NEXT: addi sp, sp, -32 589; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 590; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 591; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 592; RV64I-NEXT: mv s0, a1 593; RV64I-NEXT: mv s1, a0 594; RV64I-NEXT: mv a0, a2 595; RV64I-NEXT: li a1, 0 596; RV64I-NEXT: call __addsf3@plt 597; RV64I-NEXT: lui a1, 524288 598; RV64I-NEXT: xor a2, a0, a1 599; RV64I-NEXT: mv a0, s1 600; RV64I-NEXT: mv a1, s0 601; RV64I-NEXT: call fmaf@plt 602; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 603; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 604; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 605; RV64I-NEXT: addi sp, sp, 32 606; RV64I-NEXT: ret 607 %c_ = fadd float 0.0, %c ; avoid negation using xor 608 %negc = fsub float -0.0, %c_ 609 %1 = call float @llvm.fma.f32(float %a, float %b, float %negc) 610 ret float %1 611} 612 613define float @fnmadd_s(float %a, float %b, float %c) nounwind { 614; RV32IF-LABEL: fnmadd_s: 615; RV32IF: # %bb.0: 616; RV32IF-NEXT: fmv.w.x ft0, a1 617; RV32IF-NEXT: fmv.w.x ft1, a2 618; RV32IF-NEXT: fmv.w.x ft2, a0 619; RV32IF-NEXT: fmv.w.x ft3, zero 620; RV32IF-NEXT: fadd.s ft2, ft2, ft3 621; RV32IF-NEXT: fadd.s ft1, ft1, ft3 622; RV32IF-NEXT: fnmadd.s ft0, ft2, ft0, ft1 623; RV32IF-NEXT: fmv.x.w a0, ft0 624; RV32IF-NEXT: ret 625; 626; RV64IF-LABEL: fnmadd_s: 627; RV64IF: # %bb.0: 628; RV64IF-NEXT: fmv.w.x ft0, a1 629; RV64IF-NEXT: fmv.w.x ft1, a2 630; RV64IF-NEXT: fmv.w.x ft2, a0 631; RV64IF-NEXT: fmv.w.x ft3, zero 632; RV64IF-NEXT: fadd.s ft2, ft2, ft3 633; RV64IF-NEXT: fadd.s ft1, ft1, ft3 634; RV64IF-NEXT: fnmadd.s ft0, ft2, ft0, ft1 635; RV64IF-NEXT: fmv.x.w a0, ft0 636; RV64IF-NEXT: ret 637; 638; RV32I-LABEL: fnmadd_s: 639; RV32I: # %bb.0: 640; RV32I-NEXT: addi sp, sp, -16 641; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 642; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 643; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 644; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 645; RV32I-NEXT: mv s0, a2 646; RV32I-NEXT: mv s2, a1 647; RV32I-NEXT: li a1, 0 648; RV32I-NEXT: call __addsf3@plt 649; RV32I-NEXT: mv s1, a0 650; RV32I-NEXT: mv a0, s0 651; RV32I-NEXT: li a1, 0 652; RV32I-NEXT: call __addsf3@plt 653; RV32I-NEXT: lui a2, 524288 654; RV32I-NEXT: xor a1, s1, a2 655; RV32I-NEXT: xor a2, a0, a2 656; RV32I-NEXT: mv a0, a1 657; RV32I-NEXT: mv a1, s2 658; RV32I-NEXT: call fmaf@plt 659; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 660; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 661; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 662; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 663; RV32I-NEXT: addi sp, sp, 16 664; RV32I-NEXT: ret 665; 666; RV64I-LABEL: fnmadd_s: 667; RV64I: # %bb.0: 668; RV64I-NEXT: addi sp, sp, -32 669; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 670; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 671; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 672; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 673; RV64I-NEXT: mv s0, a2 674; RV64I-NEXT: mv s2, a1 675; RV64I-NEXT: li a1, 0 676; RV64I-NEXT: call __addsf3@plt 677; RV64I-NEXT: mv s1, a0 678; RV64I-NEXT: mv a0, s0 679; RV64I-NEXT: li a1, 0 680; RV64I-NEXT: call __addsf3@plt 681; RV64I-NEXT: lui a2, 524288 682; RV64I-NEXT: xor a1, s1, a2 683; RV64I-NEXT: xor a2, a0, a2 684; RV64I-NEXT: mv a0, a1 685; RV64I-NEXT: mv a1, s2 686; RV64I-NEXT: call fmaf@plt 687; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 688; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 689; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 690; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 691; RV64I-NEXT: addi sp, sp, 32 692; RV64I-NEXT: ret 693 %a_ = fadd float 0.0, %a 694 %c_ = fadd float 0.0, %c 695 %nega = fsub float -0.0, %a_ 696 %negc = fsub float -0.0, %c_ 697 %1 = call float @llvm.fma.f32(float %nega, float %b, float %negc) 698 ret float %1 699} 700 701define float @fnmadd_s_2(float %a, float %b, float %c) nounwind { 702; RV32IF-LABEL: fnmadd_s_2: 703; RV32IF: # %bb.0: 704; RV32IF-NEXT: fmv.w.x ft0, a0 705; RV32IF-NEXT: fmv.w.x ft1, a2 706; RV32IF-NEXT: fmv.w.x ft2, a1 707; RV32IF-NEXT: fmv.w.x ft3, zero 708; RV32IF-NEXT: fadd.s ft2, ft2, ft3 709; RV32IF-NEXT: fadd.s ft1, ft1, ft3 710; RV32IF-NEXT: fnmadd.s ft0, ft2, ft0, ft1 711; RV32IF-NEXT: fmv.x.w a0, ft0 712; RV32IF-NEXT: ret 713; 714; RV64IF-LABEL: fnmadd_s_2: 715; RV64IF: # %bb.0: 716; RV64IF-NEXT: fmv.w.x ft0, a0 717; RV64IF-NEXT: fmv.w.x ft1, a2 718; RV64IF-NEXT: fmv.w.x ft2, a1 719; RV64IF-NEXT: fmv.w.x ft3, zero 720; RV64IF-NEXT: fadd.s ft2, ft2, ft3 721; RV64IF-NEXT: fadd.s ft1, ft1, ft3 722; RV64IF-NEXT: fnmadd.s ft0, ft2, ft0, ft1 723; RV64IF-NEXT: fmv.x.w a0, ft0 724; RV64IF-NEXT: ret 725; 726; RV32I-LABEL: fnmadd_s_2: 727; RV32I: # %bb.0: 728; RV32I-NEXT: addi sp, sp, -16 729; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 730; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 731; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 732; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 733; RV32I-NEXT: mv s0, a2 734; RV32I-NEXT: mv s2, a0 735; RV32I-NEXT: mv a0, a1 736; RV32I-NEXT: li a1, 0 737; RV32I-NEXT: call __addsf3@plt 738; RV32I-NEXT: mv s1, a0 739; RV32I-NEXT: mv a0, s0 740; RV32I-NEXT: li a1, 0 741; RV32I-NEXT: call __addsf3@plt 742; RV32I-NEXT: lui a2, 524288 743; RV32I-NEXT: xor a1, s1, a2 744; RV32I-NEXT: xor a2, a0, a2 745; RV32I-NEXT: mv a0, s2 746; RV32I-NEXT: call fmaf@plt 747; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 748; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 749; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 750; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 751; RV32I-NEXT: addi sp, sp, 16 752; RV32I-NEXT: ret 753; 754; RV64I-LABEL: fnmadd_s_2: 755; RV64I: # %bb.0: 756; RV64I-NEXT: addi sp, sp, -32 757; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 758; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 759; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 760; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 761; RV64I-NEXT: mv s0, a2 762; RV64I-NEXT: mv s2, a0 763; RV64I-NEXT: mv a0, a1 764; RV64I-NEXT: li a1, 0 765; RV64I-NEXT: call __addsf3@plt 766; RV64I-NEXT: mv s1, a0 767; RV64I-NEXT: mv a0, s0 768; RV64I-NEXT: li a1, 0 769; RV64I-NEXT: call __addsf3@plt 770; RV64I-NEXT: lui a2, 524288 771; RV64I-NEXT: xor a1, s1, a2 772; RV64I-NEXT: xor a2, a0, a2 773; RV64I-NEXT: mv a0, s2 774; RV64I-NEXT: call fmaf@plt 775; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 776; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 777; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 778; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 779; RV64I-NEXT: addi sp, sp, 32 780; RV64I-NEXT: ret 781 %b_ = fadd float 0.0, %b 782 %c_ = fadd float 0.0, %c 783 %negb = fsub float -0.0, %b_ 784 %negc = fsub float -0.0, %c_ 785 %1 = call float @llvm.fma.f32(float %a, float %negb, float %negc) 786 ret float %1 787} 788 789define float @fnmsub_s(float %a, float %b, float %c) nounwind { 790; RV32IF-LABEL: fnmsub_s: 791; RV32IF: # %bb.0: 792; RV32IF-NEXT: fmv.w.x ft0, a2 793; RV32IF-NEXT: fmv.w.x ft1, a1 794; RV32IF-NEXT: fmv.w.x ft2, a0 795; RV32IF-NEXT: fmv.w.x ft3, zero 796; RV32IF-NEXT: fadd.s ft2, ft2, ft3 797; RV32IF-NEXT: fnmsub.s ft0, ft2, ft1, ft0 798; RV32IF-NEXT: fmv.x.w a0, ft0 799; RV32IF-NEXT: ret 800; 801; RV64IF-LABEL: fnmsub_s: 802; RV64IF: # %bb.0: 803; RV64IF-NEXT: fmv.w.x ft0, a2 804; RV64IF-NEXT: fmv.w.x ft1, a1 805; RV64IF-NEXT: fmv.w.x ft2, a0 806; RV64IF-NEXT: fmv.w.x ft3, zero 807; RV64IF-NEXT: fadd.s ft2, ft2, ft3 808; RV64IF-NEXT: fnmsub.s ft0, ft2, ft1, ft0 809; RV64IF-NEXT: fmv.x.w a0, ft0 810; RV64IF-NEXT: ret 811; 812; RV32I-LABEL: fnmsub_s: 813; RV32I: # %bb.0: 814; RV32I-NEXT: addi sp, sp, -16 815; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 816; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 817; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 818; RV32I-NEXT: mv s0, a2 819; RV32I-NEXT: mv s1, a1 820; RV32I-NEXT: li a1, 0 821; RV32I-NEXT: call __addsf3@plt 822; RV32I-NEXT: lui a1, 524288 823; RV32I-NEXT: xor a0, a0, a1 824; RV32I-NEXT: mv a1, s1 825; RV32I-NEXT: mv a2, s0 826; RV32I-NEXT: call fmaf@plt 827; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 828; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 829; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 830; RV32I-NEXT: addi sp, sp, 16 831; RV32I-NEXT: ret 832; 833; RV64I-LABEL: fnmsub_s: 834; RV64I: # %bb.0: 835; RV64I-NEXT: addi sp, sp, -32 836; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 837; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 838; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 839; RV64I-NEXT: mv s0, a2 840; RV64I-NEXT: mv s1, a1 841; RV64I-NEXT: li a1, 0 842; RV64I-NEXT: call __addsf3@plt 843; RV64I-NEXT: lui a1, 524288 844; RV64I-NEXT: xor a0, a0, a1 845; RV64I-NEXT: mv a1, s1 846; RV64I-NEXT: mv a2, s0 847; RV64I-NEXT: call fmaf@plt 848; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 849; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 850; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 851; RV64I-NEXT: addi sp, sp, 32 852; RV64I-NEXT: ret 853 %a_ = fadd float 0.0, %a 854 %nega = fsub float -0.0, %a_ 855 %1 = call float @llvm.fma.f32(float %nega, float %b, float %c) 856 ret float %1 857} 858 859define float @fnmsub_s_2(float %a, float %b, float %c) nounwind { 860; RV32IF-LABEL: fnmsub_s_2: 861; RV32IF: # %bb.0: 862; RV32IF-NEXT: fmv.w.x ft0, a2 863; RV32IF-NEXT: fmv.w.x ft1, a0 864; RV32IF-NEXT: fmv.w.x ft2, a1 865; RV32IF-NEXT: fmv.w.x ft3, zero 866; RV32IF-NEXT: fadd.s ft2, ft2, ft3 867; RV32IF-NEXT: fnmsub.s ft0, ft2, ft1, ft0 868; RV32IF-NEXT: fmv.x.w a0, ft0 869; RV32IF-NEXT: ret 870; 871; RV64IF-LABEL: fnmsub_s_2: 872; RV64IF: # %bb.0: 873; RV64IF-NEXT: fmv.w.x ft0, a2 874; RV64IF-NEXT: fmv.w.x ft1, a0 875; RV64IF-NEXT: fmv.w.x ft2, a1 876; RV64IF-NEXT: fmv.w.x ft3, zero 877; RV64IF-NEXT: fadd.s ft2, ft2, ft3 878; RV64IF-NEXT: fnmsub.s ft0, ft2, ft1, ft0 879; RV64IF-NEXT: fmv.x.w a0, ft0 880; RV64IF-NEXT: ret 881; 882; RV32I-LABEL: fnmsub_s_2: 883; RV32I: # %bb.0: 884; RV32I-NEXT: addi sp, sp, -16 885; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 886; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 887; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 888; RV32I-NEXT: mv s0, a2 889; RV32I-NEXT: mv s1, a0 890; RV32I-NEXT: mv a0, a1 891; RV32I-NEXT: li a1, 0 892; RV32I-NEXT: call __addsf3@plt 893; RV32I-NEXT: lui a1, 524288 894; RV32I-NEXT: xor a1, a0, a1 895; RV32I-NEXT: mv a0, s1 896; RV32I-NEXT: mv a2, s0 897; RV32I-NEXT: call fmaf@plt 898; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 899; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 900; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 901; RV32I-NEXT: addi sp, sp, 16 902; RV32I-NEXT: ret 903; 904; RV64I-LABEL: fnmsub_s_2: 905; RV64I: # %bb.0: 906; RV64I-NEXT: addi sp, sp, -32 907; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 908; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 909; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 910; RV64I-NEXT: mv s0, a2 911; RV64I-NEXT: mv s1, a0 912; RV64I-NEXT: mv a0, a1 913; RV64I-NEXT: li a1, 0 914; RV64I-NEXT: call __addsf3@plt 915; RV64I-NEXT: lui a1, 524288 916; RV64I-NEXT: xor a1, a0, a1 917; RV64I-NEXT: mv a0, s1 918; RV64I-NEXT: mv a2, s0 919; RV64I-NEXT: call fmaf@plt 920; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 921; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 922; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 923; RV64I-NEXT: addi sp, sp, 32 924; RV64I-NEXT: ret 925 %b_ = fadd float 0.0, %b 926 %negb = fsub float -0.0, %b_ 927 %1 = call float @llvm.fma.f32(float %a, float %negb, float %c) 928 ret float %1 929} 930 931define float @fmadd_s_contract(float %a, float %b, float %c) nounwind { 932; RV32IF-LABEL: fmadd_s_contract: 933; RV32IF: # %bb.0: 934; RV32IF-NEXT: fmv.w.x ft0, a2 935; RV32IF-NEXT: fmv.w.x ft1, a1 936; RV32IF-NEXT: fmv.w.x ft2, a0 937; RV32IF-NEXT: fmadd.s ft0, ft2, ft1, ft0 938; RV32IF-NEXT: fmv.x.w a0, ft0 939; RV32IF-NEXT: ret 940; 941; RV64IF-LABEL: fmadd_s_contract: 942; RV64IF: # %bb.0: 943; RV64IF-NEXT: fmv.w.x ft0, a2 944; RV64IF-NEXT: fmv.w.x ft1, a1 945; RV64IF-NEXT: fmv.w.x ft2, a0 946; RV64IF-NEXT: fmadd.s ft0, ft2, ft1, ft0 947; RV64IF-NEXT: fmv.x.w a0, ft0 948; RV64IF-NEXT: ret 949; 950; RV32I-LABEL: fmadd_s_contract: 951; RV32I: # %bb.0: 952; RV32I-NEXT: addi sp, sp, -16 953; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 954; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 955; RV32I-NEXT: mv s0, a2 956; RV32I-NEXT: call __mulsf3@plt 957; RV32I-NEXT: mv a1, s0 958; RV32I-NEXT: call __addsf3@plt 959; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 960; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 961; RV32I-NEXT: addi sp, sp, 16 962; RV32I-NEXT: ret 963; 964; RV64I-LABEL: fmadd_s_contract: 965; RV64I: # %bb.0: 966; RV64I-NEXT: addi sp, sp, -16 967; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill 968; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill 969; RV64I-NEXT: mv s0, a2 970; RV64I-NEXT: call __mulsf3@plt 971; RV64I-NEXT: mv a1, s0 972; RV64I-NEXT: call __addsf3@plt 973; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload 974; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload 975; RV64I-NEXT: addi sp, sp, 16 976; RV64I-NEXT: ret 977 %1 = fmul contract float %a, %b 978 %2 = fadd contract float %1, %c 979 ret float %2 980} 981 982define float @fmsub_s_contract(float %a, float %b, float %c) nounwind { 983; RV32IF-LABEL: fmsub_s_contract: 984; RV32IF: # %bb.0: 985; RV32IF-NEXT: fmv.w.x ft0, a1 986; RV32IF-NEXT: fmv.w.x ft1, a0 987; RV32IF-NEXT: fmv.w.x ft2, a2 988; RV32IF-NEXT: fmv.w.x ft3, zero 989; RV32IF-NEXT: fadd.s ft2, ft2, ft3 990; RV32IF-NEXT: fmsub.s ft0, ft1, ft0, ft2 991; RV32IF-NEXT: fmv.x.w a0, ft0 992; RV32IF-NEXT: ret 993; 994; RV64IF-LABEL: fmsub_s_contract: 995; RV64IF: # %bb.0: 996; RV64IF-NEXT: fmv.w.x ft0, a1 997; RV64IF-NEXT: fmv.w.x ft1, a0 998; RV64IF-NEXT: fmv.w.x ft2, a2 999; RV64IF-NEXT: fmv.w.x ft3, zero 1000; RV64IF-NEXT: fadd.s ft2, ft2, ft3 1001; RV64IF-NEXT: fmsub.s ft0, ft1, ft0, ft2 1002; RV64IF-NEXT: fmv.x.w a0, ft0 1003; RV64IF-NEXT: ret 1004; 1005; RV32I-LABEL: fmsub_s_contract: 1006; RV32I: # %bb.0: 1007; RV32I-NEXT: addi sp, sp, -16 1008; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 1009; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 1010; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 1011; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 1012; RV32I-NEXT: mv s2, a1 1013; RV32I-NEXT: mv s1, a0 1014; RV32I-NEXT: mv a0, a2 1015; RV32I-NEXT: li a1, 0 1016; RV32I-NEXT: call __addsf3@plt 1017; RV32I-NEXT: mv s0, a0 1018; RV32I-NEXT: mv a0, s1 1019; RV32I-NEXT: mv a1, s2 1020; RV32I-NEXT: call __mulsf3@plt 1021; RV32I-NEXT: mv a1, s0 1022; RV32I-NEXT: call __subsf3@plt 1023; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 1024; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 1025; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 1026; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 1027; RV32I-NEXT: addi sp, sp, 16 1028; RV32I-NEXT: ret 1029; 1030; RV64I-LABEL: fmsub_s_contract: 1031; RV64I: # %bb.0: 1032; RV64I-NEXT: addi sp, sp, -32 1033; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 1034; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 1035; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 1036; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 1037; RV64I-NEXT: mv s2, a1 1038; RV64I-NEXT: mv s1, a0 1039; RV64I-NEXT: mv a0, a2 1040; RV64I-NEXT: li a1, 0 1041; RV64I-NEXT: call __addsf3@plt 1042; RV64I-NEXT: mv s0, a0 1043; RV64I-NEXT: mv a0, s1 1044; RV64I-NEXT: mv a1, s2 1045; RV64I-NEXT: call __mulsf3@plt 1046; RV64I-NEXT: mv a1, s0 1047; RV64I-NEXT: call __subsf3@plt 1048; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 1049; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 1050; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 1051; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 1052; RV64I-NEXT: addi sp, sp, 32 1053; RV64I-NEXT: ret 1054 %c_ = fadd float 0.0, %c ; avoid negation using xor 1055 %1 = fmul contract float %a, %b 1056 %2 = fsub contract float %1, %c_ 1057 ret float %2 1058} 1059 1060define float @fnmadd_s_contract(float %a, float %b, float %c) nounwind { 1061; RV32IF-LABEL: fnmadd_s_contract: 1062; RV32IF: # %bb.0: 1063; RV32IF-NEXT: fmv.w.x ft0, a2 1064; RV32IF-NEXT: fmv.w.x ft1, a1 1065; RV32IF-NEXT: fmv.w.x ft2, a0 1066; RV32IF-NEXT: fmv.w.x ft3, zero 1067; RV32IF-NEXT: fadd.s ft2, ft2, ft3 1068; RV32IF-NEXT: fadd.s ft1, ft1, ft3 1069; RV32IF-NEXT: fadd.s ft0, ft0, ft3 1070; RV32IF-NEXT: fnmadd.s ft0, ft2, ft1, ft0 1071; RV32IF-NEXT: fmv.x.w a0, ft0 1072; RV32IF-NEXT: ret 1073; 1074; RV64IF-LABEL: fnmadd_s_contract: 1075; RV64IF: # %bb.0: 1076; RV64IF-NEXT: fmv.w.x ft0, a2 1077; RV64IF-NEXT: fmv.w.x ft1, a1 1078; RV64IF-NEXT: fmv.w.x ft2, a0 1079; RV64IF-NEXT: fmv.w.x ft3, zero 1080; RV64IF-NEXT: fadd.s ft2, ft2, ft3 1081; RV64IF-NEXT: fadd.s ft1, ft1, ft3 1082; RV64IF-NEXT: fadd.s ft0, ft0, ft3 1083; RV64IF-NEXT: fnmadd.s ft0, ft2, ft1, ft0 1084; RV64IF-NEXT: fmv.x.w a0, ft0 1085; RV64IF-NEXT: ret 1086; 1087; RV32I-LABEL: fnmadd_s_contract: 1088; RV32I: # %bb.0: 1089; RV32I-NEXT: addi sp, sp, -32 1090; RV32I-NEXT: sw ra, 28(sp) # 4-byte Folded Spill 1091; RV32I-NEXT: sw s0, 24(sp) # 4-byte Folded Spill 1092; RV32I-NEXT: sw s1, 20(sp) # 4-byte Folded Spill 1093; RV32I-NEXT: sw s2, 16(sp) # 4-byte Folded Spill 1094; RV32I-NEXT: sw s3, 12(sp) # 4-byte Folded Spill 1095; RV32I-NEXT: mv s2, a2 1096; RV32I-NEXT: mv s1, a1 1097; RV32I-NEXT: li a1, 0 1098; RV32I-NEXT: call __addsf3@plt 1099; RV32I-NEXT: mv s3, a0 1100; RV32I-NEXT: mv a0, s1 1101; RV32I-NEXT: li a1, 0 1102; RV32I-NEXT: call __addsf3@plt 1103; RV32I-NEXT: mv s1, a0 1104; RV32I-NEXT: mv a0, s2 1105; RV32I-NEXT: li a1, 0 1106; RV32I-NEXT: call __addsf3@plt 1107; RV32I-NEXT: mv s0, a0 1108; RV32I-NEXT: mv a0, s3 1109; RV32I-NEXT: mv a1, s1 1110; RV32I-NEXT: call __mulsf3@plt 1111; RV32I-NEXT: lui a1, 524288 1112; RV32I-NEXT: xor a0, a0, a1 1113; RV32I-NEXT: mv a1, s0 1114; RV32I-NEXT: call __subsf3@plt 1115; RV32I-NEXT: lw ra, 28(sp) # 4-byte Folded Reload 1116; RV32I-NEXT: lw s0, 24(sp) # 4-byte Folded Reload 1117; RV32I-NEXT: lw s1, 20(sp) # 4-byte Folded Reload 1118; RV32I-NEXT: lw s2, 16(sp) # 4-byte Folded Reload 1119; RV32I-NEXT: lw s3, 12(sp) # 4-byte Folded Reload 1120; RV32I-NEXT: addi sp, sp, 32 1121; RV32I-NEXT: ret 1122; 1123; RV64I-LABEL: fnmadd_s_contract: 1124; RV64I: # %bb.0: 1125; RV64I-NEXT: addi sp, sp, -48 1126; RV64I-NEXT: sd ra, 40(sp) # 8-byte Folded Spill 1127; RV64I-NEXT: sd s0, 32(sp) # 8-byte Folded Spill 1128; RV64I-NEXT: sd s1, 24(sp) # 8-byte Folded Spill 1129; RV64I-NEXT: sd s2, 16(sp) # 8-byte Folded Spill 1130; RV64I-NEXT: sd s3, 8(sp) # 8-byte Folded Spill 1131; RV64I-NEXT: mv s2, a2 1132; RV64I-NEXT: mv s1, a1 1133; RV64I-NEXT: li a1, 0 1134; RV64I-NEXT: call __addsf3@plt 1135; RV64I-NEXT: mv s3, a0 1136; RV64I-NEXT: mv a0, s1 1137; RV64I-NEXT: li a1, 0 1138; RV64I-NEXT: call __addsf3@plt 1139; RV64I-NEXT: mv s1, a0 1140; RV64I-NEXT: mv a0, s2 1141; RV64I-NEXT: li a1, 0 1142; RV64I-NEXT: call __addsf3@plt 1143; RV64I-NEXT: mv s0, a0 1144; RV64I-NEXT: mv a0, s3 1145; RV64I-NEXT: mv a1, s1 1146; RV64I-NEXT: call __mulsf3@plt 1147; RV64I-NEXT: lui a1, 524288 1148; RV64I-NEXT: xor a0, a0, a1 1149; RV64I-NEXT: mv a1, s0 1150; RV64I-NEXT: call __subsf3@plt 1151; RV64I-NEXT: ld ra, 40(sp) # 8-byte Folded Reload 1152; RV64I-NEXT: ld s0, 32(sp) # 8-byte Folded Reload 1153; RV64I-NEXT: ld s1, 24(sp) # 8-byte Folded Reload 1154; RV64I-NEXT: ld s2, 16(sp) # 8-byte Folded Reload 1155; RV64I-NEXT: ld s3, 8(sp) # 8-byte Folded Reload 1156; RV64I-NEXT: addi sp, sp, 48 1157; RV64I-NEXT: ret 1158 %a_ = fadd float 0.0, %a ; avoid negation using xor 1159 %b_ = fadd float 0.0, %b ; avoid negation using xor 1160 %c_ = fadd float 0.0, %c ; avoid negation using xor 1161 %1 = fmul contract float %a_, %b_ 1162 %2 = fneg float %1 1163 %3 = fsub contract float %2, %c_ 1164 ret float %3 1165} 1166 1167define float @fnmsub_s_contract(float %a, float %b, float %c) nounwind { 1168; RV32IF-LABEL: fnmsub_s_contract: 1169; RV32IF: # %bb.0: 1170; RV32IF-NEXT: fmv.w.x ft0, a2 1171; RV32IF-NEXT: fmv.w.x ft1, a1 1172; RV32IF-NEXT: fmv.w.x ft2, a0 1173; RV32IF-NEXT: fmv.w.x ft3, zero 1174; RV32IF-NEXT: fadd.s ft2, ft2, ft3 1175; RV32IF-NEXT: fadd.s ft1, ft1, ft3 1176; RV32IF-NEXT: fnmsub.s ft0, ft2, ft1, ft0 1177; RV32IF-NEXT: fmv.x.w a0, ft0 1178; RV32IF-NEXT: ret 1179; 1180; RV64IF-LABEL: fnmsub_s_contract: 1181; RV64IF: # %bb.0: 1182; RV64IF-NEXT: fmv.w.x ft0, a2 1183; RV64IF-NEXT: fmv.w.x ft1, a1 1184; RV64IF-NEXT: fmv.w.x ft2, a0 1185; RV64IF-NEXT: fmv.w.x ft3, zero 1186; RV64IF-NEXT: fadd.s ft2, ft2, ft3 1187; RV64IF-NEXT: fadd.s ft1, ft1, ft3 1188; RV64IF-NEXT: fnmsub.s ft0, ft2, ft1, ft0 1189; RV64IF-NEXT: fmv.x.w a0, ft0 1190; RV64IF-NEXT: ret 1191; 1192; RV32I-LABEL: fnmsub_s_contract: 1193; RV32I: # %bb.0: 1194; RV32I-NEXT: addi sp, sp, -16 1195; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 1196; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 1197; RV32I-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 1198; RV32I-NEXT: sw s2, 0(sp) # 4-byte Folded Spill 1199; RV32I-NEXT: mv s2, a2 1200; RV32I-NEXT: mv s1, a1 1201; RV32I-NEXT: li a1, 0 1202; RV32I-NEXT: call __addsf3@plt 1203; RV32I-NEXT: mv s0, a0 1204; RV32I-NEXT: mv a0, s1 1205; RV32I-NEXT: li a1, 0 1206; RV32I-NEXT: call __addsf3@plt 1207; RV32I-NEXT: mv a1, a0 1208; RV32I-NEXT: mv a0, s0 1209; RV32I-NEXT: call __mulsf3@plt 1210; RV32I-NEXT: mv a1, a0 1211; RV32I-NEXT: mv a0, s2 1212; RV32I-NEXT: call __subsf3@plt 1213; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 1214; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 1215; RV32I-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 1216; RV32I-NEXT: lw s2, 0(sp) # 4-byte Folded Reload 1217; RV32I-NEXT: addi sp, sp, 16 1218; RV32I-NEXT: ret 1219; 1220; RV64I-LABEL: fnmsub_s_contract: 1221; RV64I: # %bb.0: 1222; RV64I-NEXT: addi sp, sp, -32 1223; RV64I-NEXT: sd ra, 24(sp) # 8-byte Folded Spill 1224; RV64I-NEXT: sd s0, 16(sp) # 8-byte Folded Spill 1225; RV64I-NEXT: sd s1, 8(sp) # 8-byte Folded Spill 1226; RV64I-NEXT: sd s2, 0(sp) # 8-byte Folded Spill 1227; RV64I-NEXT: mv s2, a2 1228; RV64I-NEXT: mv s1, a1 1229; RV64I-NEXT: li a1, 0 1230; RV64I-NEXT: call __addsf3@plt 1231; RV64I-NEXT: mv s0, a0 1232; RV64I-NEXT: mv a0, s1 1233; RV64I-NEXT: li a1, 0 1234; RV64I-NEXT: call __addsf3@plt 1235; RV64I-NEXT: mv a1, a0 1236; RV64I-NEXT: mv a0, s0 1237; RV64I-NEXT: call __mulsf3@plt 1238; RV64I-NEXT: mv a1, a0 1239; RV64I-NEXT: mv a0, s2 1240; RV64I-NEXT: call __subsf3@plt 1241; RV64I-NEXT: ld ra, 24(sp) # 8-byte Folded Reload 1242; RV64I-NEXT: ld s0, 16(sp) # 8-byte Folded Reload 1243; RV64I-NEXT: ld s1, 8(sp) # 8-byte Folded Reload 1244; RV64I-NEXT: ld s2, 0(sp) # 8-byte Folded Reload 1245; RV64I-NEXT: addi sp, sp, 32 1246; RV64I-NEXT: ret 1247 %a_ = fadd float 0.0, %a ; avoid negation using xor 1248 %b_ = fadd float 0.0, %b ; avoid negation using xor 1249 %1 = fmul contract float %a_, %b_ 1250 %2 = fsub contract float %c, %1 1251 ret float %2 1252} 1253