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: fcvt.d.w ft3, zero 464; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 465; RV32IFD-NEXT: fmsub.d ft0, ft1, ft0, ft2 466; RV32IFD-NEXT: fsd ft0, 8(sp) 467; RV32IFD-NEXT: lw a0, 8(sp) 468; RV32IFD-NEXT: lw a1, 12(sp) 469; RV32IFD-NEXT: addi sp, sp, 16 470; RV32IFD-NEXT: ret 471; 472; RV64IFD-LABEL: fmsub_d: 473; RV64IFD: # %bb.0: 474; RV64IFD-NEXT: fmv.d.x ft0, a1 475; RV64IFD-NEXT: fmv.d.x ft1, a0 476; RV64IFD-NEXT: fmv.d.x ft2, a2 477; RV64IFD-NEXT: fmv.d.x ft3, zero 478; RV64IFD-NEXT: fadd.d ft2, ft2, ft3 479; RV64IFD-NEXT: fmsub.d ft0, ft1, ft0, ft2 480; RV64IFD-NEXT: fmv.x.d a0, ft0 481; RV64IFD-NEXT: ret 482 %c_ = fadd double 0.0, %c ; avoid negation using xor 483 %negc = fsub double -0.0, %c_ 484 %1 = call double @llvm.fma.f64(double %a, double %b, double %negc) 485 ret double %1 486} 487 488define double @fnmadd_d(double %a, double %b, double %c) nounwind { 489; RV32IFD-LABEL: fnmadd_d: 490; RV32IFD: # %bb.0: 491; RV32IFD-NEXT: addi sp, sp, -16 492; RV32IFD-NEXT: sw a2, 8(sp) 493; RV32IFD-NEXT: sw a3, 12(sp) 494; RV32IFD-NEXT: fld ft0, 8(sp) 495; RV32IFD-NEXT: sw a4, 8(sp) 496; RV32IFD-NEXT: sw a5, 12(sp) 497; RV32IFD-NEXT: fld ft1, 8(sp) 498; RV32IFD-NEXT: sw a0, 8(sp) 499; RV32IFD-NEXT: sw a1, 12(sp) 500; RV32IFD-NEXT: fld ft2, 8(sp) 501; RV32IFD-NEXT: fcvt.d.w ft3, zero 502; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 503; RV32IFD-NEXT: fadd.d ft1, ft1, ft3 504; RV32IFD-NEXT: fnmadd.d ft0, ft2, ft0, ft1 505; RV32IFD-NEXT: fsd ft0, 8(sp) 506; RV32IFD-NEXT: lw a0, 8(sp) 507; RV32IFD-NEXT: lw a1, 12(sp) 508; RV32IFD-NEXT: addi sp, sp, 16 509; RV32IFD-NEXT: ret 510; 511; RV64IFD-LABEL: fnmadd_d: 512; RV64IFD: # %bb.0: 513; RV64IFD-NEXT: fmv.d.x ft0, a1 514; RV64IFD-NEXT: fmv.d.x ft1, a2 515; RV64IFD-NEXT: fmv.d.x ft2, a0 516; RV64IFD-NEXT: fmv.d.x ft3, zero 517; RV64IFD-NEXT: fadd.d ft2, ft2, ft3 518; RV64IFD-NEXT: fadd.d ft1, ft1, ft3 519; RV64IFD-NEXT: fnmadd.d ft0, ft2, ft0, ft1 520; RV64IFD-NEXT: fmv.x.d a0, ft0 521; RV64IFD-NEXT: ret 522 %a_ = fadd double 0.0, %a 523 %c_ = fadd double 0.0, %c 524 %nega = fsub double -0.0, %a_ 525 %negc = fsub double -0.0, %c_ 526 %1 = call double @llvm.fma.f64(double %nega, double %b, double %negc) 527 ret double %1 528} 529 530define double @fnmadd_d_2(double %a, double %b, double %c) nounwind { 531; RV32IFD-LABEL: fnmadd_d_2: 532; RV32IFD: # %bb.0: 533; RV32IFD-NEXT: addi sp, sp, -16 534; RV32IFD-NEXT: sw a0, 8(sp) 535; RV32IFD-NEXT: sw a1, 12(sp) 536; RV32IFD-NEXT: fld ft0, 8(sp) 537; RV32IFD-NEXT: sw a4, 8(sp) 538; RV32IFD-NEXT: sw a5, 12(sp) 539; RV32IFD-NEXT: fld ft1, 8(sp) 540; RV32IFD-NEXT: sw a2, 8(sp) 541; RV32IFD-NEXT: sw a3, 12(sp) 542; RV32IFD-NEXT: fld ft2, 8(sp) 543; RV32IFD-NEXT: fcvt.d.w ft3, zero 544; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 545; RV32IFD-NEXT: fadd.d ft1, ft1, ft3 546; RV32IFD-NEXT: fnmadd.d ft0, ft2, ft0, ft1 547; RV32IFD-NEXT: fsd ft0, 8(sp) 548; RV32IFD-NEXT: lw a0, 8(sp) 549; RV32IFD-NEXT: lw a1, 12(sp) 550; RV32IFD-NEXT: addi sp, sp, 16 551; RV32IFD-NEXT: ret 552; 553; RV64IFD-LABEL: fnmadd_d_2: 554; RV64IFD: # %bb.0: 555; RV64IFD-NEXT: fmv.d.x ft0, a0 556; RV64IFD-NEXT: fmv.d.x ft1, a2 557; RV64IFD-NEXT: fmv.d.x ft2, a1 558; RV64IFD-NEXT: fmv.d.x ft3, zero 559; RV64IFD-NEXT: fadd.d ft2, ft2, ft3 560; RV64IFD-NEXT: fadd.d ft1, ft1, ft3 561; RV64IFD-NEXT: fnmadd.d ft0, ft2, ft0, ft1 562; RV64IFD-NEXT: fmv.x.d a0, ft0 563; RV64IFD-NEXT: ret 564 %b_ = fadd double 0.0, %b 565 %c_ = fadd double 0.0, %c 566 %negb = fsub double -0.0, %b_ 567 %negc = fsub double -0.0, %c_ 568 %1 = call double @llvm.fma.f64(double %a, double %negb, double %negc) 569 ret double %1 570} 571 572define double @fnmsub_d(double %a, double %b, double %c) nounwind { 573; RV32IFD-LABEL: fnmsub_d: 574; RV32IFD: # %bb.0: 575; RV32IFD-NEXT: addi sp, sp, -16 576; RV32IFD-NEXT: sw a4, 8(sp) 577; RV32IFD-NEXT: sw a5, 12(sp) 578; RV32IFD-NEXT: fld ft0, 8(sp) 579; RV32IFD-NEXT: sw a2, 8(sp) 580; RV32IFD-NEXT: sw a3, 12(sp) 581; RV32IFD-NEXT: fld ft1, 8(sp) 582; RV32IFD-NEXT: sw a0, 8(sp) 583; RV32IFD-NEXT: sw a1, 12(sp) 584; RV32IFD-NEXT: fld ft2, 8(sp) 585; RV32IFD-NEXT: fcvt.d.w ft3, zero 586; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 587; RV32IFD-NEXT: fnmsub.d ft0, ft2, ft1, ft0 588; RV32IFD-NEXT: fsd ft0, 8(sp) 589; RV32IFD-NEXT: lw a0, 8(sp) 590; RV32IFD-NEXT: lw a1, 12(sp) 591; RV32IFD-NEXT: addi sp, sp, 16 592; RV32IFD-NEXT: ret 593; 594; RV64IFD-LABEL: fnmsub_d: 595; RV64IFD: # %bb.0: 596; RV64IFD-NEXT: fmv.d.x ft0, a2 597; RV64IFD-NEXT: fmv.d.x ft1, a1 598; RV64IFD-NEXT: fmv.d.x ft2, a0 599; RV64IFD-NEXT: fmv.d.x ft3, zero 600; RV64IFD-NEXT: fadd.d ft2, ft2, ft3 601; RV64IFD-NEXT: fnmsub.d ft0, ft2, ft1, ft0 602; RV64IFD-NEXT: fmv.x.d a0, ft0 603; RV64IFD-NEXT: ret 604 %a_ = fadd double 0.0, %a 605 %nega = fsub double -0.0, %a_ 606 %1 = call double @llvm.fma.f64(double %nega, double %b, double %c) 607 ret double %1 608} 609 610define double @fnmsub_d_2(double %a, double %b, double %c) nounwind { 611; RV32IFD-LABEL: fnmsub_d_2: 612; RV32IFD: # %bb.0: 613; RV32IFD-NEXT: addi sp, sp, -16 614; RV32IFD-NEXT: sw a4, 8(sp) 615; RV32IFD-NEXT: sw a5, 12(sp) 616; RV32IFD-NEXT: fld ft0, 8(sp) 617; RV32IFD-NEXT: sw a0, 8(sp) 618; RV32IFD-NEXT: sw a1, 12(sp) 619; RV32IFD-NEXT: fld ft1, 8(sp) 620; RV32IFD-NEXT: sw a2, 8(sp) 621; RV32IFD-NEXT: sw a3, 12(sp) 622; RV32IFD-NEXT: fld ft2, 8(sp) 623; RV32IFD-NEXT: fcvt.d.w ft3, zero 624; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 625; RV32IFD-NEXT: fnmsub.d ft0, ft2, ft1, ft0 626; RV32IFD-NEXT: fsd ft0, 8(sp) 627; RV32IFD-NEXT: lw a0, 8(sp) 628; RV32IFD-NEXT: lw a1, 12(sp) 629; RV32IFD-NEXT: addi sp, sp, 16 630; RV32IFD-NEXT: ret 631; 632; RV64IFD-LABEL: fnmsub_d_2: 633; RV64IFD: # %bb.0: 634; RV64IFD-NEXT: fmv.d.x ft0, a2 635; RV64IFD-NEXT: fmv.d.x ft1, a0 636; RV64IFD-NEXT: fmv.d.x ft2, a1 637; RV64IFD-NEXT: fmv.d.x ft3, zero 638; RV64IFD-NEXT: fadd.d ft2, ft2, ft3 639; RV64IFD-NEXT: fnmsub.d ft0, ft2, ft1, ft0 640; RV64IFD-NEXT: fmv.x.d a0, ft0 641; RV64IFD-NEXT: ret 642 %b_ = fadd double 0.0, %b 643 %negb = fsub double -0.0, %b_ 644 %1 = call double @llvm.fma.f64(double %a, double %negb, double %c) 645 ret double %1 646} 647 648define double @fmadd_d_contract(double %a, double %b, double %c) nounwind { 649; RV32IFD-LABEL: fmadd_d_contract: 650; RV32IFD: # %bb.0: 651; RV32IFD-NEXT: addi sp, sp, -16 652; RV32IFD-NEXT: sw a4, 8(sp) 653; RV32IFD-NEXT: sw a5, 12(sp) 654; RV32IFD-NEXT: fld ft0, 8(sp) 655; RV32IFD-NEXT: sw a2, 8(sp) 656; RV32IFD-NEXT: sw a3, 12(sp) 657; RV32IFD-NEXT: fld ft1, 8(sp) 658; RV32IFD-NEXT: sw a0, 8(sp) 659; RV32IFD-NEXT: sw a1, 12(sp) 660; RV32IFD-NEXT: fld ft2, 8(sp) 661; RV32IFD-NEXT: fmadd.d ft0, ft2, ft1, ft0 662; RV32IFD-NEXT: fsd ft0, 8(sp) 663; RV32IFD-NEXT: lw a0, 8(sp) 664; RV32IFD-NEXT: lw a1, 12(sp) 665; RV32IFD-NEXT: addi sp, sp, 16 666; RV32IFD-NEXT: ret 667; 668; RV64IFD-LABEL: fmadd_d_contract: 669; RV64IFD: # %bb.0: 670; RV64IFD-NEXT: fmv.d.x ft0, a2 671; RV64IFD-NEXT: fmv.d.x ft1, a1 672; RV64IFD-NEXT: fmv.d.x ft2, a0 673; RV64IFD-NEXT: fmadd.d ft0, ft2, ft1, ft0 674; RV64IFD-NEXT: fmv.x.d a0, ft0 675; RV64IFD-NEXT: ret 676 %1 = fmul contract double %a, %b 677 %2 = fadd contract double %1, %c 678 ret double %2 679} 680 681define double @fmsub_d_contract(double %a, double %b, double %c) nounwind { 682; RV32IFD-LABEL: fmsub_d_contract: 683; RV32IFD: # %bb.0: 684; RV32IFD-NEXT: addi sp, sp, -16 685; RV32IFD-NEXT: sw a2, 8(sp) 686; RV32IFD-NEXT: sw a3, 12(sp) 687; RV32IFD-NEXT: fld ft0, 8(sp) 688; RV32IFD-NEXT: sw a0, 8(sp) 689; RV32IFD-NEXT: sw a1, 12(sp) 690; RV32IFD-NEXT: fld ft1, 8(sp) 691; RV32IFD-NEXT: sw a4, 8(sp) 692; RV32IFD-NEXT: sw a5, 12(sp) 693; RV32IFD-NEXT: fld ft2, 8(sp) 694; RV32IFD-NEXT: fcvt.d.w ft3, zero 695; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 696; RV32IFD-NEXT: fmsub.d ft0, ft1, ft0, ft2 697; RV32IFD-NEXT: fsd ft0, 8(sp) 698; RV32IFD-NEXT: lw a0, 8(sp) 699; RV32IFD-NEXT: lw a1, 12(sp) 700; RV32IFD-NEXT: addi sp, sp, 16 701; RV32IFD-NEXT: ret 702; 703; RV64IFD-LABEL: fmsub_d_contract: 704; RV64IFD: # %bb.0: 705; RV64IFD-NEXT: fmv.d.x ft0, a1 706; RV64IFD-NEXT: fmv.d.x ft1, a0 707; RV64IFD-NEXT: fmv.d.x ft2, a2 708; RV64IFD-NEXT: fmv.d.x ft3, zero 709; RV64IFD-NEXT: fadd.d ft2, ft2, ft3 710; RV64IFD-NEXT: fmsub.d ft0, ft1, ft0, ft2 711; RV64IFD-NEXT: fmv.x.d a0, ft0 712; RV64IFD-NEXT: ret 713 %c_ = fadd double 0.0, %c ; avoid negation using xor 714 %1 = fmul contract double %a, %b 715 %2 = fsub contract double %1, %c_ 716 ret double %2 717} 718 719define double @fnmadd_d_contract(double %a, double %b, double %c) nounwind { 720; RV32IFD-LABEL: fnmadd_d_contract: 721; RV32IFD: # %bb.0: 722; RV32IFD-NEXT: addi sp, sp, -16 723; RV32IFD-NEXT: sw a4, 8(sp) 724; RV32IFD-NEXT: sw a5, 12(sp) 725; RV32IFD-NEXT: fld ft0, 8(sp) 726; RV32IFD-NEXT: sw a2, 8(sp) 727; RV32IFD-NEXT: sw a3, 12(sp) 728; RV32IFD-NEXT: fld ft1, 8(sp) 729; RV32IFD-NEXT: sw a0, 8(sp) 730; RV32IFD-NEXT: sw a1, 12(sp) 731; RV32IFD-NEXT: fld ft2, 8(sp) 732; RV32IFD-NEXT: fcvt.d.w ft3, zero 733; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 734; RV32IFD-NEXT: fadd.d ft1, ft1, ft3 735; RV32IFD-NEXT: fadd.d ft0, ft0, ft3 736; RV32IFD-NEXT: fnmadd.d ft0, ft2, ft1, ft0 737; RV32IFD-NEXT: fsd ft0, 8(sp) 738; RV32IFD-NEXT: lw a0, 8(sp) 739; RV32IFD-NEXT: lw a1, 12(sp) 740; RV32IFD-NEXT: addi sp, sp, 16 741; RV32IFD-NEXT: ret 742; 743; RV64IFD-LABEL: fnmadd_d_contract: 744; RV64IFD: # %bb.0: 745; RV64IFD-NEXT: fmv.d.x ft0, a2 746; RV64IFD-NEXT: fmv.d.x ft1, a1 747; RV64IFD-NEXT: fmv.d.x ft2, a0 748; RV64IFD-NEXT: fmv.d.x ft3, zero 749; RV64IFD-NEXT: fadd.d ft2, ft2, ft3 750; RV64IFD-NEXT: fadd.d ft1, ft1, ft3 751; RV64IFD-NEXT: fadd.d ft0, ft0, ft3 752; RV64IFD-NEXT: fnmadd.d ft0, ft2, ft1, ft0 753; RV64IFD-NEXT: fmv.x.d a0, ft0 754; RV64IFD-NEXT: ret 755 %a_ = fadd double 0.0, %a ; avoid negation using xor 756 %b_ = fadd double 0.0, %b ; avoid negation using xor 757 %c_ = fadd double 0.0, %c ; avoid negation using xor 758 %1 = fmul contract double %a_, %b_ 759 %2 = fneg double %1 760 %3 = fsub contract double %2, %c_ 761 ret double %3 762} 763 764define double @fnmsub_d_contract(double %a, double %b, double %c) nounwind { 765; RV32IFD-LABEL: fnmsub_d_contract: 766; RV32IFD: # %bb.0: 767; RV32IFD-NEXT: addi sp, sp, -16 768; RV32IFD-NEXT: sw a4, 8(sp) 769; RV32IFD-NEXT: sw a5, 12(sp) 770; RV32IFD-NEXT: fld ft0, 8(sp) 771; RV32IFD-NEXT: sw a2, 8(sp) 772; RV32IFD-NEXT: sw a3, 12(sp) 773; RV32IFD-NEXT: fld ft1, 8(sp) 774; RV32IFD-NEXT: sw a0, 8(sp) 775; RV32IFD-NEXT: sw a1, 12(sp) 776; RV32IFD-NEXT: fld ft2, 8(sp) 777; RV32IFD-NEXT: fcvt.d.w ft3, zero 778; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 779; RV32IFD-NEXT: fadd.d ft1, ft1, ft3 780; RV32IFD-NEXT: fnmsub.d ft0, ft2, ft1, ft0 781; RV32IFD-NEXT: fsd ft0, 8(sp) 782; RV32IFD-NEXT: lw a0, 8(sp) 783; RV32IFD-NEXT: lw a1, 12(sp) 784; RV32IFD-NEXT: addi sp, sp, 16 785; RV32IFD-NEXT: ret 786; 787; RV64IFD-LABEL: fnmsub_d_contract: 788; RV64IFD: # %bb.0: 789; RV64IFD-NEXT: fmv.d.x ft0, a2 790; RV64IFD-NEXT: fmv.d.x ft1, a1 791; RV64IFD-NEXT: fmv.d.x ft2, a0 792; RV64IFD-NEXT: fmv.d.x ft3, zero 793; RV64IFD-NEXT: fadd.d ft2, ft2, ft3 794; RV64IFD-NEXT: fadd.d ft1, ft1, ft3 795; RV64IFD-NEXT: fnmsub.d ft0, ft2, ft1, ft0 796; RV64IFD-NEXT: fmv.x.d a0, ft0 797; RV64IFD-NEXT: ret 798 %a_ = fadd double 0.0, %a ; avoid negation using xor 799 %b_ = fadd double 0.0, %b ; avoid negation using xor 800 %1 = fmul contract double %a_, %b_ 801 %2 = fsub contract double %c, %1 802 ret double %2 803} 804