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: | FileCheck -check-prefix=RV32IFD %s 4; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \ 5; RUN: | FileCheck -check-prefix=RV64IFD %s 6 7; These tests are each targeted at a particular RISC-V FPU instruction. Most 8; other files in this folder exercise LLVM IR instructions that don't directly 9; match a RISC-V instruction. 10 11define double @fadd_d(double %a, double %b) nounwind { 12; RV32IFD-LABEL: fadd_d: 13; RV32IFD: # %bb.0: 14; RV32IFD-NEXT: addi sp, sp, -16 15; RV32IFD-NEXT: sw a2, 8(sp) 16; RV32IFD-NEXT: sw a3, 12(sp) 17; RV32IFD-NEXT: fld ft0, 8(sp) 18; RV32IFD-NEXT: sw a0, 8(sp) 19; RV32IFD-NEXT: sw a1, 12(sp) 20; RV32IFD-NEXT: fld ft1, 8(sp) 21; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 22; RV32IFD-NEXT: fsd ft0, 8(sp) 23; RV32IFD-NEXT: lw a0, 8(sp) 24; RV32IFD-NEXT: lw a1, 12(sp) 25; RV32IFD-NEXT: addi sp, sp, 16 26; RV32IFD-NEXT: ret 27; 28; RV64IFD-LABEL: fadd_d: 29; RV64IFD: # %bb.0: 30; RV64IFD-NEXT: fmv.d.x ft0, a1 31; RV64IFD-NEXT: fmv.d.x ft1, a0 32; RV64IFD-NEXT: fadd.d ft0, ft1, ft0 33; RV64IFD-NEXT: fmv.x.d a0, ft0 34; RV64IFD-NEXT: ret 35 %1 = fadd double %a, %b 36 ret double %1 37} 38 39define double @fsub_d(double %a, double %b) nounwind { 40; RV32IFD-LABEL: fsub_d: 41; RV32IFD: # %bb.0: 42; RV32IFD-NEXT: addi sp, sp, -16 43; RV32IFD-NEXT: sw a2, 8(sp) 44; RV32IFD-NEXT: sw a3, 12(sp) 45; RV32IFD-NEXT: fld ft0, 8(sp) 46; RV32IFD-NEXT: sw a0, 8(sp) 47; RV32IFD-NEXT: sw a1, 12(sp) 48; RV32IFD-NEXT: fld ft1, 8(sp) 49; RV32IFD-NEXT: fsub.d ft0, ft1, ft0 50; RV32IFD-NEXT: fsd ft0, 8(sp) 51; RV32IFD-NEXT: lw a0, 8(sp) 52; RV32IFD-NEXT: lw a1, 12(sp) 53; RV32IFD-NEXT: addi sp, sp, 16 54; RV32IFD-NEXT: ret 55; 56; RV64IFD-LABEL: fsub_d: 57; RV64IFD: # %bb.0: 58; RV64IFD-NEXT: fmv.d.x ft0, a1 59; RV64IFD-NEXT: fmv.d.x ft1, a0 60; RV64IFD-NEXT: fsub.d ft0, ft1, ft0 61; RV64IFD-NEXT: fmv.x.d a0, ft0 62; RV64IFD-NEXT: ret 63 %1 = fsub double %a, %b 64 ret double %1 65} 66 67define double @fmul_d(double %a, double %b) nounwind { 68; RV32IFD-LABEL: fmul_d: 69; RV32IFD: # %bb.0: 70; RV32IFD-NEXT: addi sp, sp, -16 71; RV32IFD-NEXT: sw a2, 8(sp) 72; RV32IFD-NEXT: sw a3, 12(sp) 73; RV32IFD-NEXT: fld ft0, 8(sp) 74; RV32IFD-NEXT: sw a0, 8(sp) 75; RV32IFD-NEXT: sw a1, 12(sp) 76; RV32IFD-NEXT: fld ft1, 8(sp) 77; RV32IFD-NEXT: fmul.d ft0, ft1, ft0 78; RV32IFD-NEXT: fsd ft0, 8(sp) 79; RV32IFD-NEXT: lw a0, 8(sp) 80; RV32IFD-NEXT: lw a1, 12(sp) 81; RV32IFD-NEXT: addi sp, sp, 16 82; RV32IFD-NEXT: ret 83; 84; RV64IFD-LABEL: fmul_d: 85; RV64IFD: # %bb.0: 86; RV64IFD-NEXT: fmv.d.x ft0, a1 87; RV64IFD-NEXT: fmv.d.x ft1, a0 88; RV64IFD-NEXT: fmul.d ft0, ft1, ft0 89; RV64IFD-NEXT: fmv.x.d a0, ft0 90; RV64IFD-NEXT: ret 91 %1 = fmul double %a, %b 92 ret double %1 93} 94 95define double @fdiv_d(double %a, double %b) nounwind { 96; RV32IFD-LABEL: fdiv_d: 97; RV32IFD: # %bb.0: 98; RV32IFD-NEXT: addi sp, sp, -16 99; RV32IFD-NEXT: sw a2, 8(sp) 100; RV32IFD-NEXT: sw a3, 12(sp) 101; RV32IFD-NEXT: fld ft0, 8(sp) 102; RV32IFD-NEXT: sw a0, 8(sp) 103; RV32IFD-NEXT: sw a1, 12(sp) 104; RV32IFD-NEXT: fld ft1, 8(sp) 105; RV32IFD-NEXT: fdiv.d ft0, ft1, ft0 106; RV32IFD-NEXT: fsd ft0, 8(sp) 107; RV32IFD-NEXT: lw a0, 8(sp) 108; RV32IFD-NEXT: lw a1, 12(sp) 109; RV32IFD-NEXT: addi sp, sp, 16 110; RV32IFD-NEXT: ret 111; 112; RV64IFD-LABEL: fdiv_d: 113; RV64IFD: # %bb.0: 114; RV64IFD-NEXT: fmv.d.x ft0, a1 115; RV64IFD-NEXT: fmv.d.x ft1, a0 116; RV64IFD-NEXT: fdiv.d ft0, ft1, ft0 117; RV64IFD-NEXT: fmv.x.d a0, ft0 118; RV64IFD-NEXT: ret 119 %1 = fdiv double %a, %b 120 ret double %1 121} 122 123declare double @llvm.sqrt.f64(double) 124 125define double @fsqrt_d(double %a) nounwind { 126; RV32IFD-LABEL: fsqrt_d: 127; RV32IFD: # %bb.0: 128; RV32IFD-NEXT: addi sp, sp, -16 129; RV32IFD-NEXT: sw a0, 8(sp) 130; RV32IFD-NEXT: sw a1, 12(sp) 131; RV32IFD-NEXT: fld ft0, 8(sp) 132; RV32IFD-NEXT: fsqrt.d ft0, ft0 133; RV32IFD-NEXT: fsd ft0, 8(sp) 134; RV32IFD-NEXT: lw a0, 8(sp) 135; RV32IFD-NEXT: lw a1, 12(sp) 136; RV32IFD-NEXT: addi sp, sp, 16 137; RV32IFD-NEXT: ret 138; 139; RV64IFD-LABEL: fsqrt_d: 140; RV64IFD: # %bb.0: 141; RV64IFD-NEXT: fmv.d.x ft0, a0 142; RV64IFD-NEXT: fsqrt.d ft0, ft0 143; RV64IFD-NEXT: fmv.x.d a0, ft0 144; RV64IFD-NEXT: ret 145 %1 = call double @llvm.sqrt.f64(double %a) 146 ret double %1 147} 148 149declare double @llvm.copysign.f64(double, double) 150 151define double @fsgnj_d(double %a, double %b) nounwind { 152; RV32IFD-LABEL: fsgnj_d: 153; RV32IFD: # %bb.0: 154; RV32IFD-NEXT: addi sp, sp, -16 155; RV32IFD-NEXT: sw a2, 8(sp) 156; RV32IFD-NEXT: sw a3, 12(sp) 157; RV32IFD-NEXT: fld ft0, 8(sp) 158; RV32IFD-NEXT: sw a0, 8(sp) 159; RV32IFD-NEXT: sw a1, 12(sp) 160; RV32IFD-NEXT: fld ft1, 8(sp) 161; RV32IFD-NEXT: fsgnj.d ft0, ft1, ft0 162; RV32IFD-NEXT: fsd ft0, 8(sp) 163; RV32IFD-NEXT: lw a0, 8(sp) 164; RV32IFD-NEXT: lw a1, 12(sp) 165; RV32IFD-NEXT: addi sp, sp, 16 166; RV32IFD-NEXT: ret 167; 168; RV64IFD-LABEL: fsgnj_d: 169; RV64IFD: # %bb.0: 170; RV64IFD-NEXT: fmv.d.x ft0, a1 171; RV64IFD-NEXT: fmv.d.x ft1, a0 172; RV64IFD-NEXT: fsgnj.d ft0, ft1, ft0 173; RV64IFD-NEXT: fmv.x.d a0, ft0 174; RV64IFD-NEXT: ret 175 %1 = call double @llvm.copysign.f64(double %a, double %b) 176 ret double %1 177} 178 179; This function performs extra work to ensure that 180; DAGCombiner::visitBITCAST doesn't replace the fneg with an xor. 181define i32 @fneg_d(double %a, double %b) nounwind { 182; RV32IFD-LABEL: fneg_d: 183; RV32IFD: # %bb.0: 184; RV32IFD-NEXT: addi sp, sp, -16 185; RV32IFD-NEXT: sw a0, 8(sp) 186; RV32IFD-NEXT: sw a1, 12(sp) 187; RV32IFD-NEXT: fld ft0, 8(sp) 188; RV32IFD-NEXT: fadd.d ft0, ft0, ft0 189; RV32IFD-NEXT: fneg.d ft1, ft0 190; RV32IFD-NEXT: feq.d a0, ft0, ft1 191; RV32IFD-NEXT: addi sp, sp, 16 192; RV32IFD-NEXT: ret 193; 194; RV64IFD-LABEL: fneg_d: 195; RV64IFD: # %bb.0: 196; RV64IFD-NEXT: fmv.d.x ft0, a0 197; RV64IFD-NEXT: fadd.d ft0, ft0, ft0 198; RV64IFD-NEXT: fneg.d ft1, ft0 199; RV64IFD-NEXT: feq.d a0, ft0, ft1 200; RV64IFD-NEXT: ret 201 %1 = fadd double %a, %a 202 %2 = fneg double %1 203 %3 = fcmp oeq double %1, %2 204 %4 = zext i1 %3 to i32 205 ret i32 %4 206} 207 208define double @fsgnjn_d(double %a, double %b) nounwind { 209; TODO: fsgnjn.s isn't selected on RV64 because DAGCombiner::visitBITCAST will 210; convert (bitconvert (fneg x)) to a xor. 211; 212; RV32IFD-LABEL: fsgnjn_d: 213; RV32IFD: # %bb.0: 214; RV32IFD-NEXT: addi sp, sp, -16 215; RV32IFD-NEXT: sw a2, 8(sp) 216; RV32IFD-NEXT: sw a3, 12(sp) 217; RV32IFD-NEXT: fld ft0, 8(sp) 218; RV32IFD-NEXT: sw a0, 8(sp) 219; RV32IFD-NEXT: sw a1, 12(sp) 220; RV32IFD-NEXT: fld ft1, 8(sp) 221; RV32IFD-NEXT: fsgnjn.d ft0, ft1, ft0 222; RV32IFD-NEXT: fsd ft0, 8(sp) 223; RV32IFD-NEXT: lw a0, 8(sp) 224; RV32IFD-NEXT: lw a1, 12(sp) 225; RV32IFD-NEXT: addi sp, sp, 16 226; RV32IFD-NEXT: ret 227; 228; RV64IFD-LABEL: fsgnjn_d: 229; RV64IFD: # %bb.0: 230; RV64IFD-NEXT: addi a2, zero, -1 231; RV64IFD-NEXT: slli a2, a2, 63 232; RV64IFD-NEXT: xor a1, a1, a2 233; RV64IFD-NEXT: fmv.d.x ft0, a1 234; RV64IFD-NEXT: fmv.d.x ft1, a0 235; RV64IFD-NEXT: fsgnj.d ft0, ft1, ft0 236; RV64IFD-NEXT: fmv.x.d a0, ft0 237; RV64IFD-NEXT: ret 238 %1 = fsub double -0.0, %b 239 %2 = call double @llvm.copysign.f64(double %a, double %1) 240 ret double %2 241} 242 243declare double @llvm.fabs.f64(double) 244 245; This function performs extra work to ensure that 246; DAGCombiner::visitBITCAST doesn't replace the fabs with an and. 247define double @fabs_d(double %a, double %b) nounwind { 248; RV32IFD-LABEL: fabs_d: 249; RV32IFD: # %bb.0: 250; RV32IFD-NEXT: addi sp, sp, -16 251; RV32IFD-NEXT: sw a2, 8(sp) 252; RV32IFD-NEXT: sw a3, 12(sp) 253; RV32IFD-NEXT: fld ft0, 8(sp) 254; RV32IFD-NEXT: sw a0, 8(sp) 255; RV32IFD-NEXT: sw a1, 12(sp) 256; RV32IFD-NEXT: fld ft1, 8(sp) 257; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 258; RV32IFD-NEXT: fabs.d ft1, ft0 259; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 260; RV32IFD-NEXT: fsd ft0, 8(sp) 261; RV32IFD-NEXT: lw a0, 8(sp) 262; RV32IFD-NEXT: lw a1, 12(sp) 263; RV32IFD-NEXT: addi sp, sp, 16 264; RV32IFD-NEXT: ret 265; 266; RV64IFD-LABEL: fabs_d: 267; RV64IFD: # %bb.0: 268; RV64IFD-NEXT: fmv.d.x ft0, a1 269; RV64IFD-NEXT: fmv.d.x ft1, a0 270; RV64IFD-NEXT: fadd.d ft0, ft1, ft0 271; RV64IFD-NEXT: fabs.d ft1, ft0 272; RV64IFD-NEXT: fadd.d ft0, ft1, ft0 273; RV64IFD-NEXT: fmv.x.d a0, ft0 274; RV64IFD-NEXT: ret 275 %1 = fadd double %a, %b 276 %2 = call double @llvm.fabs.f64(double %1) 277 %3 = fadd double %2, %1 278 ret double %3 279} 280 281declare double @llvm.minnum.f64(double, double) 282 283define double @fmin_d(double %a, double %b) nounwind { 284; RV32IFD-LABEL: fmin_d: 285; RV32IFD: # %bb.0: 286; RV32IFD-NEXT: addi sp, sp, -16 287; RV32IFD-NEXT: sw a2, 8(sp) 288; RV32IFD-NEXT: sw a3, 12(sp) 289; RV32IFD-NEXT: fld ft0, 8(sp) 290; RV32IFD-NEXT: sw a0, 8(sp) 291; RV32IFD-NEXT: sw a1, 12(sp) 292; RV32IFD-NEXT: fld ft1, 8(sp) 293; RV32IFD-NEXT: fmin.d ft0, ft1, ft0 294; RV32IFD-NEXT: fsd ft0, 8(sp) 295; RV32IFD-NEXT: lw a0, 8(sp) 296; RV32IFD-NEXT: lw a1, 12(sp) 297; RV32IFD-NEXT: addi sp, sp, 16 298; RV32IFD-NEXT: ret 299; 300; RV64IFD-LABEL: fmin_d: 301; RV64IFD: # %bb.0: 302; RV64IFD-NEXT: fmv.d.x ft0, a1 303; RV64IFD-NEXT: fmv.d.x ft1, a0 304; RV64IFD-NEXT: fmin.d ft0, ft1, ft0 305; RV64IFD-NEXT: fmv.x.d a0, ft0 306; RV64IFD-NEXT: ret 307 %1 = call double @llvm.minnum.f64(double %a, double %b) 308 ret double %1 309} 310 311declare double @llvm.maxnum.f64(double, double) 312 313define double @fmax_d(double %a, double %b) nounwind { 314; RV32IFD-LABEL: fmax_d: 315; RV32IFD: # %bb.0: 316; RV32IFD-NEXT: addi sp, sp, -16 317; RV32IFD-NEXT: sw a2, 8(sp) 318; RV32IFD-NEXT: sw a3, 12(sp) 319; RV32IFD-NEXT: fld ft0, 8(sp) 320; RV32IFD-NEXT: sw a0, 8(sp) 321; RV32IFD-NEXT: sw a1, 12(sp) 322; RV32IFD-NEXT: fld ft1, 8(sp) 323; RV32IFD-NEXT: fmax.d ft0, ft1, ft0 324; RV32IFD-NEXT: fsd ft0, 8(sp) 325; RV32IFD-NEXT: lw a0, 8(sp) 326; RV32IFD-NEXT: lw a1, 12(sp) 327; RV32IFD-NEXT: addi sp, sp, 16 328; RV32IFD-NEXT: ret 329; 330; RV64IFD-LABEL: fmax_d: 331; RV64IFD: # %bb.0: 332; RV64IFD-NEXT: fmv.d.x ft0, a1 333; RV64IFD-NEXT: fmv.d.x ft1, a0 334; RV64IFD-NEXT: fmax.d ft0, ft1, ft0 335; RV64IFD-NEXT: fmv.x.d a0, ft0 336; RV64IFD-NEXT: ret 337 %1 = call double @llvm.maxnum.f64(double %a, double %b) 338 ret double %1 339} 340 341define i32 @feq_d(double %a, double %b) nounwind { 342; RV32IFD-LABEL: feq_d: 343; RV32IFD: # %bb.0: 344; RV32IFD-NEXT: addi sp, sp, -16 345; RV32IFD-NEXT: sw a2, 8(sp) 346; RV32IFD-NEXT: sw a3, 12(sp) 347; RV32IFD-NEXT: fld ft0, 8(sp) 348; RV32IFD-NEXT: sw a0, 8(sp) 349; RV32IFD-NEXT: sw a1, 12(sp) 350; RV32IFD-NEXT: fld ft1, 8(sp) 351; RV32IFD-NEXT: feq.d a0, ft1, ft0 352; RV32IFD-NEXT: addi sp, sp, 16 353; RV32IFD-NEXT: ret 354; 355; RV64IFD-LABEL: feq_d: 356; RV64IFD: # %bb.0: 357; RV64IFD-NEXT: fmv.d.x ft0, a1 358; RV64IFD-NEXT: fmv.d.x ft1, a0 359; RV64IFD-NEXT: feq.d a0, ft1, ft0 360; RV64IFD-NEXT: ret 361 %1 = fcmp oeq double %a, %b 362 %2 = zext i1 %1 to i32 363 ret i32 %2 364} 365 366define i32 @flt_d(double %a, double %b) nounwind { 367; RV32IFD-LABEL: flt_d: 368; RV32IFD: # %bb.0: 369; RV32IFD-NEXT: addi sp, sp, -16 370; RV32IFD-NEXT: sw a2, 8(sp) 371; RV32IFD-NEXT: sw a3, 12(sp) 372; RV32IFD-NEXT: fld ft0, 8(sp) 373; RV32IFD-NEXT: sw a0, 8(sp) 374; RV32IFD-NEXT: sw a1, 12(sp) 375; RV32IFD-NEXT: fld ft1, 8(sp) 376; RV32IFD-NEXT: flt.d a0, ft1, ft0 377; RV32IFD-NEXT: addi sp, sp, 16 378; RV32IFD-NEXT: ret 379; 380; RV64IFD-LABEL: flt_d: 381; RV64IFD: # %bb.0: 382; RV64IFD-NEXT: fmv.d.x ft0, a1 383; RV64IFD-NEXT: fmv.d.x ft1, a0 384; RV64IFD-NEXT: flt.d a0, ft1, ft0 385; RV64IFD-NEXT: ret 386 %1 = fcmp olt double %a, %b 387 %2 = zext i1 %1 to i32 388 ret i32 %2 389} 390 391define i32 @fle_d(double %a, double %b) nounwind { 392; RV32IFD-LABEL: fle_d: 393; RV32IFD: # %bb.0: 394; RV32IFD-NEXT: addi sp, sp, -16 395; RV32IFD-NEXT: sw a2, 8(sp) 396; RV32IFD-NEXT: sw a3, 12(sp) 397; RV32IFD-NEXT: fld ft0, 8(sp) 398; RV32IFD-NEXT: sw a0, 8(sp) 399; RV32IFD-NEXT: sw a1, 12(sp) 400; RV32IFD-NEXT: fld ft1, 8(sp) 401; RV32IFD-NEXT: fle.d a0, ft1, ft0 402; RV32IFD-NEXT: addi sp, sp, 16 403; RV32IFD-NEXT: ret 404; 405; RV64IFD-LABEL: fle_d: 406; RV64IFD: # %bb.0: 407; RV64IFD-NEXT: fmv.d.x ft0, a1 408; RV64IFD-NEXT: fmv.d.x ft1, a0 409; RV64IFD-NEXT: fle.d a0, ft1, ft0 410; RV64IFD-NEXT: ret 411 %1 = fcmp ole double %a, %b 412 %2 = zext i1 %1 to i32 413 ret i32 %2 414} 415 416declare double @llvm.fma.f64(double, double, double) 417 418define double @fmadd_d(double %a, double %b, double %c) nounwind { 419; RV32IFD-LABEL: fmadd_d: 420; RV32IFD: # %bb.0: 421; RV32IFD-NEXT: addi sp, sp, -16 422; RV32IFD-NEXT: sw a4, 8(sp) 423; RV32IFD-NEXT: sw a5, 12(sp) 424; RV32IFD-NEXT: fld ft0, 8(sp) 425; RV32IFD-NEXT: sw a2, 8(sp) 426; RV32IFD-NEXT: sw a3, 12(sp) 427; RV32IFD-NEXT: fld ft1, 8(sp) 428; RV32IFD-NEXT: sw a0, 8(sp) 429; RV32IFD-NEXT: sw a1, 12(sp) 430; RV32IFD-NEXT: fld ft2, 8(sp) 431; RV32IFD-NEXT: fmadd.d ft0, ft2, ft1, ft0 432; RV32IFD-NEXT: fsd ft0, 8(sp) 433; RV32IFD-NEXT: lw a0, 8(sp) 434; RV32IFD-NEXT: lw a1, 12(sp) 435; RV32IFD-NEXT: addi sp, sp, 16 436; RV32IFD-NEXT: ret 437; 438; RV64IFD-LABEL: fmadd_d: 439; RV64IFD: # %bb.0: 440; RV64IFD-NEXT: fmv.d.x ft0, a2 441; RV64IFD-NEXT: fmv.d.x ft1, a1 442; RV64IFD-NEXT: fmv.d.x ft2, a0 443; RV64IFD-NEXT: fmadd.d ft0, ft2, ft1, ft0 444; RV64IFD-NEXT: fmv.x.d a0, ft0 445; RV64IFD-NEXT: ret 446 %1 = call double @llvm.fma.f64(double %a, double %b, double %c) 447 ret double %1 448} 449 450define double @fmsub_d(double %a, double %b, double %c) nounwind { 451; RV32IFD-LABEL: fmsub_d: 452; RV32IFD: # %bb.0: 453; RV32IFD-NEXT: addi sp, sp, -16 454; RV32IFD-NEXT: sw a2, 8(sp) 455; RV32IFD-NEXT: sw a3, 12(sp) 456; RV32IFD-NEXT: fld ft0, 8(sp) 457; RV32IFD-NEXT: sw a0, 8(sp) 458; RV32IFD-NEXT: sw a1, 12(sp) 459; RV32IFD-NEXT: fld ft1, 8(sp) 460; RV32IFD-NEXT: sw a4, 8(sp) 461; RV32IFD-NEXT: sw a5, 12(sp) 462; RV32IFD-NEXT: fld ft2, 8(sp) 463; RV32IFD-NEXT: lui a0, %hi(.LCPI15_0) 464; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI15_0) 465; RV32IFD-NEXT: fld ft3, 0(a0) 466; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 467; RV32IFD-NEXT: fmsub.d ft0, ft1, ft0, ft2 468; RV32IFD-NEXT: fsd ft0, 8(sp) 469; RV32IFD-NEXT: lw a0, 8(sp) 470; RV32IFD-NEXT: lw a1, 12(sp) 471; RV32IFD-NEXT: addi sp, sp, 16 472; RV32IFD-NEXT: ret 473; 474; RV64IFD-LABEL: fmsub_d: 475; RV64IFD: # %bb.0: 476; RV64IFD-NEXT: fmv.d.x ft0, a2 477; RV64IFD-NEXT: lui a2, %hi(.LCPI15_0) 478; RV64IFD-NEXT: addi a2, a2, %lo(.LCPI15_0) 479; RV64IFD-NEXT: fld ft1, 0(a2) 480; RV64IFD-NEXT: fadd.d ft0, ft0, ft1 481; RV64IFD-NEXT: fmv.d.x ft1, a1 482; RV64IFD-NEXT: fmv.d.x ft2, a0 483; RV64IFD-NEXT: fmsub.d ft0, ft2, ft1, ft0 484; RV64IFD-NEXT: fmv.x.d a0, ft0 485; RV64IFD-NEXT: ret 486 %c_ = fadd double 0.0, %c ; avoid negation using xor 487 %negc = fsub double -0.0, %c_ 488 %1 = call double @llvm.fma.f64(double %a, double %b, double %negc) 489 ret double %1 490} 491 492define double @fnmadd_d(double %a, double %b, double %c) nounwind { 493; RV32IFD-LABEL: fnmadd_d: 494; RV32IFD: # %bb.0: 495; RV32IFD-NEXT: addi sp, sp, -16 496; RV32IFD-NEXT: sw a2, 8(sp) 497; RV32IFD-NEXT: sw a3, 12(sp) 498; RV32IFD-NEXT: fld ft0, 8(sp) 499; RV32IFD-NEXT: sw a0, 8(sp) 500; RV32IFD-NEXT: sw a1, 12(sp) 501; RV32IFD-NEXT: fld ft1, 8(sp) 502; RV32IFD-NEXT: sw a4, 8(sp) 503; RV32IFD-NEXT: sw a5, 12(sp) 504; RV32IFD-NEXT: fld ft2, 8(sp) 505; RV32IFD-NEXT: lui a0, %hi(.LCPI16_0) 506; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI16_0) 507; RV32IFD-NEXT: fld ft3, 0(a0) 508; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 509; RV32IFD-NEXT: fadd.d ft1, ft1, ft3 510; RV32IFD-NEXT: fnmadd.d ft0, ft1, ft0, ft2 511; RV32IFD-NEXT: fsd ft0, 8(sp) 512; RV32IFD-NEXT: lw a0, 8(sp) 513; RV32IFD-NEXT: lw a1, 12(sp) 514; RV32IFD-NEXT: addi sp, sp, 16 515; RV32IFD-NEXT: ret 516; 517; RV64IFD-LABEL: fnmadd_d: 518; RV64IFD: # %bb.0: 519; RV64IFD-NEXT: fmv.d.x ft0, a2 520; RV64IFD-NEXT: lui a2, %hi(.LCPI16_0) 521; RV64IFD-NEXT: addi a2, a2, %lo(.LCPI16_0) 522; RV64IFD-NEXT: fld ft1, 0(a2) 523; RV64IFD-NEXT: fadd.d ft0, ft0, ft1 524; RV64IFD-NEXT: fmv.d.x ft2, a0 525; RV64IFD-NEXT: fadd.d ft1, ft2, ft1 526; RV64IFD-NEXT: fmv.d.x ft2, a1 527; RV64IFD-NEXT: fnmadd.d ft0, ft1, ft2, ft0 528; RV64IFD-NEXT: fmv.x.d a0, ft0 529; RV64IFD-NEXT: ret 530 %a_ = fadd double 0.0, %a 531 %c_ = fadd double 0.0, %c 532 %nega = fsub double -0.0, %a_ 533 %negc = fsub double -0.0, %c_ 534 %1 = call double @llvm.fma.f64(double %nega, double %b, double %negc) 535 ret double %1 536} 537 538define double @fnmsub_d(double %a, double %b, double %c) nounwind { 539; RV32IFD-LABEL: fnmsub_d: 540; RV32IFD: # %bb.0: 541; RV32IFD-NEXT: addi sp, sp, -16 542; RV32IFD-NEXT: sw a4, 8(sp) 543; RV32IFD-NEXT: sw a5, 12(sp) 544; RV32IFD-NEXT: fld ft0, 8(sp) 545; RV32IFD-NEXT: sw a2, 8(sp) 546; RV32IFD-NEXT: sw a3, 12(sp) 547; RV32IFD-NEXT: fld ft1, 8(sp) 548; RV32IFD-NEXT: sw a0, 8(sp) 549; RV32IFD-NEXT: sw a1, 12(sp) 550; RV32IFD-NEXT: fld ft2, 8(sp) 551; RV32IFD-NEXT: lui a0, %hi(.LCPI17_0) 552; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI17_0) 553; RV32IFD-NEXT: fld ft3, 0(a0) 554; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 555; RV32IFD-NEXT: fnmsub.d ft0, ft2, ft1, ft0 556; RV32IFD-NEXT: fsd ft0, 8(sp) 557; RV32IFD-NEXT: lw a0, 8(sp) 558; RV32IFD-NEXT: lw a1, 12(sp) 559; RV32IFD-NEXT: addi sp, sp, 16 560; RV32IFD-NEXT: ret 561; 562; RV64IFD-LABEL: fnmsub_d: 563; RV64IFD: # %bb.0: 564; RV64IFD-NEXT: fmv.d.x ft0, a0 565; RV64IFD-NEXT: lui a0, %hi(.LCPI17_0) 566; RV64IFD-NEXT: addi a0, a0, %lo(.LCPI17_0) 567; RV64IFD-NEXT: fld ft1, 0(a0) 568; RV64IFD-NEXT: fadd.d ft0, ft0, ft1 569; RV64IFD-NEXT: fmv.d.x ft1, a2 570; RV64IFD-NEXT: fmv.d.x ft2, a1 571; RV64IFD-NEXT: fnmsub.d ft0, ft0, ft2, ft1 572; RV64IFD-NEXT: fmv.x.d a0, ft0 573; RV64IFD-NEXT: ret 574 %a_ = fadd double 0.0, %a 575 %nega = fsub double -0.0, %a_ 576 %1 = call double @llvm.fma.f64(double %nega, double %b, double %c) 577 ret double %1 578} 579