1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s 3 4; Test that basic 64-bit floating-point operations assemble as expected. 5 6target triple = "wasm32-unknown-unknown" 7 8declare double @llvm.fabs.f64(double) 9declare double @llvm.copysign.f64(double, double) 10declare double @llvm.sqrt.f64(double) 11declare double @llvm.ceil.f64(double) 12declare double @llvm.floor.f64(double) 13declare double @llvm.trunc.f64(double) 14declare double @llvm.nearbyint.f64(double) 15declare double @llvm.rint.f64(double) 16declare double @llvm.roundeven.f64(double) 17declare double @llvm.fma.f64(double, double, double) 18 19define double @fadd64(double %x, double %y) { 20; CHECK-LABEL: fadd64: 21; CHECK: .functype fadd64 (f64, f64) -> (f64) 22; CHECK-NEXT: # %bb.0: 23; CHECK-NEXT: local.get $push2=, 0 24; CHECK-NEXT: local.get $push1=, 1 25; CHECK-NEXT: f64.add $push0=, $pop2, $pop1 26; CHECK-NEXT: return $pop0 27 %a = fadd double %x, %y 28 ret double %a 29} 30 31define double @fsub64(double %x, double %y) { 32; CHECK-LABEL: fsub64: 33; CHECK: .functype fsub64 (f64, f64) -> (f64) 34; CHECK-NEXT: # %bb.0: 35; CHECK-NEXT: local.get $push2=, 0 36; CHECK-NEXT: local.get $push1=, 1 37; CHECK-NEXT: f64.sub $push0=, $pop2, $pop1 38; CHECK-NEXT: return $pop0 39 %a = fsub double %x, %y 40 ret double %a 41} 42 43define double @fmul64(double %x, double %y) { 44; CHECK-LABEL: fmul64: 45; CHECK: .functype fmul64 (f64, f64) -> (f64) 46; CHECK-NEXT: # %bb.0: 47; CHECK-NEXT: local.get $push2=, 0 48; CHECK-NEXT: local.get $push1=, 1 49; CHECK-NEXT: f64.mul $push0=, $pop2, $pop1 50; CHECK-NEXT: return $pop0 51 %a = fmul double %x, %y 52 ret double %a 53} 54 55define double @fdiv64(double %x, double %y) { 56; CHECK-LABEL: fdiv64: 57; CHECK: .functype fdiv64 (f64, f64) -> (f64) 58; CHECK-NEXT: # %bb.0: 59; CHECK-NEXT: local.get $push2=, 0 60; CHECK-NEXT: local.get $push1=, 1 61; CHECK-NEXT: f64.div $push0=, $pop2, $pop1 62; CHECK-NEXT: return $pop0 63 %a = fdiv double %x, %y 64 ret double %a 65} 66 67define double @fabs64(double %x) { 68; CHECK-LABEL: fabs64: 69; CHECK: .functype fabs64 (f64) -> (f64) 70; CHECK-NEXT: # %bb.0: 71; CHECK-NEXT: local.get $push1=, 0 72; CHECK-NEXT: f64.abs $push0=, $pop1 73; CHECK-NEXT: return $pop0 74 %a = call double @llvm.fabs.f64(double %x) 75 ret double %a 76} 77 78define double @fneg64(double %x) { 79; CHECK-LABEL: fneg64: 80; CHECK: .functype fneg64 (f64) -> (f64) 81; CHECK-NEXT: # %bb.0: 82; CHECK-NEXT: local.get $push1=, 0 83; CHECK-NEXT: f64.neg $push0=, $pop1 84; CHECK-NEXT: return $pop0 85 %a = fsub double -0., %x 86 ret double %a 87} 88 89define double @copysign64(double %x, double %y) { 90; CHECK-LABEL: copysign64: 91; CHECK: .functype copysign64 (f64, f64) -> (f64) 92; CHECK-NEXT: # %bb.0: 93; CHECK-NEXT: local.get $push2=, 0 94; CHECK-NEXT: local.get $push1=, 1 95; CHECK-NEXT: f64.copysign $push0=, $pop2, $pop1 96; CHECK-NEXT: return $pop0 97 %a = call double @llvm.copysign.f64(double %x, double %y) 98 ret double %a 99} 100 101define double @sqrt64(double %x) { 102; CHECK-LABEL: sqrt64: 103; CHECK: .functype sqrt64 (f64) -> (f64) 104; CHECK-NEXT: # %bb.0: 105; CHECK-NEXT: local.get $push1=, 0 106; CHECK-NEXT: f64.sqrt $push0=, $pop1 107; CHECK-NEXT: return $pop0 108 %a = call double @llvm.sqrt.f64(double %x) 109 ret double %a 110} 111 112define double @ceil64(double %x) { 113; CHECK-LABEL: ceil64: 114; CHECK: .functype ceil64 (f64) -> (f64) 115; CHECK-NEXT: # %bb.0: 116; CHECK-NEXT: local.get $push1=, 0 117; CHECK-NEXT: f64.ceil $push0=, $pop1 118; CHECK-NEXT: return $pop0 119 %a = call double @llvm.ceil.f64(double %x) 120 ret double %a 121} 122 123define double @floor64(double %x) { 124; CHECK-LABEL: floor64: 125; CHECK: .functype floor64 (f64) -> (f64) 126; CHECK-NEXT: # %bb.0: 127; CHECK-NEXT: local.get $push1=, 0 128; CHECK-NEXT: f64.floor $push0=, $pop1 129; CHECK-NEXT: return $pop0 130 %a = call double @llvm.floor.f64(double %x) 131 ret double %a 132} 133 134define double @trunc64(double %x) { 135; CHECK-LABEL: trunc64: 136; CHECK: .functype trunc64 (f64) -> (f64) 137; CHECK-NEXT: # %bb.0: 138; CHECK-NEXT: local.get $push1=, 0 139; CHECK-NEXT: f64.trunc $push0=, $pop1 140; CHECK-NEXT: return $pop0 141 %a = call double @llvm.trunc.f64(double %x) 142 ret double %a 143} 144 145define double @nearest64(double %x) { 146; CHECK-LABEL: nearest64: 147; CHECK: .functype nearest64 (f64) -> (f64) 148; CHECK-NEXT: # %bb.0: 149; CHECK-NEXT: local.get $push1=, 0 150; CHECK-NEXT: f64.nearest $push0=, $pop1 151; CHECK-NEXT: return $pop0 152 %a = call double @llvm.nearbyint.f64(double %x) 153 ret double %a 154} 155 156define double @nearest64_via_rint(double %x) { 157; CHECK-LABEL: nearest64_via_rint: 158; CHECK: .functype nearest64_via_rint (f64) -> (f64) 159; CHECK-NEXT: # %bb.0: 160; CHECK-NEXT: local.get $push1=, 0 161; CHECK-NEXT: f64.nearest $push0=, $pop1 162; CHECK-NEXT: return $pop0 163 %a = call double @llvm.rint.f64(double %x) 164 ret double %a 165} 166 167define double @nearest64_via_roundeven(double %x) { 168; CHECK-LABEL: nearest64_via_roundeven: 169; CHECK: .functype nearest64_via_roundeven (f64) -> (f64) 170; CHECK-NEXT: # %bb.0: 171; CHECK-NEXT: local.get $push1=, 0 172; CHECK-NEXT: f64.nearest $push0=, $pop1 173; CHECK-NEXT: return $pop0 174 %a = call double @llvm.roundeven.f64(double %x) 175 ret double %a 176} 177 178; This is not "minimum" because a -0.0 input returns +0.0. 179 180define double @fmin64(double %x) { 181; CHECK-LABEL: fmin64: 182; CHECK: .functype fmin64 (f64) -> (f64) 183; CHECK-NEXT: # %bb.0: 184; CHECK-NEXT: f64.const $push0=, 0x0p0 185; CHECK-NEXT: local.get $push5=, 0 186; CHECK-NEXT: local.get $push4=, 0 187; CHECK-NEXT: f64.const $push3=, 0x0p0 188; CHECK-NEXT: f64.ge $push1=, $pop4, $pop3 189; CHECK-NEXT: f64.select $push2=, $pop0, $pop5, $pop1 190; CHECK-NEXT: return $pop2 191 %a = fcmp ult double %x, 0.0 192 %b = select i1 %a, double %x, double 0.0 193 ret double %b 194} 195 196; This is not "maximum" because a -0.0 input returns +0.0. 197 198define double @fmax64(double %x) { 199; CHECK-LABEL: fmax64: 200; CHECK: .functype fmax64 (f64) -> (f64) 201; CHECK-NEXT: # %bb.0: 202; CHECK-NEXT: f64.const $push0=, 0x0p0 203; CHECK-NEXT: local.get $push5=, 0 204; CHECK-NEXT: local.get $push4=, 0 205; CHECK-NEXT: f64.const $push3=, 0x0p0 206; CHECK-NEXT: f64.le $push1=, $pop4, $pop3 207; CHECK-NEXT: f64.select $push2=, $pop0, $pop5, $pop1 208; CHECK-NEXT: return $pop2 209 %a = fcmp ugt double %x, 0.0 210 %b = select i1 %a, double %x, double 0.0 211 ret double %b 212} 213 214declare double @llvm.minimum.f64(double, double) 215define double @fmin64_intrinsic(double %x, double %y) { 216; CHECK-LABEL: fmin64_intrinsic: 217; CHECK: .functype fmin64_intrinsic (f64, f64) -> (f64) 218; CHECK-NEXT: # %bb.0: 219; CHECK-NEXT: local.get $push2=, 0 220; CHECK-NEXT: local.get $push1=, 1 221; CHECK-NEXT: f64.min $push0=, $pop2, $pop1 222; CHECK-NEXT: return $pop0 223 %a = call double @llvm.minimum.f64(double %x, double %y) 224 ret double %a 225} 226 227declare double @llvm.minnum.f64(double, double) 228define double @fminnum64_intrinsic(double %x, double %y) { 229; CHECK-LABEL: fminnum64_intrinsic: 230; CHECK: .functype fminnum64_intrinsic (f64, f64) -> (f64) 231; CHECK-NEXT: # %bb.0: 232; CHECK-NEXT: local.get $push5=, 0 233; CHECK-NEXT: local.get $push4=, 1 234; CHECK-NEXT: local.get $push3=, 0 235; CHECK-NEXT: local.get $push2=, 1 236; CHECK-NEXT: f64.lt $push0=, $pop3, $pop2 237; CHECK-NEXT: f64.select $push1=, $pop5, $pop4, $pop0 238; CHECK-NEXT: return $pop1 239 %a = call nnan double @llvm.minnum.f64(double %x, double %y) 240 ret double %a 241} 242 243define double @fminnum64_nsz_intrinsic(double %x, double %y) { 244; CHECK-LABEL: fminnum64_nsz_intrinsic: 245; CHECK: .functype fminnum64_nsz_intrinsic (f64, f64) -> (f64) 246; CHECK-NEXT: # %bb.0: 247; CHECK-NEXT: local.get $push2=, 0 248; CHECK-NEXT: local.get $push1=, 1 249; CHECK-NEXT: f64.min $push0=, $pop2, $pop1 250; CHECK-NEXT: return $pop0 251 %a = call nnan nsz double @llvm.minnum.f64(double %x, double %y) 252 ret double %a 253} 254 255define double @fminnum64_zero_intrinsic(double %x) { 256; CHECK-LABEL: fminnum64_zero_intrinsic: 257; CHECK: .functype fminnum64_zero_intrinsic (f64) -> (f64) 258; CHECK-NEXT: # %bb.0: 259; CHECK-NEXT: local.get $push5=, 0 260; CHECK-NEXT: f64.const $push0=, -0x0p0 261; CHECK-NEXT: local.get $push4=, 0 262; CHECK-NEXT: f64.const $push3=, -0x0p0 263; CHECK-NEXT: f64.lt $push1=, $pop4, $pop3 264; CHECK-NEXT: f64.select $push2=, $pop5, $pop0, $pop1 265; CHECK-NEXT: return $pop2 266 %a = call nnan double @llvm.minnum.f64(double %x, double -0.0) 267 ret double %a 268} 269 270define double @fminnum64_non_zero_intrinsic(double %x) { 271; CHECK-LABEL: fminnum64_non_zero_intrinsic: 272; CHECK: .functype fminnum64_non_zero_intrinsic (f64) -> (f64) 273; CHECK-NEXT: # %bb.0: 274; CHECK-NEXT: local.get $push2=, 0 275; CHECK-NEXT: f64.const $push0=, -0x1p0 276; CHECK-NEXT: f64.min $push1=, $pop2, $pop0 277; CHECK-NEXT: return $pop1 278 %a = call nnan double @llvm.minnum.f64(double %x, double -1.0) 279 ret double %a 280} 281 282declare double @llvm.maximum.f64(double, double) 283define double @fmax64_intrinsic(double %x, double %y) { 284; CHECK-LABEL: fmax64_intrinsic: 285; CHECK: .functype fmax64_intrinsic (f64, f64) -> (f64) 286; CHECK-NEXT: # %bb.0: 287; CHECK-NEXT: local.get $push2=, 0 288; CHECK-NEXT: local.get $push1=, 1 289; CHECK-NEXT: f64.max $push0=, $pop2, $pop1 290; CHECK-NEXT: return $pop0 291 %a = call double @llvm.maximum.f64(double %x, double %y) 292 ret double %a 293} 294 295declare double @llvm.maxnum.f64(double, double) 296define double@fmaxnum64_intrinsic(double %x, double %y) { 297; CHECK-LABEL: fmaxnum64_intrinsic: 298; CHECK: .functype fmaxnum64_intrinsic (f64, f64) -> (f64) 299; CHECK-NEXT: # %bb.0: 300; CHECK-NEXT: local.get $push5=, 0 301; CHECK-NEXT: local.get $push4=, 1 302; CHECK-NEXT: local.get $push3=, 0 303; CHECK-NEXT: local.get $push2=, 1 304; CHECK-NEXT: f64.gt $push0=, $pop3, $pop2 305; CHECK-NEXT: f64.select $push1=, $pop5, $pop4, $pop0 306; CHECK-NEXT: return $pop1 307 %a = call nnan double @llvm.maxnum.f64(double %x, double %y) 308 ret double %a 309} 310 311define double@fmaxnum64_nsz_intrinsic(double %x, double %y) { 312; CHECK-LABEL: fmaxnum64_nsz_intrinsic: 313; CHECK: .functype fmaxnum64_nsz_intrinsic (f64, f64) -> (f64) 314; CHECK-NEXT: # %bb.0: 315; CHECK-NEXT: local.get $push2=, 0 316; CHECK-NEXT: local.get $push1=, 1 317; CHECK-NEXT: f64.max $push0=, $pop2, $pop1 318; CHECK-NEXT: return $pop0 319 %a = call nnan nsz double @llvm.maxnum.f64(double %x, double %y) 320 ret double %a 321} 322 323define double @fmaxnum64_zero_intrinsic(double %x) { 324; CHECK-LABEL: fmaxnum64_zero_intrinsic: 325; CHECK: .functype fmaxnum64_zero_intrinsic (f64) -> (f64) 326; CHECK-NEXT: # %bb.0: 327; CHECK-NEXT: local.get $push5=, 0 328; CHECK-NEXT: f64.const $push0=, 0x0p0 329; CHECK-NEXT: local.get $push4=, 0 330; CHECK-NEXT: f64.const $push3=, 0x0p0 331; CHECK-NEXT: f64.gt $push1=, $pop4, $pop3 332; CHECK-NEXT: f64.select $push2=, $pop5, $pop0, $pop1 333; CHECK-NEXT: return $pop2 334 %a = call nnan double @llvm.maxnum.f64(double %x, double 0.0) 335 ret double %a 336} 337 338define double @fmaxnum64_non_zero_intrinsic(double %x) { 339; CHECK-LABEL: fmaxnum64_non_zero_intrinsic: 340; CHECK: .functype fmaxnum64_non_zero_intrinsic (f64) -> (f64) 341; CHECK-NEXT: # %bb.0: 342; CHECK-NEXT: local.get $push2=, 0 343; CHECK-NEXT: f64.const $push0=, 0x1p0 344; CHECK-NEXT: f64.max $push1=, $pop2, $pop0 345; CHECK-NEXT: return $pop1 346 %a = call nnan double @llvm.maxnum.f64(double %x, double 1.0) 347 ret double %a 348} 349 350define double @fma64(double %a, double %b, double %c) { 351; CHECK-LABEL: fma64: 352; CHECK: .functype fma64 (f64, f64, f64) -> (f64) 353; CHECK-NEXT: # %bb.0: 354; CHECK-NEXT: local.get $push3=, 0 355; CHECK-NEXT: local.get $push2=, 1 356; CHECK-NEXT: local.get $push1=, 2 357; CHECK-NEXT: call $push0=, fma, $pop3, $pop2, $pop1 358; CHECK-NEXT: return $pop0 359 %d = call double @llvm.fma.f64(double %a, double %b, double %c) 360 ret double %d 361} 362