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