Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td +++ llvm/lib/Target/WebAssembly/WebAssemblyInstrControl.td @@ -26,10 +26,16 @@ "br \t$dst", 0x0c>; } // isBranch = 1, isTerminator = 1, hasCtrlDep = 1 +def bool_node : PatLeaf<(i32 I32:$cond), [{ + return CurDAG->computeKnownBits(SDValue(N, 0)).countMinLeadingZeros() == 31; +}]>; + def : Pat<(brcond (i32 (setne I32:$cond, 0)), bb:$dst), (BR_IF bb_op:$dst, I32:$cond)>; def : Pat<(brcond (i32 (seteq I32:$cond, 0)), bb:$dst), (BR_UNLESS bb_op:$dst, I32:$cond)>; +def : Pat<(brcond (i32 (xor bool_node:$cond, (i32 1))), bb:$dst), + (BR_UNLESS bb_op:$dst, I32:$cond)>; // A list of branch targets enclosed in {} and separated by comma. // Used by br_table only. Index: llvm/test/CodeGen/WebAssembly/comparisons-f32.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/comparisons-f32.ll +++ llvm/test/CodeGen/WebAssembly/comparisons-f32.ll @@ -187,3 +187,85 @@ %b = zext i1 %a to i32 ret i32 %b } + +; CHECK-LABEL: olt_f32_branch +; CHECK: local.get $push[[L4:[0-9]+]]=, 0 +; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1 +; CHECK-NEXT: f32.lt $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]] +; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]] +; CHECK-NEXT: br_if 0, $pop[[NUM3]] +; CHECK-NEXT: call _Z5call1v +define void @olt_f32_branch(float %a, float %b) { +entry: + %cmp = fcmp olt float %a, %b + br i1 %cmp, label %if.then, label %if.end + +if.then: + tail call void @_Z5call1v() + br label %if.end + +if.end: + ret void +} + +; CHECK-LABEL: ugt_f32_branch +; CHECK: local.get $push[[L4:[0-9]+]]=, 0 +; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1 +; CHECK-NEXT: f32.le $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]] +; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]] +; CHECK-NEXT: br_if 0, $pop[[NUM3]] +; CHECK-NEXT: call _Z5call1v +define void @ugt_f32_branch(float %a, float %b) { +entry: + %cmp = fcmp ugt float %a, %b + br i1 %cmp, label %if.end, label %if.then + +if.then: + tail call void @_Z5call1v() + br label %if.end + +if.end: + ret void +} + +; CHECK-LABEL: ogt_f32_branch +; CHECK: local.get $push[[L4:[0-9]+]]=, 0 +; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1 +; CHECK-NEXT: f32.gt $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]] +; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]] +; CHECK-NEXT: br_if 0, $pop[[NUM3]] +; CHECK-NEXT: call _Z5call1v +define void @ogt_f32_branch(float %a, float %b) { +entry: + %cmp = fcmp ogt float %a, %b + br i1 %cmp, label %if.then, label %if.end + +if.then: + tail call void @_Z5call1v() + br label %if.end + +if.end: + ret void +} + +; CHECK-LABEL: ult_f32_branch +; CHECK: local.get $push[[L4:[0-9]+]]=, 0 +; CHECK-NEXT: local.get $push[[L3:[0-9]+]]=, 1 +; CHECK-NEXT: f32.ge $push[[NUM0:[0-9]+]]=, $pop[[L4]], $pop[[L3]] +; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]] +; CHECK-NEXT: br_if 0, $pop[[NUM3]] +; CHECK-NEXT: call _Z5call1v +define void @ult_f32_branch(float %a, float %b) { +entry: + %cmp = fcmp ult float %a, %b + br i1 %cmp, label %if.end, label %if.then + +if.then: + tail call void @_Z5call1v() + br label %if.end + +if.end: + ret void +} + +declare void @_Z5call1v() Index: llvm/test/CodeGen/WebAssembly/comparisons-f64.ll =================================================================== --- llvm/test/CodeGen/WebAssembly/comparisons-f64.ll +++ llvm/test/CodeGen/WebAssembly/comparisons-f64.ll @@ -186,3 +186,93 @@ %b = zext i1 %a to i32 ret i32 %b } + +; CHECK-LABEL: olt_f64_branch: +; CHECK-NEXT: .functype olt_f64_branch (f64, f64) -> () +; CHECK-NEXT: block +; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0 +; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1 +; CHECK-NEXT: f64.lt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]] +; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]] +; CHECK-NEXT: br_if 0, $pop[[NUM3]] +; CHECK-NEXT: call _Z5call1v +define void @olt_f64_branch(double %a, double %b) { +entry: + %cmp = fcmp olt double %a, %b + br i1 %cmp, label %if.then, label %if.end + +if.then: + tail call void @_Z5call1v() + br label %if.end + +if.end: + ret void +} + +; CHECK-LABEL: ugt_f64_branch: +; CHECK-NEXT: .functype ugt_f64_branch (f64, f64) -> () +; CHECK-NEXT: block +; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0 +; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1 +; CHECK-NEXT: f64.le $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]] +; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]] +; CHECK-NEXT: br_if 0, $pop[[NUM3]] +; CHECK-NEXT: call _Z5call1v +define void @ugt_f64_branch(double %a, double %b) { +entry: + %cmp = fcmp ugt double %a, %b + br i1 %cmp, label %if.end, label %if.then + +if.then: + tail call void @_Z5call1v() + br label %if.end + +if.end: + ret void +} + +; CHECK-LABEL: ogt_f64_branch: +; CHECK-NEXT: .functype ogt_f64_branch (f64, f64) -> () +; CHECK-NEXT: block +; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0 +; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1 +; CHECK-NEXT: f64.gt $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]] +; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]] +; CHECK-NEXT: br_if 0, $pop[[NUM3]] +; CHECK-NEXT: call _Z5call1v +define void @ogt_f64_branch(double %a, double %b) { +entry: + %cmp = fcmp ogt double %a, %b + br i1 %cmp, label %if.then, label %if.end + +if.then: + tail call void @_Z5call1v() + br label %if.end + +if.end: + ret void +} + +; CHECK-LABEL: ult_f64_branch: +; CHECK-NEXT: .functype ult_f64_branch (f64, f64) -> () +; CHECK-NEXT: block +; CHECK-NEXT: local.get $push[[L0:[0-9]+]]=, 0 +; CHECK-NEXT: local.get $push[[L1:[0-9]+]]=, 1 +; CHECK-NEXT: f64.ge $push[[NUM0:[0-9]+]]=, $pop[[L0]], $pop[[L1]] +; CHECK-NEXT: i32.eqz $push[[NUM3:[0-9]+]]=, $pop[[NUM0]] +; CHECK-NEXT: br_if 0, $pop[[NUM3]] +; CHECK-NEXT: call _Z5call1v +define void @ult_f64_branch(double %a, double %b) { +entry: + %cmp = fcmp ult double %a, %b + br i1 %cmp, label %if.end, label %if.then + +if.then: + tail call void @_Z5call1v() + br label %if.end + +if.end: + ret void +} + +declare void @_Z5call1v()