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