1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -target-abi ilp32d -mattr=+zfa,+d < %s \ 3; RUN: | FileCheck --check-prefixes=CHECK,RV32IDZFA %s 4; RUN: llc -mtriple=riscv64 -target-abi lp64d -mattr=+zfa,+d < %s \ 5; RUN: | FileCheck --check-prefixes=CHECK,RV64DZFA %s 6 7define double @loadfpimm1() { 8; CHECK-LABEL: loadfpimm1: 9; CHECK: # %bb.0: 10; CHECK-NEXT: fli.d fa0, 0.0625 11; CHECK-NEXT: ret 12 ret double 0.0625 13} 14 15define double @loadfpimm2() { 16; CHECK-LABEL: loadfpimm2: 17; CHECK: # %bb.0: 18; CHECK-NEXT: fli.d fa0, 0.75 19; CHECK-NEXT: ret 20 ret double 0.75 21} 22 23define double @loadfpimm3() { 24; CHECK-LABEL: loadfpimm3: 25; CHECK: # %bb.0: 26; CHECK-NEXT: fli.d fa0, 1.25 27; CHECK-NEXT: ret 28 ret double 1.25 29} 30 31define double @loadfpimm4() { 32; CHECK-LABEL: loadfpimm4: 33; CHECK: # %bb.0: 34; CHECK-NEXT: fli.d fa0, 3.0 35; CHECK-NEXT: ret 36 ret double 3.0 37} 38 39define double @loadfpimm5() { 40; CHECK-LABEL: loadfpimm5: 41; CHECK: # %bb.0: 42; CHECK-NEXT: fli.d fa0, 256.0 43; CHECK-NEXT: ret 44 ret double 256.0 45} 46 47define double @loadfpimm6() { 48; CHECK-LABEL: loadfpimm6: 49; CHECK: # %bb.0: 50; CHECK-NEXT: fli.d fa0, inf 51; CHECK-NEXT: ret 52 ret double 0x7FF0000000000000 53} 54 55define double @loadfpimm7() { 56; CHECK-LABEL: loadfpimm7: 57; CHECK: # %bb.0: 58; CHECK-NEXT: fli.d fa0, nan 59; CHECK-NEXT: ret 60 ret double 0x7FF8000000000000 61} 62 63define double @loadfpimm8() { 64; CHECK-LABEL: loadfpimm8: 65; CHECK: # %bb.0: 66; CHECK-NEXT: fli.d fa0, min 67; CHECK-NEXT: ret 68 ret double 0x0010000000000000 69} 70 71define double @loadfpimm9() { 72; CHECK-LABEL: loadfpimm9: 73; CHECK: # %bb.0: 74; CHECK-NEXT: lui a0, %hi(.LCPI8_0) 75; CHECK-NEXT: fld fa0, %lo(.LCPI8_0)(a0) 76; CHECK-NEXT: ret 77 ret double 255.0 78} 79 80; Negative test. This is 1 * 2^256. 81define double @loadfpimm10() { 82; CHECK-LABEL: loadfpimm10: 83; CHECK: # %bb.0: 84; CHECK-NEXT: lui a0, %hi(.LCPI9_0) 85; CHECK-NEXT: fld fa0, %lo(.LCPI9_0)(a0) 86; CHECK-NEXT: ret 87 ret double 0x1000000000000000 88} 89 90; Negative test. This is a qnan with payload of 1. 91define double @loadfpimm11() { 92; CHECK-LABEL: loadfpimm11: 93; CHECK: # %bb.0: 94; CHECK-NEXT: lui a0, %hi(.LCPI10_0) 95; CHECK-NEXT: fld fa0, %lo(.LCPI10_0)(a0) 96; CHECK-NEXT: ret 97 ret double 0x7ff8000000000001 98} 99 100; Negative test. This is an snan with payload of 1. 101define double @loadfpimm12() { 102; CHECK-LABEL: loadfpimm12: 103; CHECK: # %bb.0: 104; CHECK-NEXT: lui a0, %hi(.LCPI11_0) 105; CHECK-NEXT: fld fa0, %lo(.LCPI11_0)(a0) 106; CHECK-NEXT: ret 107 ret double 0x7ff0000000000001 108} 109 110; Negative test. This is the smallest denormal. 111define double @loadfpimm13() { 112; RV32IDZFA-LABEL: loadfpimm13: 113; RV32IDZFA: # %bb.0: 114; RV32IDZFA-NEXT: lui a0, %hi(.LCPI12_0) 115; RV32IDZFA-NEXT: fld fa0, %lo(.LCPI12_0)(a0) 116; RV32IDZFA-NEXT: ret 117; 118; RV64DZFA-LABEL: loadfpimm13: 119; RV64DZFA: # %bb.0: 120; RV64DZFA-NEXT: li a0, 1 121; RV64DZFA-NEXT: fmv.d.x fa0, a0 122; RV64DZFA-NEXT: ret 123 ret double 0x0000000000000001 124} 125 126; Negative test. This is 2^-1023, a denormal. 127define double @loadfpimm15() { 128; CHECK-LABEL: loadfpimm15: 129; CHECK: # %bb.0: 130; CHECK-NEXT: lui a0, %hi(.LCPI13_0) 131; CHECK-NEXT: fld fa0, %lo(.LCPI13_0)(a0) 132; CHECK-NEXT: ret 133 ret double 0x0008000000000000 134} 135 136define double @loadfpimm16() { 137; CHECK-LABEL: loadfpimm16: 138; CHECK: # %bb.0: 139; CHECK-NEXT: fli.d fa0, -1.0 140; CHECK-NEXT: ret 141 ret double -1.0 142} 143 144; Ensure fli isn't directly used for negated versions of numbers in the fli 145; table. 146define double @loadfpimm17() { 147; CHECK-LABEL: loadfpimm17: 148; CHECK: # %bb.0: 149; CHECK-NEXT: fli.d fa5, 2.0 150; CHECK-NEXT: fneg.d fa0, fa5 151; CHECK-NEXT: ret 152 ret double -2.0 153} 154 155; Ensure fli isn't directly used for negative min normal value. 156define double @loadfpimm18() { 157; CHECK-LABEL: loadfpimm18: 158; CHECK: # %bb.0: 159; CHECK-NEXT: fli.d fa5, min 160; CHECK-NEXT: fneg.d fa0, fa5 161; CHECK-NEXT: ret 162 ret double 0x8010000000000000 163} 164 165declare double @llvm.minimum.f64(double, double) 166 167define double @fminm_d(double %a, double %b) nounwind { 168; CHECK-LABEL: fminm_d: 169; CHECK: # %bb.0: 170; CHECK-NEXT: fminm.d fa0, fa0, fa1 171; CHECK-NEXT: ret 172 %1 = call double @llvm.minimum.f64(double %a, double %b) 173 ret double %1 174} 175 176declare double @llvm.maximum.f64(double, double) 177 178define double @fmaxm_d(double %a, double %b) nounwind { 179; CHECK-LABEL: fmaxm_d: 180; CHECK: # %bb.0: 181; CHECK-NEXT: fmaxm.d fa0, fa0, fa1 182; CHECK-NEXT: ret 183 %1 = call double @llvm.maximum.f64(double %a, double %b) 184 ret double %1 185} 186 187define double @fround_d_1(double %a) nounwind { 188; CHECK-LABEL: fround_d_1: 189; CHECK: # %bb.0: 190; CHECK-NEXT: fround.d fa0, fa0, rmm 191; CHECK-NEXT: ret 192 %call = tail call double @round(double %a) nounwind readnone 193 ret double %call 194} 195 196declare double @round(double) nounwind readnone 197 198 199define double @fround_d_2(double %a) nounwind { 200; CHECK-LABEL: fround_d_2: 201; CHECK: # %bb.0: 202; CHECK-NEXT: fround.d fa0, fa0, rdn 203; CHECK-NEXT: ret 204 %call = tail call double @floor(double %a) nounwind readnone 205 ret double %call 206} 207 208declare double @floor(double) nounwind readnone 209 210 211define double @fround_d_3(double %a) nounwind { 212; CHECK-LABEL: fround_d_3: 213; CHECK: # %bb.0: 214; CHECK-NEXT: fround.d fa0, fa0, rup 215; CHECK-NEXT: ret 216 %call = tail call double @ceil(double %a) nounwind readnone 217 ret double %call 218} 219 220declare double @ceil(double) nounwind readnone 221 222 223define double @fround_d_4(double %a) nounwind { 224; CHECK-LABEL: fround_d_4: 225; CHECK: # %bb.0: 226; CHECK-NEXT: fround.d fa0, fa0, rtz 227; CHECK-NEXT: ret 228 %call = tail call double @trunc(double %a) nounwind readnone 229 ret double %call 230} 231 232declare double @trunc(double) nounwind readnone 233 234 235define double @fround_d_5(double %a) nounwind { 236; CHECK-LABEL: fround_d_5: 237; CHECK: # %bb.0: 238; CHECK-NEXT: fround.d fa0, fa0 239; CHECK-NEXT: ret 240 %call = tail call double @nearbyint(double %a) nounwind readnone 241 ret double %call 242} 243 244declare double @nearbyint(double) nounwind readnone 245 246define double @fround_d_6(double %a) nounwind { 247; CHECK-LABEL: fround_d_6: 248; CHECK: # %bb.0: 249; CHECK-NEXT: fround.d fa0, fa0, rne 250; CHECK-NEXT: ret 251 %call = tail call double @llvm.roundeven.f64(double %a) nounwind readnone 252 ret double %call 253} 254 255declare double @llvm.roundeven.f64(double) nounwind readnone 256 257 258define double @froundnx_d(double %a) nounwind { 259; CHECK-LABEL: froundnx_d: 260; CHECK: # %bb.0: 261; CHECK-NEXT: froundnx.d fa0, fa0 262; CHECK-NEXT: ret 263 %call = tail call double @rint(double %a) nounwind readnone 264 ret double %call 265} 266 267declare double @rint(double) nounwind readnone 268 269declare i1 @llvm.experimental.constrained.fcmp.f64(double, double, metadata, metadata) 270 271define i32 @fcmp_olt_q(double %a, double %b) nounwind strictfp { 272; CHECK-LABEL: fcmp_olt_q: 273; CHECK: # %bb.0: 274; CHECK-NEXT: fltq.d a0, fa0, fa1 275; CHECK-NEXT: ret 276 %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"olt", metadata !"fpexcept.strict") strictfp 277 %2 = zext i1 %1 to i32 278 ret i32 %2 279} 280 281define i32 @fcmp_ole_q(double %a, double %b) nounwind strictfp { 282; CHECK-LABEL: fcmp_ole_q: 283; CHECK: # %bb.0: 284; CHECK-NEXT: fleq.d a0, fa0, fa1 285; CHECK-NEXT: ret 286 %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"ole", metadata !"fpexcept.strict") strictfp 287 %2 = zext i1 %1 to i32 288 ret i32 %2 289} 290 291define i32 @fcmp_one_q(double %a, double %b) nounwind strictfp { 292; CHECK-LABEL: fcmp_one_q: 293; CHECK: # %bb.0: 294; CHECK-NEXT: fltq.d a0, fa0, fa1 295; CHECK-NEXT: fltq.d a1, fa1, fa0 296; CHECK-NEXT: or a0, a1, a0 297; CHECK-NEXT: ret 298 %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"one", metadata !"fpexcept.strict") strictfp 299 %2 = zext i1 %1 to i32 300 ret i32 %2 301} 302 303define i32 @fcmp_ueq_q(double %a, double %b) nounwind strictfp { 304; CHECK-LABEL: fcmp_ueq_q: 305; CHECK: # %bb.0: 306; CHECK-NEXT: fltq.d a0, fa0, fa1 307; CHECK-NEXT: fltq.d a1, fa1, fa0 308; CHECK-NEXT: or a0, a1, a0 309; CHECK-NEXT: xori a0, a0, 1 310; CHECK-NEXT: ret 311 %1 = call i1 @llvm.experimental.constrained.fcmp.f64(double %a, double %b, metadata !"ueq", metadata !"fpexcept.strict") strictfp 312 %2 = zext i1 %1 to i32 313 ret i32 %2 314} 315 316define i64 @fmvh_x_d(double %fa) { 317; RV32IDZFA-LABEL: fmvh_x_d: 318; RV32IDZFA: # %bb.0: 319; RV32IDZFA-NEXT: fmv.x.w a0, fa0 320; RV32IDZFA-NEXT: fmvh.x.d a1, fa0 321; RV32IDZFA-NEXT: ret 322; 323; RV64DZFA-LABEL: fmvh_x_d: 324; RV64DZFA: # %bb.0: 325; RV64DZFA-NEXT: fmv.x.d a0, fa0 326; RV64DZFA-NEXT: ret 327 %i = bitcast double %fa to i64 328 ret i64 %i 329} 330 331define double @fmvp_d_x(i64 %a) { 332; RV32IDZFA-LABEL: fmvp_d_x: 333; RV32IDZFA: # %bb.0: 334; RV32IDZFA-NEXT: fmvp.d.x fa0, a0, a1 335; RV32IDZFA-NEXT: ret 336; 337; RV64DZFA-LABEL: fmvp_d_x: 338; RV64DZFA: # %bb.0: 339; RV64DZFA-NEXT: fmv.d.x fa0, a0 340; RV64DZFA-NEXT: ret 341 %or = bitcast i64 %a to double 342 ret double %or 343} 344 345define double @fadd_neg_0p5(double %x) { 346; CHECK-LABEL: fadd_neg_0p5: 347; CHECK: # %bb.0: 348; CHECK-NEXT: fli.d fa5, 0.5 349; CHECK-NEXT: fsub.d fa0, fa0, fa5 350; CHECK-NEXT: ret 351 %a = fadd double %x, -0.5 352 ret double %a 353} 354 355define double @fma_neg_addend(double %x, double %y) nounwind { 356; CHECK-LABEL: fma_neg_addend: 357; CHECK: # %bb.0: 358; CHECK-NEXT: fli.d fa5, 0.5 359; CHECK-NEXT: fmsub.d fa0, fa0, fa1, fa5 360; CHECK-NEXT: ret 361 %a = call double @llvm.fma.f32(double %x, double %y, double -0.5) 362 ret double %a 363} 364 365define double @fma_neg_multiplicand(double %x, double %y) nounwind { 366; CHECK-LABEL: fma_neg_multiplicand: 367; CHECK: # %bb.0: 368; CHECK-NEXT: fli.d fa5, 0.125 369; CHECK-NEXT: fnmsub.d fa0, fa5, fa0, fa1 370; CHECK-NEXT: ret 371 %a = call double @llvm.fma.f32(double %x, double -0.125, double %y) 372 ret double %a 373} 374 375define double @fma_neg_addend_multiplicand(double %x) nounwind { 376; CHECK-LABEL: fma_neg_addend_multiplicand: 377; CHECK: # %bb.0: 378; CHECK-NEXT: fli.d fa5, 0.25 379; CHECK-NEXT: fli.d fa4, 0.5 380; CHECK-NEXT: fnmadd.d fa0, fa4, fa0, fa5 381; CHECK-NEXT: ret 382 %a = call double @llvm.fma.f32(double %x, double -0.5, double -0.25) 383 ret double %a 384} 385 386define double @select_loadfpimm(double %x) nounwind { 387; RV32IDZFA-LABEL: select_loadfpimm: 388; RV32IDZFA: # %bb.0: # %entry 389; RV32IDZFA-NEXT: fcvt.d.w fa5, zero 390; RV32IDZFA-NEXT: fle.d a0, fa5, fa0 391; RV32IDZFA-NEXT: fli.d fa0, 0.5 392; RV32IDZFA-NEXT: bnez a0, .LBB36_2 393; RV32IDZFA-NEXT: # %bb.1: 394; RV32IDZFA-NEXT: fneg.d fa0, fa0 395; RV32IDZFA-NEXT: .LBB36_2: # %entry 396; RV32IDZFA-NEXT: ret 397; 398; RV64DZFA-LABEL: select_loadfpimm: 399; RV64DZFA: # %bb.0: # %entry 400; RV64DZFA-NEXT: fmv.d.x fa5, zero 401; RV64DZFA-NEXT: fle.d a0, fa5, fa0 402; RV64DZFA-NEXT: fli.d fa0, 0.5 403; RV64DZFA-NEXT: bnez a0, .LBB36_2 404; RV64DZFA-NEXT: # %bb.1: 405; RV64DZFA-NEXT: fneg.d fa0, fa0 406; RV64DZFA-NEXT: .LBB36_2: # %entry 407; RV64DZFA-NEXT: ret 408entry: 409 %cmp = fcmp ult double %x, 0.000000e+00 410 %sel = select i1 %cmp, double -5.000000e-01, double 5.000000e-01 411 ret double %sel 412} 413