1; RUN: llc < %s -asm-verbose=false | FileCheck %s 2 3; Test that basic 64-bit floating-point operations assemble as expected. 4 5target datalayout = "e-p:32:32-i64:64-n32:64-S128" 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) 16 17; CHECK-LABEL: fadd64: 18; CHECK-NEXT: .param f64{{$}} 19; CHECK-NEXT: .param f64{{$}} 20; CHECK-NEXT: .result f64{{$}} 21; CHECK-NEXT: .local f64, f64, f64{{$}} 22; CHECK-NEXT: get_local push, 1{{$}} 23; CHECK-NEXT: set_local 2, pop{{$}} 24; CHECK-NEXT: get_local push, 0{{$}} 25; CHECK-NEXT: set_local 3, pop{{$}} 26; CHECK-NEXT: f64.add push, (get_local 3), (get_local 2){{$}} 27; CHECK-NEXT: set_local 4, pop{{$}} 28; CHECK-NEXT: return (get_local 4){{$}} 29define double @fadd64(double %x, double %y) { 30 %a = fadd double %x, %y 31 ret double %a 32} 33 34; CHECK-LABEL: fsub64: 35; CHECK: f64.sub push, (get_local 3), (get_local 2){{$}} 36; CHECK-NEXT: set_local 4, pop{{$}} 37define double @fsub64(double %x, double %y) { 38 %a = fsub double %x, %y 39 ret double %a 40} 41 42; CHECK-LABEL: fmul64: 43; CHECK: f64.mul push, (get_local 3), (get_local 2){{$}} 44; CHECK-NEXT: set_local 4, pop{{$}} 45define double @fmul64(double %x, double %y) { 46 %a = fmul double %x, %y 47 ret double %a 48} 49 50; CHECK-LABEL: fdiv64: 51; CHECK: f64.div push, (get_local 3), (get_local 2){{$}} 52; CHECK-NEXT: set_local 4, pop{{$}} 53define double @fdiv64(double %x, double %y) { 54 %a = fdiv double %x, %y 55 ret double %a 56} 57 58; CHECK-LABEL: fabs64: 59; CHECK: f64.abs push, (get_local 1){{$}} 60; CHECK-NEXT: set_local 2, pop{{$}} 61define double @fabs64(double %x) { 62 %a = call double @llvm.fabs.f64(double %x) 63 ret double %a 64} 65 66; CHECK-LABEL: fneg64: 67; CHECK: f64.neg push, (get_local 1){{$}} 68; CHECK-NEXT: set_local 2, pop{{$}} 69define double @fneg64(double %x) { 70 %a = fsub double -0., %x 71 ret double %a 72} 73 74; CHECK-LABEL: copysign64: 75; CHECK: f64.copysign push, (get_local 3), (get_local 2){{$}} 76; CHECK-NEXT: set_local 4, pop{{$}} 77define double @copysign64(double %x, double %y) { 78 %a = call double @llvm.copysign.f64(double %x, double %y) 79 ret double %a 80} 81 82; CHECK-LABEL: sqrt64: 83; CHECK: f64.sqrt push, (get_local 1){{$}} 84; CHECK-NEXT: set_local 2, pop{{$}} 85define double @sqrt64(double %x) { 86 %a = call double @llvm.sqrt.f64(double %x) 87 ret double %a 88} 89 90; CHECK-LABEL: ceil64: 91; CHECK: f64.ceil push, (get_local 1){{$}} 92; CHECK-NEXT: set_local 2, pop{{$}} 93define double @ceil64(double %x) { 94 %a = call double @llvm.ceil.f64(double %x) 95 ret double %a 96} 97 98; CHECK-LABEL: floor64: 99; CHECK: f64.floor push, (get_local 1){{$}} 100; CHECK-NEXT: set_local 2, pop{{$}} 101define double @floor64(double %x) { 102 %a = call double @llvm.floor.f64(double %x) 103 ret double %a 104} 105 106; CHECK-LABEL: trunc64: 107; CHECK: f64.trunc push, (get_local 1){{$}} 108; CHECK-NEXT: set_local 2, pop{{$}} 109define double @trunc64(double %x) { 110 %a = call double @llvm.trunc.f64(double %x) 111 ret double %a 112} 113 114; CHECK-LABEL: nearest64: 115; CHECK: f64.nearest push, (get_local 1){{$}} 116; CHECK-NEXT: set_local 2, pop{{$}} 117define double @nearest64(double %x) { 118 %a = call double @llvm.nearbyint.f64(double %x) 119 ret double %a 120} 121 122; CHECK-LABEL: nearest64_via_rint: 123; CHECK: f64.nearest push, (get_local 1){{$}} 124; CHECK-NEXT: set_local 2, pop{{$}} 125define double @nearest64_via_rint(double %x) { 126 %a = call double @llvm.rint.f64(double %x) 127 ret double %a 128} 129 130; Min and max tests. LLVM currently only forms fminnan and fmaxnan nodes in 131; cases where there's a single fcmp with a select and it can prove that one 132; of the arms is never NaN, so we only test that case. In the future if LLVM 133; learns to form fminnan/fmaxnan in more cases, we can write more general 134; tests. 135 136; CHECK-LABEL: fmin64: 137; CHECK: f64.min push, (get_local 1), (get_local 2){{$}} 138; CHECK-NEXT: set_local 3, pop{{$}} 139define double @fmin64(double %x) { 140 %a = fcmp ult double %x, 0.0 141 %b = select i1 %a, double %x, double 0.0 142 ret double %b 143} 144 145; CHECK-LABEL: fmax64: 146; CHECK: f64.max push, (get_local 1), (get_local 2){{$}} 147; CHECK-NEXT: set_local 3, pop{{$}} 148define double @fmax64(double %x) { 149 %a = fcmp ugt double %x, 0.0 150 %b = select i1 %a, double %x, double 0.0 151 ret double %b 152} 153