493 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 that basic 64-bit floating-point comparison operations assemble as5; expected.6 7target triple = "wasm32-unknown-unknown"8 9define i32 @ord_f64(double %x, double %y) {10; CHECK-LABEL: ord_f64:11; CHECK: .functype ord_f64 (f64, f64) -> (i32)12; CHECK-NEXT: # %bb.0:13; CHECK-NEXT: local.get $push4=, 014; CHECK-NEXT: local.get $push3=, 015; CHECK-NEXT: f64.eq $push1=, $pop4, $pop316; CHECK-NEXT: local.get $push6=, 117; CHECK-NEXT: local.get $push5=, 118; CHECK-NEXT: f64.eq $push0=, $pop6, $pop519; CHECK-NEXT: i32.and $push2=, $pop1, $pop020; CHECK-NEXT: return $pop221 %a = fcmp ord double %x, %y22 %b = zext i1 %a to i3223 ret i32 %b24}25 26define i32 @uno_f64(double %x, double %y) {27; CHECK-LABEL: uno_f64:28; CHECK: .functype uno_f64 (f64, f64) -> (i32)29; CHECK-NEXT: # %bb.0:30; CHECK-NEXT: local.get $push4=, 031; CHECK-NEXT: local.get $push3=, 032; CHECK-NEXT: f64.ne $push1=, $pop4, $pop333; CHECK-NEXT: local.get $push6=, 134; CHECK-NEXT: local.get $push5=, 135; CHECK-NEXT: f64.ne $push0=, $pop6, $pop536; CHECK-NEXT: i32.or $push2=, $pop1, $pop037; CHECK-NEXT: return $pop238 %a = fcmp uno double %x, %y39 %b = zext i1 %a to i3240 ret i32 %b41}42 43define i32 @oeq_f64(double %x, double %y) {44; CHECK-LABEL: oeq_f64:45; CHECK: .functype oeq_f64 (f64, f64) -> (i32)46; CHECK-NEXT: # %bb.0:47; CHECK-NEXT: local.get $push2=, 048; CHECK-NEXT: local.get $push1=, 149; CHECK-NEXT: f64.eq $push0=, $pop2, $pop150; CHECK-NEXT: return $pop051 %a = fcmp oeq double %x, %y52 %b = zext i1 %a to i3253 ret i32 %b54}55 56define i32 @une_f64(double %x, double %y) {57; CHECK-LABEL: une_f64:58; CHECK: .functype une_f64 (f64, f64) -> (i32)59; CHECK-NEXT: # %bb.0:60; CHECK-NEXT: local.get $push2=, 061; CHECK-NEXT: local.get $push1=, 162; CHECK-NEXT: f64.ne $push0=, $pop2, $pop163; CHECK-NEXT: return $pop064 %a = fcmp une double %x, %y65 %b = zext i1 %a to i3266 ret i32 %b67}68 69define i32 @olt_f64(double %x, double %y) {70; CHECK-LABEL: olt_f64:71; CHECK: .functype olt_f64 (f64, f64) -> (i32)72; CHECK-NEXT: # %bb.0:73; CHECK-NEXT: local.get $push2=, 074; CHECK-NEXT: local.get $push1=, 175; CHECK-NEXT: f64.lt $push0=, $pop2, $pop176; CHECK-NEXT: return $pop077 %a = fcmp olt double %x, %y78 %b = zext i1 %a to i3279 ret i32 %b80}81 82define i32 @ole_f64(double %x, double %y) {83; CHECK-LABEL: ole_f64:84; CHECK: .functype ole_f64 (f64, f64) -> (i32)85; CHECK-NEXT: # %bb.0:86; CHECK-NEXT: local.get $push2=, 087; CHECK-NEXT: local.get $push1=, 188; CHECK-NEXT: f64.le $push0=, $pop2, $pop189; CHECK-NEXT: return $pop090 %a = fcmp ole double %x, %y91 %b = zext i1 %a to i3292 ret i32 %b93}94 95define i32 @ogt_f64(double %x, double %y) {96; CHECK-LABEL: ogt_f64:97; CHECK: .functype ogt_f64 (f64, f64) -> (i32)98; CHECK-NEXT: # %bb.0:99; CHECK-NEXT: local.get $push2=, 0100; CHECK-NEXT: local.get $push1=, 1101; CHECK-NEXT: f64.gt $push0=, $pop2, $pop1102; CHECK-NEXT: return $pop0103 %a = fcmp ogt double %x, %y104 %b = zext i1 %a to i32105 ret i32 %b106}107 108define i32 @oge_f64(double %x, double %y) {109; CHECK-LABEL: oge_f64:110; CHECK: .functype oge_f64 (f64, f64) -> (i32)111; CHECK-NEXT: # %bb.0:112; CHECK-NEXT: local.get $push2=, 0113; CHECK-NEXT: local.get $push1=, 1114; CHECK-NEXT: f64.ge $push0=, $pop2, $pop1115; CHECK-NEXT: return $pop0116 %a = fcmp oge double %x, %y117 %b = zext i1 %a to i32118 ret i32 %b119}120 121; Expanded comparisons, which also check for NaN.122 123define i32 @ueq_f64(double %x, double %y) {124; CHECK-LABEL: ueq_f64:125; CHECK: .functype ueq_f64 (f64, f64) -> (i32)126; CHECK-NEXT: # %bb.0:127; CHECK-NEXT: local.get $push6=, 0128; CHECK-NEXT: local.get $push5=, 1129; CHECK-NEXT: f64.gt $push1=, $pop6, $pop5130; CHECK-NEXT: local.get $push8=, 0131; CHECK-NEXT: local.get $push7=, 1132; CHECK-NEXT: f64.lt $push0=, $pop8, $pop7133; CHECK-NEXT: i32.or $push2=, $pop1, $pop0134; CHECK-NEXT: i32.const $push3=, 1135; CHECK-NEXT: i32.xor $push4=, $pop2, $pop3136; CHECK-NEXT: return $pop4137 %a = fcmp ueq double %x, %y138 %b = zext i1 %a to i32139 ret i32 %b140}141 142define i32 @one_f64(double %x, double %y) {143; CHECK-LABEL: one_f64:144; CHECK: .functype one_f64 (f64, f64) -> (i32)145; CHECK-NEXT: # %bb.0:146; CHECK-NEXT: local.get $push4=, 0147; CHECK-NEXT: local.get $push3=, 1148; CHECK-NEXT: f64.gt $push1=, $pop4, $pop3149; CHECK-NEXT: local.get $push6=, 0150; CHECK-NEXT: local.get $push5=, 1151; CHECK-NEXT: f64.lt $push0=, $pop6, $pop5152; CHECK-NEXT: i32.or $push2=, $pop1, $pop0153; CHECK-NEXT: return $pop2154 %a = fcmp one double %x, %y155 %b = zext i1 %a to i32156 ret i32 %b157}158 159define i32 @ult_f64(double %x, double %y) {160; CHECK-LABEL: ult_f64:161; CHECK: .functype ult_f64 (f64, f64) -> (i32)162; CHECK-NEXT: # %bb.0:163; CHECK-NEXT: local.get $push4=, 0164; CHECK-NEXT: local.get $push3=, 1165; CHECK-NEXT: f64.ge $push0=, $pop4, $pop3166; CHECK-NEXT: i32.const $push1=, 1167; CHECK-NEXT: i32.xor $push2=, $pop0, $pop1168; CHECK-NEXT: return $pop2169 %a = fcmp ult double %x, %y170 %b = zext i1 %a to i32171 ret i32 %b172}173 174define i32 @ule_f64(double %x, double %y) {175; CHECK-LABEL: ule_f64:176; CHECK: .functype ule_f64 (f64, f64) -> (i32)177; CHECK-NEXT: # %bb.0:178; CHECK-NEXT: local.get $push4=, 0179; CHECK-NEXT: local.get $push3=, 1180; CHECK-NEXT: f64.gt $push0=, $pop4, $pop3181; CHECK-NEXT: i32.const $push1=, 1182; CHECK-NEXT: i32.xor $push2=, $pop0, $pop1183; CHECK-NEXT: return $pop2184 %a = fcmp ule double %x, %y185 %b = zext i1 %a to i32186 ret i32 %b187}188 189define i32 @ugt_f64(double %x, double %y) {190; CHECK-LABEL: ugt_f64:191; CHECK: .functype ugt_f64 (f64, f64) -> (i32)192; CHECK-NEXT: # %bb.0:193; CHECK-NEXT: local.get $push4=, 0194; CHECK-NEXT: local.get $push3=, 1195; CHECK-NEXT: f64.le $push0=, $pop4, $pop3196; CHECK-NEXT: i32.const $push1=, 1197; CHECK-NEXT: i32.xor $push2=, $pop0, $pop1198; CHECK-NEXT: return $pop2199 %a = fcmp ugt double %x, %y200 %b = zext i1 %a to i32201 ret i32 %b202}203 204define i32 @uge_f64(double %x, double %y) {205; CHECK-LABEL: uge_f64:206; CHECK: .functype uge_f64 (f64, f64) -> (i32)207; CHECK-NEXT: # %bb.0:208; CHECK-NEXT: local.get $push4=, 0209; CHECK-NEXT: local.get $push3=, 1210; CHECK-NEXT: f64.lt $push0=, $pop4, $pop3211; CHECK-NEXT: i32.const $push1=, 1212; CHECK-NEXT: i32.xor $push2=, $pop0, $pop1213; CHECK-NEXT: return $pop2214 %a = fcmp uge double %x, %y215 %b = zext i1 %a to i32216 ret i32 %b217}218 219define void @olt_f64_branch(double %a, double %b) {220; CHECK-LABEL: olt_f64_branch:221; CHECK: .functype olt_f64_branch (f64, f64) -> ()222; CHECK-NEXT: # %bb.0: # %entry223; CHECK-NEXT: block224; CHECK-NEXT: local.get $push2=, 0225; CHECK-NEXT: local.get $push1=, 1226; CHECK-NEXT: f64.lt $push0=, $pop2, $pop1227; CHECK-NEXT: i32.eqz $push3=, $pop0228; CHECK-NEXT: br_if 0, $pop3 # 0: down to label0229; CHECK-NEXT: # %bb.1: # %if.then230; CHECK-NEXT: call call1231; CHECK-NEXT: .LBB14_2: # %if.end232; CHECK-NEXT: end_block # label0:233; CHECK-NEXT: return234entry:235 %cmp = fcmp olt double %a, %b236 br i1 %cmp, label %if.then, label %if.end237 238if.then:239 tail call void @call1()240 br label %if.end241 242if.end:243 ret void244}245 246define void @ole_f64_branch(double %a, double %b) {247; CHECK-LABEL: ole_f64_branch:248; CHECK: .functype ole_f64_branch (f64, f64) -> ()249; CHECK-NEXT: # %bb.0: # %entry250; CHECK-NEXT: block251; CHECK-NEXT: local.get $push2=, 0252; CHECK-NEXT: local.get $push1=, 1253; CHECK-NEXT: f64.le $push0=, $pop2, $pop1254; CHECK-NEXT: i32.eqz $push3=, $pop0255; CHECK-NEXT: br_if 0, $pop3 # 0: down to label1256; CHECK-NEXT: # %bb.1: # %if.then257; CHECK-NEXT: call call1258; CHECK-NEXT: .LBB15_2: # %if.end259; CHECK-NEXT: end_block # label1:260; CHECK-NEXT: return261entry:262 %cmp = fcmp ole double %a, %b263 br i1 %cmp, label %if.then, label %if.end264 265if.then:266 tail call void @call1()267 br label %if.end268 269if.end:270 ret void271}272 273define void @ugt_f64_branch(double %a, double %b) {274; CHECK-LABEL: ugt_f64_branch:275; CHECK: .functype ugt_f64_branch (f64, f64) -> ()276; CHECK-NEXT: # %bb.0: # %entry277; CHECK-NEXT: block278; CHECK-NEXT: local.get $push2=, 0279; CHECK-NEXT: local.get $push1=, 1280; CHECK-NEXT: f64.le $push0=, $pop2, $pop1281; CHECK-NEXT: i32.eqz $push3=, $pop0282; CHECK-NEXT: br_if 0, $pop3 # 0: down to label2283; CHECK-NEXT: # %bb.1: # %if.then284; CHECK-NEXT: call call1285; CHECK-NEXT: .LBB16_2: # %if.end286; CHECK-NEXT: end_block # label2:287; CHECK-NEXT: return288entry:289 %cmp = fcmp ugt double %a, %b290 br i1 %cmp, label %if.end, label %if.then291 292if.then:293 tail call void @call1()294 br label %if.end295 296if.end:297 ret void298}299 300define void @ogt_f64_branch(double %a, double %b) {301; CHECK-LABEL: ogt_f64_branch:302; CHECK: .functype ogt_f64_branch (f64, f64) -> ()303; CHECK-NEXT: # %bb.0: # %entry304; CHECK-NEXT: block305; CHECK-NEXT: local.get $push2=, 0306; CHECK-NEXT: local.get $push1=, 1307; CHECK-NEXT: f64.gt $push0=, $pop2, $pop1308; CHECK-NEXT: i32.eqz $push3=, $pop0309; CHECK-NEXT: br_if 0, $pop3 # 0: down to label3310; CHECK-NEXT: # %bb.1: # %if.then311; CHECK-NEXT: call call1312; CHECK-NEXT: .LBB17_2: # %if.end313; CHECK-NEXT: end_block # label3:314; CHECK-NEXT: return315entry:316 %cmp = fcmp ogt double %a, %b317 br i1 %cmp, label %if.then, label %if.end318 319if.then:320 tail call void @call1()321 br label %if.end322 323if.end:324 ret void325}326 327define void @ult_f64_branch(double %a, double %b) {328; CHECK-LABEL: ult_f64_branch:329; CHECK: .functype ult_f64_branch (f64, f64) -> ()330; CHECK-NEXT: # %bb.0: # %entry331; CHECK-NEXT: block332; CHECK-NEXT: local.get $push2=, 0333; CHECK-NEXT: local.get $push1=, 1334; CHECK-NEXT: f64.ge $push0=, $pop2, $pop1335; CHECK-NEXT: i32.eqz $push3=, $pop0336; CHECK-NEXT: br_if 0, $pop3 # 0: down to label4337; CHECK-NEXT: # %bb.1: # %if.then338; CHECK-NEXT: call call1339; CHECK-NEXT: .LBB18_2: # %if.end340; CHECK-NEXT: end_block # label4:341; CHECK-NEXT: return342entry:343 %cmp = fcmp ult double %a, %b344 br i1 %cmp, label %if.end, label %if.then345 346if.then:347 tail call void @call1()348 br label %if.end349 350if.end:351 ret void352}353 354define void @ule_f64_branch(double %a, double %b) {355; CHECK-LABEL: ule_f64_branch:356; CHECK: .functype ule_f64_branch (f64, f64) -> ()357; CHECK-NEXT: # %bb.0: # %entry358; CHECK-NEXT: block359; CHECK-NEXT: local.get $push2=, 0360; CHECK-NEXT: local.get $push1=, 1361; CHECK-NEXT: f64.gt $push0=, $pop2, $pop1362; CHECK-NEXT: i32.eqz $push3=, $pop0363; CHECK-NEXT: br_if 0, $pop3 # 0: down to label5364; CHECK-NEXT: # %bb.1: # %if.then365; CHECK-NEXT: call call1366; CHECK-NEXT: .LBB19_2: # %if.end367; CHECK-NEXT: end_block # label5:368; CHECK-NEXT: return369entry:370 %cmp = fcmp ule double %a, %b371 br i1 %cmp, label %if.end, label %if.then372 373if.then:374 tail call void @call1()375 br label %if.end376 377if.end:378 ret void379}380 381define void @xor_zext_switch(double %a, double %b) {382; CHECK-LABEL: xor_zext_switch:383; CHECK: .functype xor_zext_switch (f64, f64) -> ()384; CHECK-NEXT: # %bb.0: # %entry385; CHECK-NEXT: block386; CHECK-NEXT: i32.const $push1=, 0387; CHECK-NEXT: br_if 0, $pop1 # 0: down to label6388; CHECK-NEXT: # %bb.1: # %entry389; CHECK-NEXT: block390; CHECK-NEXT: block391; CHECK-NEXT: local.get $push3=, 0392; CHECK-NEXT: local.get $push2=, 1393; CHECK-NEXT: f64.ge $push0=, $pop3, $pop2394; CHECK-NEXT: br_table $pop0, 0, 1, 0 # 0: down to label8395; CHECK-NEXT: # 1: down to label7396; CHECK-NEXT: .LBB20_2: # %sw.bb.1397; CHECK-NEXT: end_block # label8:398; CHECK-NEXT: call foo1399; CHECK-NEXT: return400; CHECK-NEXT: .LBB20_3: # %sw.bb.2401; CHECK-NEXT: end_block # label7:402; CHECK-NEXT: call foo2403; CHECK-NEXT: .LBB20_4: # %exit404; CHECK-NEXT: end_block # label6:405; CHECK-NEXT: return406entry:407 %cmp = fcmp ult double %a, %b408 %zext = zext i1 %cmp to i32409 %xor = xor i32 %zext, 1410 switch i32 %xor, label %exit [411 i32 0, label %sw.bb.1412 i32 1, label %sw.bb.2413 ]414 415sw.bb.1:416 tail call void @foo1()417 br label %exit418 419sw.bb.2:420 tail call void @foo2()421 br label %exit422 423exit:424 ret void425}426 427define void @xor_add_switch(double %a, double %b) {428; CHECK-LABEL: xor_add_switch:429; CHECK: .functype xor_add_switch (f64, f64) -> ()430; CHECK-NEXT: # %bb.0: # %entry431; CHECK-NEXT: block432; CHECK-NEXT: block433; CHECK-NEXT: block434; CHECK-NEXT: block435; CHECK-NEXT: local.get $push8=, 0436; CHECK-NEXT: local.get $push7=, 1437; CHECK-NEXT: f64.ge $push1=, $pop8, $pop7438; CHECK-NEXT: i32.const $push2=, 1439; CHECK-NEXT: i32.xor $push3=, $pop1, $pop2440; CHECK-NEXT: i32.const $push6=, 1441; CHECK-NEXT: i32.add $push4=, $pop3, $pop6442; CHECK-NEXT: i32.const $push5=, 1443; CHECK-NEXT: i32.xor $push0=, $pop4, $pop5444; CHECK-NEXT: br_table $pop0, 0, 1, 2, 3 # 0: down to label12445; CHECK-NEXT: # 1: down to label11446; CHECK-NEXT: # 2: down to label10447; CHECK-NEXT: # 3: down to label9448; CHECK-NEXT: .LBB21_1: # %sw.bb.1449; CHECK-NEXT: end_block # label12:450; CHECK-NEXT: call foo1451; CHECK-NEXT: return452; CHECK-NEXT: .LBB21_2: # %sw.bb.2453; CHECK-NEXT: end_block # label11:454; CHECK-NEXT: call foo2455; CHECK-NEXT: return456; CHECK-NEXT: .LBB21_3: # %sw.bb.3457; CHECK-NEXT: end_block # label10:458; CHECK-NEXT: call foo3459; CHECK-NEXT: .LBB21_4: # %exit460; CHECK-NEXT: end_block # label9:461; CHECK-NEXT: return462entry:463 %cmp = fcmp ult double %a, %b464 %zext = zext i1 %cmp to i32465 %add = add nsw nuw i32 %zext, 1466 %xor = xor i32 %add, 1467 switch i32 %xor, label %exit [468 i32 0, label %sw.bb.1469 i32 1, label %sw.bb.2470 i32 2, label %sw.bb.3471 ]472 473sw.bb.1:474 tail call void @foo1()475 br label %exit476 477sw.bb.2:478 tail call void @foo2()479 br label %exit480 481sw.bb.3:482 tail call void @foo3()483 br label %exit484 485exit:486 ret void487}488 489declare void @foo1()490declare void @foo2()491declare void @foo3()492declare void @call1()493