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