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