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 5; These tests are each targeted at a particular RISC-V FPU instruction. Most 6; other files in this folder exercise LLVM IR instructions that don't directly 7; match a RISC-V instruction. 8 9define double @fadd_d(double %a, double %b) nounwind { 10; RV32IFD-LABEL: fadd_d: 11; RV32IFD: # %bb.0: 12; RV32IFD-NEXT: addi sp, sp, -16 13; RV32IFD-NEXT: sw a2, 8(sp) 14; RV32IFD-NEXT: sw a3, 12(sp) 15; RV32IFD-NEXT: fld ft0, 8(sp) 16; RV32IFD-NEXT: sw a0, 8(sp) 17; RV32IFD-NEXT: sw a1, 12(sp) 18; RV32IFD-NEXT: fld ft1, 8(sp) 19; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 20; RV32IFD-NEXT: fsd ft0, 8(sp) 21; RV32IFD-NEXT: lw a0, 8(sp) 22; RV32IFD-NEXT: lw a1, 12(sp) 23; RV32IFD-NEXT: addi sp, sp, 16 24; RV32IFD-NEXT: ret 25 %1 = fadd double %a, %b 26 ret double %1 27} 28 29define double @fsub_d(double %a, double %b) nounwind { 30; RV32IFD-LABEL: fsub_d: 31; RV32IFD: # %bb.0: 32; RV32IFD-NEXT: addi sp, sp, -16 33; RV32IFD-NEXT: sw a2, 8(sp) 34; RV32IFD-NEXT: sw a3, 12(sp) 35; RV32IFD-NEXT: fld ft0, 8(sp) 36; RV32IFD-NEXT: sw a0, 8(sp) 37; RV32IFD-NEXT: sw a1, 12(sp) 38; RV32IFD-NEXT: fld ft1, 8(sp) 39; RV32IFD-NEXT: fsub.d ft0, ft1, ft0 40; RV32IFD-NEXT: fsd ft0, 8(sp) 41; RV32IFD-NEXT: lw a0, 8(sp) 42; RV32IFD-NEXT: lw a1, 12(sp) 43; RV32IFD-NEXT: addi sp, sp, 16 44; RV32IFD-NEXT: ret 45 %1 = fsub double %a, %b 46 ret double %1 47} 48 49define double @fmul_d(double %a, double %b) nounwind { 50; RV32IFD-LABEL: fmul_d: 51; RV32IFD: # %bb.0: 52; RV32IFD-NEXT: addi sp, sp, -16 53; RV32IFD-NEXT: sw a2, 8(sp) 54; RV32IFD-NEXT: sw a3, 12(sp) 55; RV32IFD-NEXT: fld ft0, 8(sp) 56; RV32IFD-NEXT: sw a0, 8(sp) 57; RV32IFD-NEXT: sw a1, 12(sp) 58; RV32IFD-NEXT: fld ft1, 8(sp) 59; RV32IFD-NEXT: fmul.d ft0, ft1, ft0 60; RV32IFD-NEXT: fsd ft0, 8(sp) 61; RV32IFD-NEXT: lw a0, 8(sp) 62; RV32IFD-NEXT: lw a1, 12(sp) 63; RV32IFD-NEXT: addi sp, sp, 16 64; RV32IFD-NEXT: ret 65 %1 = fmul double %a, %b 66 ret double %1 67} 68 69define double @fdiv_d(double %a, double %b) nounwind { 70; RV32IFD-LABEL: fdiv_d: 71; RV32IFD: # %bb.0: 72; RV32IFD-NEXT: addi sp, sp, -16 73; RV32IFD-NEXT: sw a2, 8(sp) 74; RV32IFD-NEXT: sw a3, 12(sp) 75; RV32IFD-NEXT: fld ft0, 8(sp) 76; RV32IFD-NEXT: sw a0, 8(sp) 77; RV32IFD-NEXT: sw a1, 12(sp) 78; RV32IFD-NEXT: fld ft1, 8(sp) 79; RV32IFD-NEXT: fdiv.d ft0, ft1, ft0 80; RV32IFD-NEXT: fsd ft0, 8(sp) 81; RV32IFD-NEXT: lw a0, 8(sp) 82; RV32IFD-NEXT: lw a1, 12(sp) 83; RV32IFD-NEXT: addi sp, sp, 16 84; RV32IFD-NEXT: ret 85 %1 = fdiv double %a, %b 86 ret double %1 87} 88 89declare double @llvm.sqrt.f32(double) 90 91define double @fsqrt_d(double %a) nounwind { 92; RV32IFD-LABEL: fsqrt_d: 93; RV32IFD: # %bb.0: 94; RV32IFD-NEXT: addi sp, sp, -16 95; RV32IFD-NEXT: sw a0, 8(sp) 96; RV32IFD-NEXT: sw a1, 12(sp) 97; RV32IFD-NEXT: fld ft0, 8(sp) 98; RV32IFD-NEXT: fsqrt.d ft0, ft0 99; RV32IFD-NEXT: fsd ft0, 8(sp) 100; RV32IFD-NEXT: lw a0, 8(sp) 101; RV32IFD-NEXT: lw a1, 12(sp) 102; RV32IFD-NEXT: addi sp, sp, 16 103; RV32IFD-NEXT: ret 104 %1 = call double @llvm.sqrt.f32(double %a) 105 ret double %1 106} 107 108declare double @llvm.copysign.f32(double, double) 109 110define double @fsgnj_d(double %a, double %b) nounwind { 111; RV32IFD-LABEL: fsgnj_d: 112; RV32IFD: # %bb.0: 113; RV32IFD-NEXT: addi sp, sp, -16 114; RV32IFD-NEXT: sw a2, 8(sp) 115; RV32IFD-NEXT: sw a3, 12(sp) 116; RV32IFD-NEXT: fld ft0, 8(sp) 117; RV32IFD-NEXT: sw a0, 8(sp) 118; RV32IFD-NEXT: sw a1, 12(sp) 119; RV32IFD-NEXT: fld ft1, 8(sp) 120; RV32IFD-NEXT: fsgnj.d ft0, ft1, ft0 121; RV32IFD-NEXT: fsd ft0, 8(sp) 122; RV32IFD-NEXT: lw a0, 8(sp) 123; RV32IFD-NEXT: lw a1, 12(sp) 124; RV32IFD-NEXT: addi sp, sp, 16 125; RV32IFD-NEXT: ret 126 %1 = call double @llvm.copysign.f32(double %a, double %b) 127 ret double %1 128} 129 130define double @fneg_d(double %a) nounwind { 131; RV32IFD-LABEL: fneg_d: 132; RV32IFD: # %bb.0: 133; RV32IFD-NEXT: addi sp, sp, -16 134; RV32IFD-NEXT: sw a0, 8(sp) 135; RV32IFD-NEXT: sw a1, 12(sp) 136; RV32IFD-NEXT: fld ft0, 8(sp) 137; RV32IFD-NEXT: fneg.d ft0, ft0 138; RV32IFD-NEXT: fsd ft0, 8(sp) 139; RV32IFD-NEXT: lw a0, 8(sp) 140; RV32IFD-NEXT: lw a1, 12(sp) 141; RV32IFD-NEXT: addi sp, sp, 16 142; RV32IFD-NEXT: ret 143 %1 = fsub double -0.0, %a 144 ret double %1 145} 146 147define double @fsgnjn_d(double %a, double %b) nounwind { 148; RV32IFD-LABEL: fsgnjn_d: 149; RV32IFD: # %bb.0: 150; RV32IFD-NEXT: addi sp, sp, -16 151; RV32IFD-NEXT: sw a2, 8(sp) 152; RV32IFD-NEXT: sw a3, 12(sp) 153; RV32IFD-NEXT: fld ft0, 8(sp) 154; RV32IFD-NEXT: sw a0, 8(sp) 155; RV32IFD-NEXT: sw a1, 12(sp) 156; RV32IFD-NEXT: fld ft1, 8(sp) 157; RV32IFD-NEXT: fsgnjn.d ft0, ft1, ft0 158; RV32IFD-NEXT: fsd ft0, 8(sp) 159; RV32IFD-NEXT: lw a0, 8(sp) 160; RV32IFD-NEXT: lw a1, 12(sp) 161; RV32IFD-NEXT: addi sp, sp, 16 162; RV32IFD-NEXT: ret 163 %1 = fsub double -0.0, %b 164 %2 = call double @llvm.copysign.f32(double %a, double %1) 165 ret double %2 166} 167 168declare double @llvm.fabs.f32(double) 169 170define double @fabs_d(double %a) nounwind { 171; RV32IFD-LABEL: fabs_d: 172; RV32IFD: # %bb.0: 173; RV32IFD-NEXT: addi sp, sp, -16 174; RV32IFD-NEXT: sw a0, 8(sp) 175; RV32IFD-NEXT: sw a1, 12(sp) 176; RV32IFD-NEXT: fld ft0, 8(sp) 177; RV32IFD-NEXT: fabs.d ft0, ft0 178; RV32IFD-NEXT: fsd ft0, 8(sp) 179; RV32IFD-NEXT: lw a0, 8(sp) 180; RV32IFD-NEXT: lw a1, 12(sp) 181; RV32IFD-NEXT: addi sp, sp, 16 182; RV32IFD-NEXT: ret 183 %1 = call double @llvm.fabs.f32(double %a) 184 ret double %1 185} 186 187declare double @llvm.minnum.f32(double, double) 188 189define double @fmin_d(double %a, double %b) nounwind { 190; RV32IFD-LABEL: fmin_d: 191; RV32IFD: # %bb.0: 192; RV32IFD-NEXT: addi sp, sp, -16 193; RV32IFD-NEXT: sw a2, 8(sp) 194; RV32IFD-NEXT: sw a3, 12(sp) 195; RV32IFD-NEXT: fld ft0, 8(sp) 196; RV32IFD-NEXT: sw a0, 8(sp) 197; RV32IFD-NEXT: sw a1, 12(sp) 198; RV32IFD-NEXT: fld ft1, 8(sp) 199; RV32IFD-NEXT: fmin.d ft0, ft1, ft0 200; RV32IFD-NEXT: fsd ft0, 8(sp) 201; RV32IFD-NEXT: lw a0, 8(sp) 202; RV32IFD-NEXT: lw a1, 12(sp) 203; RV32IFD-NEXT: addi sp, sp, 16 204; RV32IFD-NEXT: ret 205 %1 = call double @llvm.minnum.f32(double %a, double %b) 206 ret double %1 207} 208 209declare double @llvm.maxnum.f32(double, double) 210 211define double @fmax_d(double %a, double %b) nounwind { 212; RV32IFD-LABEL: fmax_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: fmax.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 %1 = call double @llvm.maxnum.f32(double %a, double %b) 228 ret double %1 229} 230 231define i32 @feq_d(double %a, double %b) nounwind { 232; RV32IFD-LABEL: feq_d: 233; RV32IFD: # %bb.0: 234; RV32IFD-NEXT: addi sp, sp, -16 235; RV32IFD-NEXT: sw a2, 8(sp) 236; RV32IFD-NEXT: sw a3, 12(sp) 237; RV32IFD-NEXT: fld ft0, 8(sp) 238; RV32IFD-NEXT: sw a0, 8(sp) 239; RV32IFD-NEXT: sw a1, 12(sp) 240; RV32IFD-NEXT: fld ft1, 8(sp) 241; RV32IFD-NEXT: feq.d a0, ft1, ft0 242; RV32IFD-NEXT: addi sp, sp, 16 243; RV32IFD-NEXT: ret 244 %1 = fcmp oeq double %a, %b 245 %2 = zext i1 %1 to i32 246 ret i32 %2 247} 248 249define i32 @flt_d(double %a, double %b) nounwind { 250; RV32IFD-LABEL: flt_d: 251; RV32IFD: # %bb.0: 252; RV32IFD-NEXT: addi sp, sp, -16 253; RV32IFD-NEXT: sw a2, 8(sp) 254; RV32IFD-NEXT: sw a3, 12(sp) 255; RV32IFD-NEXT: fld ft0, 8(sp) 256; RV32IFD-NEXT: sw a0, 8(sp) 257; RV32IFD-NEXT: sw a1, 12(sp) 258; RV32IFD-NEXT: fld ft1, 8(sp) 259; RV32IFD-NEXT: flt.d a0, ft1, ft0 260; RV32IFD-NEXT: addi sp, sp, 16 261; RV32IFD-NEXT: ret 262 %1 = fcmp olt double %a, %b 263 %2 = zext i1 %1 to i32 264 ret i32 %2 265} 266 267define i32 @fle_d(double %a, double %b) nounwind { 268; RV32IFD-LABEL: fle_d: 269; RV32IFD: # %bb.0: 270; RV32IFD-NEXT: addi sp, sp, -16 271; RV32IFD-NEXT: sw a2, 8(sp) 272; RV32IFD-NEXT: sw a3, 12(sp) 273; RV32IFD-NEXT: fld ft0, 8(sp) 274; RV32IFD-NEXT: sw a0, 8(sp) 275; RV32IFD-NEXT: sw a1, 12(sp) 276; RV32IFD-NEXT: fld ft1, 8(sp) 277; RV32IFD-NEXT: fle.d a0, ft1, ft0 278; RV32IFD-NEXT: addi sp, sp, 16 279; RV32IFD-NEXT: ret 280 %1 = fcmp ole double %a, %b 281 %2 = zext i1 %1 to i32 282 ret i32 %2 283} 284 285declare double @llvm.fma.f64(double, double, double) 286 287define double @fmadd_d(double %a, double %b, double %c) nounwind { 288; RV32IFD-LABEL: fmadd_d: 289; RV32IFD: # %bb.0: 290; RV32IFD-NEXT: addi sp, sp, -16 291; RV32IFD-NEXT: sw a4, 8(sp) 292; RV32IFD-NEXT: sw a5, 12(sp) 293; RV32IFD-NEXT: fld ft0, 8(sp) 294; RV32IFD-NEXT: sw a2, 8(sp) 295; RV32IFD-NEXT: sw a3, 12(sp) 296; RV32IFD-NEXT: fld ft1, 8(sp) 297; RV32IFD-NEXT: sw a0, 8(sp) 298; RV32IFD-NEXT: sw a1, 12(sp) 299; RV32IFD-NEXT: fld ft2, 8(sp) 300; RV32IFD-NEXT: fmadd.d ft0, ft2, ft1, ft0 301; RV32IFD-NEXT: fsd ft0, 8(sp) 302; RV32IFD-NEXT: lw a0, 8(sp) 303; RV32IFD-NEXT: lw a1, 12(sp) 304; RV32IFD-NEXT: addi sp, sp, 16 305; RV32IFD-NEXT: ret 306 %1 = call double @llvm.fma.f64(double %a, double %b, double %c) 307 ret double %1 308} 309 310define double @fmsub_d(double %a, double %b, double %c) nounwind { 311; RV32IFD-LABEL: fmsub_d: 312; RV32IFD: # %bb.0: 313; RV32IFD-NEXT: addi sp, sp, -16 314; RV32IFD-NEXT: sw a2, 8(sp) 315; RV32IFD-NEXT: sw a3, 12(sp) 316; RV32IFD-NEXT: fld ft0, 8(sp) 317; RV32IFD-NEXT: sw a0, 8(sp) 318; RV32IFD-NEXT: sw a1, 12(sp) 319; RV32IFD-NEXT: fld ft1, 8(sp) 320; RV32IFD-NEXT: sw a4, 8(sp) 321; RV32IFD-NEXT: sw a5, 12(sp) 322; RV32IFD-NEXT: fld ft2, 8(sp) 323; RV32IFD-NEXT: lui a0, %hi(.LCPI15_0) 324; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI15_0) 325; RV32IFD-NEXT: fld ft3, 0(a0) 326; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 327; RV32IFD-NEXT: fmsub.d ft0, ft1, ft0, ft2 328; RV32IFD-NEXT: fsd ft0, 8(sp) 329; RV32IFD-NEXT: lw a0, 8(sp) 330; RV32IFD-NEXT: lw a1, 12(sp) 331; RV32IFD-NEXT: addi sp, sp, 16 332; RV32IFD-NEXT: ret 333 %c_ = fadd double 0.0, %c ; avoid negation using xor 334 %negc = fsub double -0.0, %c_ 335 %1 = call double @llvm.fma.f64(double %a, double %b, double %negc) 336 ret double %1 337} 338 339define double @fnmadd_d(double %a, double %b, double %c) nounwind { 340; RV32IFD-LABEL: fnmadd_d: 341; RV32IFD: # %bb.0: 342; RV32IFD-NEXT: addi sp, sp, -16 343; RV32IFD-NEXT: sw a2, 8(sp) 344; RV32IFD-NEXT: sw a3, 12(sp) 345; RV32IFD-NEXT: fld ft0, 8(sp) 346; RV32IFD-NEXT: sw a0, 8(sp) 347; RV32IFD-NEXT: sw a1, 12(sp) 348; RV32IFD-NEXT: fld ft1, 8(sp) 349; RV32IFD-NEXT: sw a4, 8(sp) 350; RV32IFD-NEXT: sw a5, 12(sp) 351; RV32IFD-NEXT: fld ft2, 8(sp) 352; RV32IFD-NEXT: lui a0, %hi(.LCPI16_0) 353; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI16_0) 354; RV32IFD-NEXT: fld ft3, 0(a0) 355; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 356; RV32IFD-NEXT: fadd.d ft1, ft1, ft3 357; RV32IFD-NEXT: fnmadd.d ft0, ft1, ft0, ft2 358; RV32IFD-NEXT: fsd ft0, 8(sp) 359; RV32IFD-NEXT: lw a0, 8(sp) 360; RV32IFD-NEXT: lw a1, 12(sp) 361; RV32IFD-NEXT: addi sp, sp, 16 362; RV32IFD-NEXT: ret 363 %a_ = fadd double 0.0, %a 364 %c_ = fadd double 0.0, %c 365 %nega = fsub double -0.0, %a_ 366 %negc = fsub double -0.0, %c_ 367 %1 = call double @llvm.fma.f64(double %nega, double %b, double %negc) 368 ret double %1 369} 370 371define double @fnmsub_d(double %a, double %b, double %c) nounwind { 372; RV32IFD-LABEL: fnmsub_d: 373; RV32IFD: # %bb.0: 374; RV32IFD-NEXT: addi sp, sp, -16 375; RV32IFD-NEXT: sw a4, 8(sp) 376; RV32IFD-NEXT: sw a5, 12(sp) 377; RV32IFD-NEXT: fld ft0, 8(sp) 378; RV32IFD-NEXT: sw a2, 8(sp) 379; RV32IFD-NEXT: sw a3, 12(sp) 380; RV32IFD-NEXT: fld ft1, 8(sp) 381; RV32IFD-NEXT: sw a0, 8(sp) 382; RV32IFD-NEXT: sw a1, 12(sp) 383; RV32IFD-NEXT: fld ft2, 8(sp) 384; RV32IFD-NEXT: lui a0, %hi(.LCPI17_0) 385; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI17_0) 386; RV32IFD-NEXT: fld ft3, 0(a0) 387; RV32IFD-NEXT: fadd.d ft2, ft2, ft3 388; RV32IFD-NEXT: fnmsub.d ft0, ft2, ft1, ft0 389; RV32IFD-NEXT: fsd ft0, 8(sp) 390; RV32IFD-NEXT: lw a0, 8(sp) 391; RV32IFD-NEXT: lw a1, 12(sp) 392; RV32IFD-NEXT: addi sp, sp, 16 393; RV32IFD-NEXT: ret 394 %a_ = fadd double 0.0, %a 395 %nega = fsub double -0.0, %a_ 396 %1 = call double @llvm.fma.f64(double %nega, double %b, double %c) 397 ret double %1 398} 399