353 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s3 4; Test a subset of compiler-rt/libm libcalls expected to be emitted by the wasm backend5 6target triple = "wasm64-unknown-unknown"7 8declare fp128 @llvm.sqrt.f128(fp128)9declare fp128 @llvm.floor.f128(fp128)10declare fp128 @llvm.trunc.f128(fp128)11declare fp128 @llvm.nearbyint.f128(fp128)12declare fp128 @llvm.pow.f128(fp128, fp128)13declare fp128 @llvm.powi.f128.i32(fp128, i32)14 15declare double @llvm.tan.f64(double)16declare double @llvm.cos.f64(double)17declare double @llvm.log10.f64(double)18declare double @llvm.pow.f64(double, double)19declare double @llvm.powi.f64.i32(double, i32)20declare double @llvm.log.f64(double)21declare double @llvm.exp.f64(double)22declare double @llvm.exp10.f64(double)23declare double @llvm.ldexp.f64.i32(double, i32)24declare {double, i32} @llvm.frexp.f64.i32(double)25declare i32 @llvm.lround(double)26declare {double, double} @llvm.modf.f64(double)27 28declare void @escape_value(i32)29 30define fp128 @fp128libcalls(fp128 %x, fp128 %y, i32 %z) {31 ; compiler-rt call32; CHECK-LABEL: fp128libcalls:33; CHECK: .functype fp128libcalls (i64, i64, i64, i64, i64, i32) -> ()34; CHECK-NEXT: .local i6435; CHECK-NEXT: # %bb.0:36; CHECK-NEXT: global.get $push18=, __stack_pointer37; CHECK-NEXT: i64.const $push19=, 14438; CHECK-NEXT: i64.sub $push39=, $pop18, $pop1939; CHECK-NEXT: local.tee $push38=, 6, $pop3940; CHECK-NEXT: global.set __stack_pointer, $pop3841; CHECK-NEXT: local.get $push40=, 642; CHECK-NEXT: i64.const $push36=, 12843; CHECK-NEXT: i64.add $push37=, $pop40, $pop3644; CHECK-NEXT: local.get $push44=, 145; CHECK-NEXT: local.get $push43=, 246; CHECK-NEXT: local.get $push42=, 347; CHECK-NEXT: local.get $push41=, 448; CHECK-NEXT: call __addtf3, $pop37, $pop44, $pop43, $pop42, $pop4149; CHECK-NEXT: local.get $push45=, 650; CHECK-NEXT: i64.const $push34=, 11251; CHECK-NEXT: i64.add $push35=, $pop45, $pop3452; CHECK-NEXT: local.get $push46=, 653; CHECK-NEXT: i64.load $push1=, 128($pop46)54; CHECK-NEXT: local.get $push47=, 655; CHECK-NEXT: i64.load $push0=, 136($pop47)56; CHECK-NEXT: local.get $push49=, 357; CHECK-NEXT: local.get $push48=, 458; CHECK-NEXT: call __multf3, $pop35, $pop1, $pop0, $pop49, $pop4859; CHECK-NEXT: local.get $push50=, 660; CHECK-NEXT: i64.const $push32=, 9661; CHECK-NEXT: i64.add $push33=, $pop50, $pop3262; CHECK-NEXT: local.get $push51=, 663; CHECK-NEXT: i64.load $push3=, 112($pop51)64; CHECK-NEXT: local.get $push52=, 665; CHECK-NEXT: i64.load $push2=, 120($pop52)66; CHECK-NEXT: local.get $push54=, 367; CHECK-NEXT: local.get $push53=, 468; CHECK-NEXT: call __divtf3, $pop33, $pop3, $pop2, $pop54, $pop5369; CHECK-NEXT: local.get $push55=, 670; CHECK-NEXT: i64.const $push30=, 8071; CHECK-NEXT: i64.add $push31=, $pop55, $pop3072; CHECK-NEXT: local.get $push56=, 673; CHECK-NEXT: i64.load $push5=, 96($pop56)74; CHECK-NEXT: local.get $push57=, 675; CHECK-NEXT: i64.load $push4=, 104($pop57)76; CHECK-NEXT: call sqrtl, $pop31, $pop5, $pop477; CHECK-NEXT: local.get $push58=, 678; CHECK-NEXT: i64.const $push28=, 6479; CHECK-NEXT: i64.add $push29=, $pop58, $pop2880; CHECK-NEXT: local.get $push59=, 681; CHECK-NEXT: i64.load $push7=, 80($pop59)82; CHECK-NEXT: local.get $push60=, 683; CHECK-NEXT: i64.load $push6=, 88($pop60)84; CHECK-NEXT: call floorl, $pop29, $pop7, $pop685; CHECK-NEXT: local.get $push61=, 686; CHECK-NEXT: i64.const $push26=, 4887; CHECK-NEXT: i64.add $push27=, $pop61, $pop2688; CHECK-NEXT: local.get $push62=, 689; CHECK-NEXT: i64.load $push9=, 64($pop62)90; CHECK-NEXT: local.get $push63=, 691; CHECK-NEXT: i64.load $push8=, 72($pop63)92; CHECK-NEXT: local.get $push65=, 393; CHECK-NEXT: local.get $push64=, 494; CHECK-NEXT: call powl, $pop27, $pop9, $pop8, $pop65, $pop6495; CHECK-NEXT: local.get $push66=, 696; CHECK-NEXT: i64.const $push24=, 3297; CHECK-NEXT: i64.add $push25=, $pop66, $pop2498; CHECK-NEXT: local.get $push67=, 699; CHECK-NEXT: i64.load $push11=, 48($pop67)100; CHECK-NEXT: local.get $push68=, 6101; CHECK-NEXT: i64.load $push10=, 56($pop68)102; CHECK-NEXT: local.get $push69=, 5103; CHECK-NEXT: call __powitf2, $pop25, $pop11, $pop10, $pop69104; CHECK-NEXT: local.get $push70=, 6105; CHECK-NEXT: i64.const $push22=, 16106; CHECK-NEXT: i64.add $push23=, $pop70, $pop22107; CHECK-NEXT: local.get $push71=, 6108; CHECK-NEXT: i64.load $push13=, 32($pop71)109; CHECK-NEXT: local.get $push72=, 6110; CHECK-NEXT: i64.load $push12=, 40($pop72)111; CHECK-NEXT: call truncl, $pop23, $pop13, $pop12112; CHECK-NEXT: local.get $push75=, 6113; CHECK-NEXT: local.get $push73=, 6114; CHECK-NEXT: i64.load $push15=, 16($pop73)115; CHECK-NEXT: local.get $push74=, 6116; CHECK-NEXT: i64.load $push14=, 24($pop74)117; CHECK-NEXT: call nearbyintl, $pop75, $pop15, $pop14118; CHECK-NEXT: local.get $push77=, 0119; CHECK-NEXT: local.get $push76=, 6120; CHECK-NEXT: i64.load $push16=, 8($pop76)121; CHECK-NEXT: i64.store 8($pop77), $pop16122; CHECK-NEXT: local.get $push79=, 0123; CHECK-NEXT: local.get $push78=, 6124; CHECK-NEXT: i64.load $push17=, 0($pop78)125; CHECK-NEXT: i64.store 0($pop79), $pop17126; CHECK-NEXT: local.get $push80=, 6127; CHECK-NEXT: i64.const $push20=, 144128; CHECK-NEXT: i64.add $push21=, $pop80, $pop20129; CHECK-NEXT: global.set __stack_pointer, $pop21130; CHECK-NEXT: return131 %a = fadd fp128 %x, %y132 %b = fmul fp128 %a, %y133 %c = fdiv fp128 %b, %y134 ; libm calls135 %d = call fp128 @llvm.sqrt.f128(fp128 %c)136 %e = call fp128 @llvm.floor.f128(fp128 %d)137 %f = call fp128 @llvm.pow.f128(fp128 %e, fp128 %y)138 %g = call fp128 @llvm.powi.f128.i32(fp128 %f, i32 %z)139 %h = call fp128 @llvm.trunc.f128(fp128 %g)140 %i = call fp128 @llvm.nearbyint.f128(fp128 %h)141 ret fp128 %i142}143 144define i128 @i128libcalls(i128 %x, i128 %y) {145 ; Basic ops should be expanded146; CHECK-LABEL: i128libcalls:147; CHECK: .functype i128libcalls (i64, i64, i64, i64, i64) -> ()148; CHECK-NEXT: .local i64, i64149; CHECK-NEXT: # %bb.0:150; CHECK-NEXT: global.get $push8=, __stack_pointer151; CHECK-NEXT: i64.const $push9=, 32152; CHECK-NEXT: i64.sub $push17=, $pop8, $pop9153; CHECK-NEXT: local.tee $push16=, 5, $pop17154; CHECK-NEXT: global.set __stack_pointer, $pop16155; CHECK-NEXT: local.get $push18=, 5156; CHECK-NEXT: i64.const $push12=, 16157; CHECK-NEXT: i64.add $push13=, $pop18, $pop12158; CHECK-NEXT: local.get $push20=, 1159; CHECK-NEXT: local.get $push19=, 3160; CHECK-NEXT: i64.add $push15=, $pop20, $pop19161; CHECK-NEXT: local.tee $push14=, 6, $pop15162; CHECK-NEXT: local.get $push22=, 2163; CHECK-NEXT: local.get $push21=, 4164; CHECK-NEXT: i64.add $push0=, $pop22, $pop21165; CHECK-NEXT: local.get $push24=, 6166; CHECK-NEXT: local.get $push23=, 1167; CHECK-NEXT: i64.lt_u $push1=, $pop24, $pop23168; CHECK-NEXT: i64.extend_i32_u $push2=, $pop1169; CHECK-NEXT: i64.add $push3=, $pop0, $pop2170; CHECK-NEXT: local.get $push26=, 3171; CHECK-NEXT: local.get $push25=, 4172; CHECK-NEXT: call __multi3, $pop13, $pop14, $pop3, $pop26, $pop25173; CHECK-NEXT: local.get $push31=, 5174; CHECK-NEXT: local.get $push27=, 5175; CHECK-NEXT: i64.load $push5=, 16($pop27)176; CHECK-NEXT: local.get $push28=, 5177; CHECK-NEXT: i64.load $push4=, 24($pop28)178; CHECK-NEXT: local.get $push30=, 3179; CHECK-NEXT: local.get $push29=, 4180; CHECK-NEXT: call __umodti3, $pop31, $pop5, $pop4, $pop30, $pop29181; CHECK-NEXT: local.get $push33=, 0182; CHECK-NEXT: local.get $push32=, 5183; CHECK-NEXT: i64.load $push6=, 8($pop32)184; CHECK-NEXT: i64.store 8($pop33), $pop6185; CHECK-NEXT: local.get $push35=, 0186; CHECK-NEXT: local.get $push34=, 5187; CHECK-NEXT: i64.load $push7=, 0($pop34)188; CHECK-NEXT: i64.store 0($pop35), $pop7189; CHECK-NEXT: local.get $push36=, 5190; CHECK-NEXT: i64.const $push10=, 32191; CHECK-NEXT: i64.add $push11=, $pop36, $pop10192; CHECK-NEXT: global.set __stack_pointer, $pop11193; CHECK-NEXT: return194 %a = add i128 %x, %y195 %b = mul i128 %a, %y196 %c = urem i128 %b, %y197 ret i128 %c198}199 200define double @f64libcalls(double %x, double %y, i32 %z) {201; CHECK-LABEL: f64libcalls:202; CHECK: .functype f64libcalls (f64, f64, i32) -> (f64)203; CHECK-NEXT: .local i64204; CHECK-NEXT: # %bb.0:205; CHECK-NEXT: global.get $push12=, __stack_pointer206; CHECK-NEXT: i64.const $push13=, 16207; CHECK-NEXT: i64.sub $push21=, $pop12, $pop13208; CHECK-NEXT: local.tee $push20=, 3, $pop21209; CHECK-NEXT: global.set __stack_pointer, $pop20210; CHECK-NEXT: local.get $push25=, 0211; CHECK-NEXT: local.get $push22=, 0212; CHECK-NEXT: call $push0=, tan, $pop22213; CHECK-NEXT: call $push1=, cos, $pop0214; CHECK-NEXT: call $push2=, log10, $pop1215; CHECK-NEXT: local.get $push23=, 1216; CHECK-NEXT: call $push3=, pow, $pop2, $pop23217; CHECK-NEXT: local.get $push24=, 2218; CHECK-NEXT: call $push4=, __powidf2, $pop3, $pop24219; CHECK-NEXT: call $push5=, log, $pop4220; CHECK-NEXT: call $push6=, exp, $pop5221; CHECK-NEXT: call $push7=, exp10, $pop6222; CHECK-NEXT: call $push8=, cbrt, $pop7223; CHECK-NEXT: call $push9=, lround, $pop8224; CHECK-NEXT: call $push10=, ldexp, $pop25, $pop9225; CHECK-NEXT: local.get $push26=, 3226; CHECK-NEXT: i64.const $push18=, 4227; CHECK-NEXT: i64.add $push19=, $pop26, $pop18228; CHECK-NEXT: call $push27=, frexp, $pop10, $pop19229; CHECK-NEXT: local.set 0, $pop27230; CHECK-NEXT: local.get $push28=, 3231; CHECK-NEXT: i32.load $push11=, 4($pop28)232; CHECK-NEXT: call escape_value, $pop11233; CHECK-NEXT: local.get $push31=, 0234; CHECK-NEXT: local.get $push29=, 3235; CHECK-NEXT: i64.const $push16=, 8236; CHECK-NEXT: i64.add $push17=, $pop29, $pop16237; CHECK-NEXT: call $push30=, modf, $pop31, $pop17238; CHECK-NEXT: local.set 0, $pop30239; CHECK-NEXT: local.get $push32=, 3240; CHECK-NEXT: i64.const $push14=, 16241; CHECK-NEXT: i64.add $push15=, $pop32, $pop14242; CHECK-NEXT: global.set __stack_pointer, $pop15243; CHECK-NEXT: local.get $push33=, 0244; CHECK-NEXT: return $pop33245 246 247 %k = call double @llvm.tan.f64(double %x)248 %a = call double @llvm.cos.f64(double %k)249 %b = call double @llvm.log10.f64(double %a)250 %c = call double @llvm.pow.f64(double %b, double %y)251 %d = call double @llvm.powi.f64.i32(double %c, i32 %z)252 %e = call double @llvm.log.f64(double %d)253 %f = call double @llvm.exp.f64(double %e)254 %g = call double @llvm.exp10.f64(double %f)255 %h = call fast double @llvm.pow.f64(double %g, double 0x3FD5555555555555)256 %i = call i32 @llvm.lround(double %h)257 %j = call double @llvm.ldexp.f64.i32(double %x, i32 %i);258 %result = call {double, i32} @llvm.frexp.f64.i32(double %j)259 %result.0 = extractvalue { double, i32 } %result, 0260 %result.1 = extractvalue { double, i32 } %result, 1261 %resultModf = call {double, double} @llvm.modf.f64(double %result.0)262 %resultModf.0 = extractvalue { double, double } %resultModf, 0263 call void @escape_value(i32 %result.1)264 ret double %resultModf.0265}266 267; fcmp ord and unord (RTLIB::O_F32 / RTLIB::UO_F32 etc) are a special case (see268; comment in WebAssemblyRunimeLibcallSignatures.cpp) so check them separately.269; no libcalls are needed for f32 and f64270 271define i1 @unordd(double %x, double %y) {272; CHECK-LABEL: unordd:273; CHECK: .functype unordd (f64, f64) -> (i32)274; CHECK-NEXT: # %bb.0:275; CHECK-NEXT: local.get $push8=, 0276; CHECK-NEXT: local.get $push7=, 0277; CHECK-NEXT: f64.ne $push4=, $pop8, $pop7278; CHECK-NEXT: local.get $push10=, 1279; CHECK-NEXT: local.get $push9=, 1280; CHECK-NEXT: f64.ne $push3=, $pop10, $pop9281; CHECK-NEXT: i32.or $push5=, $pop4, $pop3282; CHECK-NEXT: local.get $push12=, 0283; CHECK-NEXT: local.get $push11=, 0284; CHECK-NEXT: f64.eq $push1=, $pop12, $pop11285; CHECK-NEXT: local.get $push14=, 1286; CHECK-NEXT: local.get $push13=, 1287; CHECK-NEXT: f64.eq $push0=, $pop14, $pop13288; CHECK-NEXT: i32.and $push2=, $pop1, $pop0289; CHECK-NEXT: i32.xor $push6=, $pop5, $pop2290; CHECK-NEXT: return $pop6291 %a = fcmp uno double %x, %y292 %b = fcmp ord double %x, %y293 %c = xor i1 %a, %b294 ret i1 %c295}296 297define i1 @unordf(float %x, float %y) {298; CHECK-LABEL: unordf:299; CHECK: .functype unordf (f32, f32) -> (i32)300; CHECK-NEXT: # %bb.0:301; CHECK-NEXT: local.get $push8=, 0302; CHECK-NEXT: local.get $push7=, 0303; CHECK-NEXT: f32.ne $push4=, $pop8, $pop7304; CHECK-NEXT: local.get $push10=, 1305; CHECK-NEXT: local.get $push9=, 1306; CHECK-NEXT: f32.ne $push3=, $pop10, $pop9307; CHECK-NEXT: i32.or $push5=, $pop4, $pop3308; CHECK-NEXT: local.get $push12=, 0309; CHECK-NEXT: local.get $push11=, 0310; CHECK-NEXT: f32.eq $push1=, $pop12, $pop11311; CHECK-NEXT: local.get $push14=, 1312; CHECK-NEXT: local.get $push13=, 1313; CHECK-NEXT: f32.eq $push0=, $pop14, $pop13314; CHECK-NEXT: i32.and $push2=, $pop1, $pop0315; CHECK-NEXT: i32.xor $push6=, $pop5, $pop2316; CHECK-NEXT: return $pop6317 %a = fcmp uno float %x, %y318 %b = fcmp ord float %x, %y319 %c = xor i1 %a, %b320 ret i1 %c321}322 323define i1 @unordt(fp128 %x, fp128 %y) {324; CHECK-LABEL: unordt:325; CHECK: .functype unordt (i64, i64, i64, i64) -> (i32)326; CHECK-NEXT: # %bb.0:327; CHECK-NEXT: local.get $push6=, 0328; CHECK-NEXT: local.get $push5=, 1329; CHECK-NEXT: local.get $push4=, 2330; CHECK-NEXT: local.get $push3=, 3331; CHECK-NEXT: call $push1=, __unordtf2, $pop6, $pop5, $pop4, $pop3332; CHECK-NEXT: i32.const $push0=, 0333; CHECK-NEXT: i32.ne $push2=, $pop1, $pop0334; CHECK-NEXT: return $pop2335 %a = fcmp uno fp128 %x, %y336 ret i1 %a337}338 339define i1 @ordt(fp128 %x, fp128 %y) {340; CHECK-LABEL: ordt:341; CHECK: .functype ordt (i64, i64, i64, i64) -> (i32)342; CHECK-NEXT: # %bb.0:343; CHECK-NEXT: local.get $push5=, 0344; CHECK-NEXT: local.get $push4=, 1345; CHECK-NEXT: local.get $push3=, 2346; CHECK-NEXT: local.get $push2=, 3347; CHECK-NEXT: call $push0=, __unordtf2, $pop5, $pop4, $pop3, $pop2348; CHECK-NEXT: i32.eqz $push1=, $pop0349; CHECK-NEXT: return $pop1350 %a = fcmp ord fp128 %x, %y351 ret i1 %a352}353