1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+nontrapping-fptoint | FileCheck %s 2 3; Test that basic conversion operations assemble as expected. 4 5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 6target triple = "wasm32-unknown-unknown" 7 8; CHECK-LABEL: i32_wrap_i64: 9; CHECK-NEXT: .functype i32_wrap_i64 (i64) -> (i32){{$}} 10; CHECK-NEXT: i32.wrap_i64 $push[[NUM:[0-9]+]]=, $0{{$}} 11; CHECK-NEXT: return $pop[[NUM]]{{$}} 12define i32 @i32_wrap_i64(i64 %x) { 13 %a = trunc i64 %x to i32 14 ret i32 %a 15} 16 17; CHECK-LABEL: i64_extend_s_i32: 18; CHECK-NEXT: .functype i64_extend_s_i32 (i32) -> (i64){{$}} 19; CHECK-NEXT: i64.extend_i32_s $push[[NUM:[0-9]+]]=, $0{{$}} 20; CHECK-NEXT: return $pop[[NUM]]{{$}} 21define i64 @i64_extend_s_i32(i32 %x) { 22 %a = sext i32 %x to i64 23 ret i64 %a 24} 25 26; CHECK-LABEL: i64_extend_u_i32: 27; CHECK-NEXT: .functype i64_extend_u_i32 (i32) -> (i64){{$}} 28; CHECK-NEXT: i64.extend_i32_u $push[[NUM:[0-9]+]]=, $0{{$}} 29; CHECK-NEXT: return $pop[[NUM]]{{$}} 30define i64 @i64_extend_u_i32(i32 %x) { 31 %a = zext i32 %x to i64 32 ret i64 %a 33} 34 35; CHECK-LABEL: i32_trunc_s_f32: 36; CHECK-NEXT: .functype i32_trunc_s_f32 (f32) -> (i32){{$}} 37; CHECK-NEXT: i32.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}} 38; CHECK-NEXT: return $pop[[NUM]]{{$}} 39define i32 @i32_trunc_s_f32(float %x) { 40 %a = fptosi float %x to i32 41 ret i32 %a 42} 43 44; CHECK-LABEL: i32_trunc_sat_s_f32: 45; CHECK-NEXT: .functype i32_trunc_sat_s_f32 (f32) -> (i32){{$}} 46; CHECK-NEXT: i32.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}} 47; CHECK-NEXT: return $pop[[NUM]]{{$}} 48declare i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float) 49define i32 @i32_trunc_sat_s_f32(float %x) { 50 %a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %x) 51 ret i32 %a 52} 53 54; CHECK-LABEL: i32_trunc_u_f32: 55; CHECK-NEXT: .functype i32_trunc_u_f32 (f32) -> (i32){{$}} 56; CHECK-NEXT: i32.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}} 57; CHECK-NEXT: return $pop[[NUM]]{{$}} 58define i32 @i32_trunc_u_f32(float %x) { 59 %a = fptoui float %x to i32 60 ret i32 %a 61} 62 63; CHECK-LABEL: i32_trunc_sat_u_f32: 64; CHECK-NEXT: .functype i32_trunc_sat_u_f32 (f32) -> (i32){{$}} 65; CHECK-NEXT: i32.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}} 66; CHECK-NEXT: return $pop[[NUM]]{{$}} 67declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float) 68define i32 @i32_trunc_sat_u_f32(float %x) { 69 %a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %x) 70 ret i32 %a 71} 72 73; CHECK-LABEL: i32_trunc_s_f64: 74; CHECK-NEXT: .functype i32_trunc_s_f64 (f64) -> (i32){{$}} 75; CHECK-NEXT: i32.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}} 76; CHECK-NEXT: return $pop[[NUM]]{{$}} 77define i32 @i32_trunc_s_f64(double %x) { 78 %a = fptosi double %x to i32 79 ret i32 %a 80} 81 82; CHECK-LABEL: i32_trunc_sat_s_f64: 83; CHECK-NEXT: .functype i32_trunc_sat_s_f64 (f64) -> (i32){{$}} 84; CHECK-NEXT: i32.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}} 85; CHECK-NEXT: return $pop[[NUM]]{{$}} 86declare i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double) 87define i32 @i32_trunc_sat_s_f64(double %x) { 88 %a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %x) 89 ret i32 %a 90} 91 92; CHECK-LABEL: i32_trunc_u_f64: 93; CHECK-NEXT: .functype i32_trunc_u_f64 (f64) -> (i32){{$}} 94; CHECK-NEXT: i32.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}} 95; CHECK-NEXT: return $pop[[NUM]]{{$}} 96define i32 @i32_trunc_u_f64(double %x) { 97 %a = fptoui double %x to i32 98 ret i32 %a 99} 100 101; CHECK-LABEL: i32_trunc_sat_u_f64: 102; CHECK-NEXT: .functype i32_trunc_sat_u_f64 (f64) -> (i32){{$}} 103; CHECK-NEXT: i32.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}} 104; CHECK-NEXT: return $pop[[NUM]]{{$}} 105declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double) 106define i32 @i32_trunc_sat_u_f64(double %x) { 107 %a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %x) 108 ret i32 %a 109} 110 111; CHECK-LABEL: i64_trunc_s_f32: 112; CHECK-NEXT: .functype i64_trunc_s_f32 (f32) -> (i64){{$}} 113; CHECK-NEXT: i64.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}} 114; CHECK-NEXT: return $pop[[NUM]]{{$}} 115define i64 @i64_trunc_s_f32(float %x) { 116 %a = fptosi float %x to i64 117 ret i64 %a 118} 119 120; CHECK-LABEL: i64_trunc_sat_s_f32: 121; CHECK-NEXT: .functype i64_trunc_sat_s_f32 (f32) -> (i64){{$}} 122; CHECK-NEXT: i64.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}} 123; CHECK-NEXT: return $pop[[NUM]]{{$}} 124declare i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float) 125define i64 @i64_trunc_sat_s_f32(float %x) { 126 %a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %x) 127 ret i64 %a 128} 129 130; CHECK-LABEL: i64_trunc_u_f32: 131; CHECK-NEXT: .functype i64_trunc_u_f32 (f32) -> (i64){{$}} 132; CHECK-NEXT: i64.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}} 133; CHECK-NEXT: return $pop[[NUM]]{{$}} 134define i64 @i64_trunc_u_f32(float %x) { 135 %a = fptoui float %x to i64 136 ret i64 %a 137} 138 139; CHECK-LABEL: i64_trunc_sat_u_f32: 140; CHECK-NEXT: .functype i64_trunc_sat_u_f32 (f32) -> (i64){{$}} 141; CHECK-NEXT: i64.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}} 142; CHECK-NEXT: return $pop[[NUM]]{{$}} 143declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float) 144define i64 @i64_trunc_sat_u_f32(float %x) { 145 %a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %x) 146 ret i64 %a 147} 148 149; CHECK-LABEL: i64_trunc_s_f64: 150; CHECK-NEXT: .functype i64_trunc_s_f64 (f64) -> (i64){{$}} 151; CHECK-NEXT: i64.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}} 152; CHECK-NEXT: return $pop[[NUM]]{{$}} 153define i64 @i64_trunc_s_f64(double %x) { 154 %a = fptosi double %x to i64 155 ret i64 %a 156} 157 158; CHECK-LABEL: i64_trunc_sat_s_f64: 159; CHECK-NEXT: .functype i64_trunc_sat_s_f64 (f64) -> (i64){{$}} 160; CHECK-NEXT: i64.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}} 161; CHECK-NEXT: return $pop[[NUM]]{{$}} 162declare i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double) 163define i64 @i64_trunc_sat_s_f64(double %x) { 164 %a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %x) 165 ret i64 %a 166} 167 168; CHECK-LABEL: i64_trunc_u_f64: 169; CHECK-NEXT: .functype i64_trunc_u_f64 (f64) -> (i64){{$}} 170; CHECK-NEXT: i64.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}} 171; CHECK-NEXT: return $pop[[NUM]]{{$}} 172define i64 @i64_trunc_u_f64(double %x) { 173 %a = fptoui double %x to i64 174 ret i64 %a 175} 176 177; CHECK-LABEL: i64_trunc_sat_u_f64: 178; CHECK-NEXT: .functype i64_trunc_sat_u_f64 (f64) -> (i64){{$}} 179; CHECK-NEXT: i64.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}} 180; CHECK-NEXT: return $pop[[NUM]]{{$}} 181declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double) 182define i64 @i64_trunc_sat_u_f64(double %x) { 183 %a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %x) 184 ret i64 %a 185} 186 187; CHECK-LABEL: f32_convert_s_i32: 188; CHECK-NEXT: .functype f32_convert_s_i32 (i32) -> (f32){{$}} 189; CHECK-NEXT: f32.convert_i32_s $push[[NUM:[0-9]+]]=, $0{{$}} 190; CHECK-NEXT: return $pop[[NUM]]{{$}} 191define float @f32_convert_s_i32(i32 %x) { 192 %a = sitofp i32 %x to float 193 ret float %a 194} 195 196; CHECK-LABEL: f32_convert_u_i32: 197; CHECK-NEXT: .functype f32_convert_u_i32 (i32) -> (f32){{$}} 198; CHECK-NEXT: f32.convert_i32_u $push[[NUM:[0-9]+]]=, $0{{$}} 199; CHECK-NEXT: return $pop[[NUM]]{{$}} 200define float @f32_convert_u_i32(i32 %x) { 201 %a = uitofp i32 %x to float 202 ret float %a 203} 204 205; CHECK-LABEL: f64_convert_s_i32: 206; CHECK-NEXT: .functype f64_convert_s_i32 (i32) -> (f64){{$}} 207; CHECK-NEXT: f64.convert_i32_s $push[[NUM:[0-9]+]]=, $0{{$}} 208; CHECK-NEXT: return $pop[[NUM]]{{$}} 209define double @f64_convert_s_i32(i32 %x) { 210 %a = sitofp i32 %x to double 211 ret double %a 212} 213 214; CHECK-LABEL: f64_convert_u_i32: 215; CHECK-NEXT: .functype f64_convert_u_i32 (i32) -> (f64){{$}} 216; CHECK-NEXT: f64.convert_i32_u $push[[NUM:[0-9]+]]=, $0{{$}} 217; CHECK-NEXT: return $pop[[NUM]]{{$}} 218define double @f64_convert_u_i32(i32 %x) { 219 %a = uitofp i32 %x to double 220 ret double %a 221} 222 223; CHECK-LABEL: f32_convert_s_i64: 224; CHECK-NEXT: .functype f32_convert_s_i64 (i64) -> (f32){{$}} 225; CHECK-NEXT: f32.convert_i64_s $push[[NUM:[0-9]+]]=, $0{{$}} 226; CHECK-NEXT: return $pop[[NUM]]{{$}} 227define float @f32_convert_s_i64(i64 %x) { 228 %a = sitofp i64 %x to float 229 ret float %a 230} 231 232; CHECK-LABEL: f32_convert_u_i64: 233; CHECK-NEXT: .functype f32_convert_u_i64 (i64) -> (f32){{$}} 234; CHECK-NEXT: f32.convert_i64_u $push[[NUM:[0-9]+]]=, $0{{$}} 235; CHECK-NEXT: return $pop[[NUM]]{{$}} 236define float @f32_convert_u_i64(i64 %x) { 237 %a = uitofp i64 %x to float 238 ret float %a 239} 240 241; CHECK-LABEL: f64_convert_s_i64: 242; CHECK-NEXT: .functype f64_convert_s_i64 (i64) -> (f64){{$}} 243; CHECK-NEXT: f64.convert_i64_s $push[[NUM:[0-9]+]]=, $0{{$}} 244; CHECK-NEXT: return $pop[[NUM]]{{$}} 245define double @f64_convert_s_i64(i64 %x) { 246 %a = sitofp i64 %x to double 247 ret double %a 248} 249 250; CHECK-LABEL: f64_convert_u_i64: 251; CHECK-NEXT: .functype f64_convert_u_i64 (i64) -> (f64){{$}} 252; CHECK-NEXT: f64.convert_i64_u $push[[NUM:[0-9]+]]=, $0{{$}} 253; CHECK-NEXT: return $pop[[NUM]]{{$}} 254define double @f64_convert_u_i64(i64 %x) { 255 %a = uitofp i64 %x to double 256 ret double %a 257} 258 259; CHECK-LABEL: f64_promote_f32: 260; CHECK-NEXT: .functype f64_promote_f32 (f32) -> (f64){{$}} 261; CHECK-NEXT: f64.promote_f32 $push[[NUM:[0-9]+]]=, $0{{$}} 262; CHECK-NEXT: return $pop[[NUM]]{{$}} 263define double @f64_promote_f32(float %x) { 264 %a = fpext float %x to double 265 ret double %a 266} 267 268; CHECK-LABEL: f32_demote_f64: 269; CHECK-NEXT: .functype f32_demote_f64 (f64) -> (f32){{$}} 270; CHECK-NEXT: f32.demote_f64 $push[[NUM:[0-9]+]]=, $0{{$}} 271; CHECK-NEXT: return $pop[[NUM]]{{$}} 272define float @f32_demote_f64(double %x) { 273 %a = fptrunc double %x to float 274 ret float %a 275} 276 277; If the high its are unused, LLVM will optimize sext/zext into anyext, which 278; we need to patterm-match back to a specific instruction. 279 280; CHECK-LABEL: anyext: 281; CHECK: i64.extend_i32_u $push0=, $0{{$}} 282define i64 @anyext(i32 %x) { 283 %y = sext i32 %x to i64 284 %w = shl i64 %y, 32 285 ret i64 %w 286} 287 288; CHECK-LABEL: bitcast_i32_to_float: 289; CHECK: f32.reinterpret_i32 $push0=, $0{{$}} 290define float @bitcast_i32_to_float(i32 %a) { 291 %t = bitcast i32 %a to float 292 ret float %t 293} 294 295; CHECK-LABEL: bitcast_float_to_i32: 296; CHECK: i32.reinterpret_f32 $push0=, $0{{$}} 297define i32 @bitcast_float_to_i32(float %a) { 298 %t = bitcast float %a to i32 299 ret i32 %t 300} 301 302; CHECK-LABEL: bitcast_i64_to_double: 303; CHECK: f64.reinterpret_i64 $push0=, $0{{$}} 304define double @bitcast_i64_to_double(i64 %a) { 305 %t = bitcast i64 %a to double 306 ret double %t 307} 308 309; CHECK-LABEL: bitcast_double_to_i64: 310; CHECK: i64.reinterpret_f64 $push0=, $0{{$}} 311define i64 @bitcast_double_to_i64(double %a) { 312 %t = bitcast double %a to i64 313 ret i64 %t 314} 315