1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s 2 3; Test that basic 32-bit floating-point comparison operations assemble as 4; expected. 5 6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 7target triple = "wasm32-unknown-unknown" 8 9; CHECK-LABEL: ord_f32: 10; CHECK-NEXT: .functype ord_f32 (f32, f32) -> (i32){{$}} 11; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 12; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 0{{$}} 13; CHECK-NEXT: f32.eq $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 14; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 1{{$}} 15; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1{{$}} 16; CHECK-NEXT: f32.eq $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} 17; CHECK-NEXT: i32.and $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}} 18; CHECK-NEXT: return $pop[[NUM2]]{{$}} 19define i32 @ord_f32(float %x, float %y) { 20 %a = fcmp ord float %x, %y 21 %b = zext i1 %a to i32 22 ret i32 %b 23} 24 25; CHECK-LABEL: uno_f32: 26; CHECK-NEXT: .functype uno_f32 (f32, f32) -> (i32){{$}} 27; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 28; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 0{{$}} 29; CHECK-NEXT: f32.ne $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 30; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 1{{$}} 31; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1{{$}} 32; CHECK-NEXT: f32.ne $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} 33; CHECK-NEXT: i32.or $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM1]]{{$}} 34; CHECK-NEXT: return $pop[[NUM2]]{{$}} 35define i32 @uno_f32(float %x, float %y) { 36 %a = fcmp uno float %x, %y 37 %b = zext i1 %a to i32 38 ret i32 %b 39} 40 41; CHECK-LABEL: oeq_f32: 42; CHECK-NEXT: .functype oeq_f32 (f32, f32) -> (i32){{$}} 43; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 44; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 45; CHECK-NEXT: f32.eq $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 46; CHECK-NEXT: return $pop[[NUM]]{{$}} 47define i32 @oeq_f32(float %x, float %y) { 48 %a = fcmp oeq float %x, %y 49 %b = zext i1 %a to i32 50 ret i32 %b 51} 52 53; CHECK-LABEL: une_f32: 54; CHECK: f32.ne $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 55; CHECK-NEXT: return $pop[[NUM]]{{$}} 56define i32 @une_f32(float %x, float %y) { 57 %a = fcmp une float %x, %y 58 %b = zext i1 %a to i32 59 ret i32 %b 60} 61 62; CHECK-LABEL: olt_f32: 63; CHECK: f32.lt $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 64; CHECK-NEXT: return $pop[[NUM]]{{$}} 65define i32 @olt_f32(float %x, float %y) { 66 %a = fcmp olt float %x, %y 67 %b = zext i1 %a to i32 68 ret i32 %b 69} 70 71; CHECK-LABEL: ole_f32: 72; CHECK: f32.le $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 73; CHECK-NEXT: return $pop[[NUM]]{{$}} 74define i32 @ole_f32(float %x, float %y) { 75 %a = fcmp ole float %x, %y 76 %b = zext i1 %a to i32 77 ret i32 %b 78} 79 80; CHECK-LABEL: ogt_f32: 81; CHECK: f32.gt $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 82; CHECK-NEXT: return $pop[[NUM]]{{$}} 83define i32 @ogt_f32(float %x, float %y) { 84 %a = fcmp ogt float %x, %y 85 %b = zext i1 %a to i32 86 ret i32 %b 87} 88 89; CHECK-LABEL: oge_f32: 90; CHECK: f32.ge $push[[NUM:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 91; CHECK-NEXT: return $pop[[NUM]]{{$}} 92define i32 @oge_f32(float %x, float %y) { 93 %a = fcmp oge float %x, %y 94 %b = zext i1 %a to i32 95 ret i32 %b 96} 97 98; Expanded comparisons, which also check for NaN. 99; These simply rely on SDAG's Expand cond code action. 100 101; CHECK-LABEL: ueq_f32: 102; CHECK-NEXT: .functype ueq_f32 (f32, f32) -> (i32){{$}} 103; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 104; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 105; CHECK-NEXT: f32.eq $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 106; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 0{{$}} 107; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 0{{$}} 108; CHECK-NEXT: f32.ne $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} 109; CHECK-NEXT: local.get $push[[L4:[0-9]+]]=, 1{{$}} 110; CHECK-NEXT: local.get $push[[L5:[0-9]+]]=, 1{{$}} 111; CHECK-NEXT: f32.ne $push[[NUM2:[0-9]+]]=, $pop[[L4]], $pop[[L5]]{{$}} 112; CHECK-NEXT: i32.or $push[[NUM3:[0-9]+]]=, $pop[[NUM1]], $pop[[NUM2]]{{$}} 113; CHECK-NEXT: i32.or $push[[NUM4:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM3]]{{$}} 114; CHECK-NEXT: return $pop[[NUM4]]{{$}} 115define i32 @ueq_f32(float %x, float %y) { 116 %a = fcmp ueq float %x, %y 117 %b = zext i1 %a to i32 118 ret i32 %b 119} 120 121; CHECK-LABEL: one_f32: 122; CHECK-NEXT: .functype one_f32 (f32, f32) -> (i32){{$}} 123; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 124; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 125; CHECK-NEXT: f32.ne $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 126; CHECK-NEXT: local.get $push[[L2:[0-9]+]]=, 0{{$}} 127; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 0{{$}} 128; CHECK-NEXT: f32.eq $push[[NUM1:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} 129; CHECK-NEXT: local.get $push[[L4:[0-9]+]]=, 1{{$}} 130; CHECK-NEXT: local.get $push[[L5:[0-9]+]]=, 1{{$}} 131; CHECK-NEXT: f32.eq $push[[NUM2:[0-9]+]]=, $pop[[L4]], $pop[[L5]]{{$}} 132; CHECK-NEXT: i32.and $push[[NUM3:[0-9]+]]=, $pop[[NUM1]], $pop[[NUM2]]{{$}} 133; CHECK-NEXT: i32.and $push[[NUM4:[0-9]+]]=, $pop[[NUM0]], $pop[[NUM3]]{{$}} 134; CHECK-NEXT: return $pop[[NUM4]] 135define i32 @one_f32(float %x, float %y) { 136 %a = fcmp one float %x, %y 137 %b = zext i1 %a to i32 138 ret i32 %b 139} 140 141; CHECK-LABEL: ult_f32: 142; CHECK-NEXT: .functype ult_f32 (f32, f32) -> (i32){{$}} 143; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 144; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 145; CHECK-NEXT: f32.ge $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 146; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1 147; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}} 148; CHECK-NEXT: return $pop[[NUM2]]{{$}} 149define i32 @ult_f32(float %x, float %y) { 150 %a = fcmp ult float %x, %y 151 %b = zext i1 %a to i32 152 ret i32 %b 153} 154 155; CHECK-LABEL: ule_f32: 156; CHECK-NEXT: .functype ule_f32 (f32, f32) -> (i32){{$}} 157; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 158; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 159; CHECK-NEXT: f32.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 160; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1 161; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}} 162; CHECK-NEXT: return $pop[[NUM2]]{{$}} 163define i32 @ule_f32(float %x, float %y) { 164 %a = fcmp ule float %x, %y 165 %b = zext i1 %a to i32 166 ret i32 %b 167} 168 169; CHECK-LABEL: ugt_f32: 170; CHECK-NEXT: .functype ugt_f32 (f32, f32) -> (i32){{$}} 171; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 172; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 173; CHECK-NEXT: f32.le $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 174; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1 175; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}} 176; CHECK-NEXT: return $pop[[NUM2]]{{$}} 177define i32 @ugt_f32(float %x, float %y) { 178 %a = fcmp ugt float %x, %y 179 %b = zext i1 %a to i32 180 ret i32 %b 181} 182 183; CHECK-LABEL: uge_f32: 184; CHECK-NEXT: .functype uge_f32 (f32, f32) -> (i32){{$}} 185; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0{{$}} 186; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1{{$}} 187; CHECK-NEXT: f32.lt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} 188; CHECK-NEXT: i32.const $push[[C0:[0-9]+]]=, 1 189; CHECK-NEXT: i32.xor $push[[NUM2:[0-9]+]]=, $pop[[NUM0]], $pop[[C0]]{{$}} 190; CHECK-NEXT: return $pop[[NUM2]]{{$}} 191define i32 @uge_f32(float %x, float %y) { 192 %a = fcmp uge float %x, %y 193 %b = zext i1 %a to i32 194 ret i32 %b 195} 196