1; RUN: llc < %s -asm-verbose=false | FileCheck %s 2 3; Test that basic 32-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 float @llvm.fabs.f32(float) 9declare float @llvm.copysign.f32(float, float) 10declare float @llvm.sqrt.f32(float) 11declare float @llvm.ceil.f32(float) 12declare float @llvm.floor.f32(float) 13declare float @llvm.trunc.f32(float) 14declare float @llvm.nearbyint.f32(float) 15declare float @llvm.rint.f32(float) 16 17; CHECK-LABEL: fadd32: 18; CHECK-NEXT: .param f32{{$}} 19; CHECK-NEXT: .param f32{{$}} 20; CHECK-NEXT: .result f32{{$}} 21; CHECK-NEXT: .local f32, f32, f32{{$}} 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: f32.add push, (get_local 3), (get_local 2){{$}} 27; CHECK-NEXT: set_local 4, pop{{$}} 28; CHECK-NEXT: return (get_local 4){{$}} 29define float @fadd32(float %x, float %y) { 30 %a = fadd float %x, %y 31 ret float %a 32} 33 34; CHECK-LABEL: fsub32: 35; CHECK: f32.sub push, (get_local 3), (get_local 2){{$}} 36; CHECK-NEXT: set_local 4, pop{{$}} 37define float @fsub32(float %x, float %y) { 38 %a = fsub float %x, %y 39 ret float %a 40} 41 42; CHECK-LABEL: fmul32: 43; CHECK: f32.mul push, (get_local 3), (get_local 2){{$}} 44; CHECK-NEXT: set_local 4, pop{{$}} 45define float @fmul32(float %x, float %y) { 46 %a = fmul float %x, %y 47 ret float %a 48} 49 50; CHECK-LABEL: fdiv32: 51; CHECK: f32.div push, (get_local 3), (get_local 2){{$}} 52; CHECK-NEXT: set_local 4, pop{{$}} 53define float @fdiv32(float %x, float %y) { 54 %a = fdiv float %x, %y 55 ret float %a 56} 57 58; CHECK-LABEL: fabs32: 59; CHECK: f32.abs push, (get_local 1){{$}} 60; CHECK-NEXT: set_local 2, pop{{$}} 61define float @fabs32(float %x) { 62 %a = call float @llvm.fabs.f32(float %x) 63 ret float %a 64} 65 66; CHECK-LABEL: fneg32: 67; CHECK: f32.neg push, (get_local 1){{$}} 68; CHECK-NEXT: set_local 2, pop{{$}} 69define float @fneg32(float %x) { 70 %a = fsub float -0., %x 71 ret float %a 72} 73 74; CHECK-LABEL: copysign32: 75; CHECK: f32.copysign push, (get_local 3), (get_local 2){{$}} 76; CHECK-NEXT: set_local 4, pop{{$}} 77define float @copysign32(float %x, float %y) { 78 %a = call float @llvm.copysign.f32(float %x, float %y) 79 ret float %a 80} 81 82; CHECK-LABEL: sqrt32: 83; CHECK: f32.sqrt push, (get_local 1){{$}} 84; CHECK-NEXT: set_local 2, pop{{$}} 85define float @sqrt32(float %x) { 86 %a = call float @llvm.sqrt.f32(float %x) 87 ret float %a 88} 89 90; CHECK-LABEL: ceil32: 91; CHECK: f32.ceil push, (get_local 1){{$}} 92; CHECK-NEXT: set_local 2, pop{{$}} 93define float @ceil32(float %x) { 94 %a = call float @llvm.ceil.f32(float %x) 95 ret float %a 96} 97 98; CHECK-LABEL: floor32: 99; CHECK: f32.floor push, (get_local 1){{$}} 100; CHECK-NEXT: set_local 2, pop{{$}} 101define float @floor32(float %x) { 102 %a = call float @llvm.floor.f32(float %x) 103 ret float %a 104} 105 106; CHECK-LABEL: trunc32: 107; CHECK: f32.trunc push, (get_local 1){{$}} 108; CHECK-NEXT: set_local 2, pop{{$}} 109define float @trunc32(float %x) { 110 %a = call float @llvm.trunc.f32(float %x) 111 ret float %a 112} 113 114; CHECK-LABEL: nearest32: 115; CHECK: f32.nearest push, (get_local 1){{$}} 116; CHECK-NEXT: set_local 2, pop{{$}} 117define float @nearest32(float %x) { 118 %a = call float @llvm.nearbyint.f32(float %x) 119 ret float %a 120} 121 122; CHECK-LABEL: nearest32_via_rint: 123; CHECK: f32.nearest push, (get_local 1){{$}} 124; CHECK-NEXT: set_local 2, pop{{$}} 125define float @nearest32_via_rint(float %x) { 126 %a = call float @llvm.rint.f32(float %x) 127 ret float %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: fmin32: 137; CHECK: f32.min push, (get_local 1), (get_local 2){{$}} 138; CHECK-NEXT: set_local 3, pop{{$}} 139define float @fmin32(float %x) { 140 %a = fcmp ult float %x, 0.0 141 %b = select i1 %a, float %x, float 0.0 142 ret float %b 143} 144 145; CHECK-LABEL: fmax32: 146; CHECK: f32.max push, (get_local 1), (get_local 2){{$}} 147; CHECK-NEXT: set_local 3, pop{{$}} 148define float @fmax32(float %x) { 149 %a = fcmp ugt float %x, 0.0 150 %b = select i1 %a, float %x, float 0.0 151 ret float %b 152} 153