aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/wasm/CodeGen.zig33
-rw-r--r--src/arch/wasm/Emit.zig2
-rw-r--r--src/arch/wasm/Mir.zig4
3 files changed, 22 insertions, 17 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig
index f52506c393..38ab19cb60 100644
--- a/src/arch/wasm/CodeGen.zig
+++ b/src/arch/wasm/CodeGen.zig
@@ -3889,27 +3889,26 @@ fn airMaxMin(self: *Self, inst: Air.Inst.Index, op: enum { max, min }) InnerErro
const lhs = try self.resolveInst(bin_op.lhs);
const rhs = try self.resolveInst(bin_op.rhs);
- const result = try self.allocLocal(ty);
-
- try self.startBlock(.block, wasm.block_empty);
- try self.startBlock(.block, wasm.block_empty);
-
- // check if LHS is greater/lesser than RHS
- const cmp_result = try self.cmp(lhs, rhs, ty, if (op == .max) .gt else .lt);
- try self.addLabel(.local_get, cmp_result.local);
- try self.addLabel(.br_if, 0); // break to outer loop if LHS is greater/lesser than RHS
-
- // set RHS as max/min
+ // operands to select from
+ try self.emitWValue(lhs);
try self.emitWValue(rhs);
- try self.addLabel(.local_set, result.local);
- try self.addLabel(.br, 1); // break out of all blocks
- try self.endBlock();
- // set LHS as max/min
+ // operands to compare
try self.emitWValue(lhs);
- try self.addLabel(.local_set, result.local);
- try self.endBlock();
+ try self.emitWValue(rhs);
+ const opcode = buildOpcode(.{
+ .op = if (op == .max) .gt else .lt,
+ .signedness = if (ty.isSignedInt()) .signed else .unsigned,
+ .valtype1 = typeToValtype(ty, self.target),
+ });
+ try self.addTag(Mir.Inst.Tag.fromOpcode(opcode));
+
+ // based on the result from comparison, return operand 0 or 1.
+ try self.addTag(.select);
+ // store result in local
+ const result = try self.allocLocal(ty);
+ try self.addLabel(.local_set, result.local);
return result;
}
diff --git a/src/arch/wasm/Emit.zig b/src/arch/wasm/Emit.zig
index 6fc2dfa3b3..bcbff8d195 100644
--- a/src/arch/wasm/Emit.zig
+++ b/src/arch/wasm/Emit.zig
@@ -96,6 +96,8 @@ pub fn emitMir(emit: *Emit) InnerError!void {
.@"return" => try emit.emitTag(tag),
.@"unreachable" => try emit.emitTag(tag),
+ .select => try emit.emitTag(tag),
+
// arithmetic
.i32_eqz => try emit.emitTag(tag),
.i32_eq => try emit.emitTag(tag),
diff --git a/src/arch/wasm/Mir.zig b/src/arch/wasm/Mir.zig
index b15dbd9020..87e64ce9e0 100644
--- a/src/arch/wasm/Mir.zig
+++ b/src/arch/wasm/Mir.zig
@@ -77,6 +77,10 @@ pub const Inst = struct {
///
/// Uses `label`
call_indirect = 0x11,
+ /// Pops three values from the stack and pushes
+ /// the first or second value dependent on the third value.
+ /// Uses `tag`
+ select = 0x1B,
/// Loads a local at given index onto the stack.
///
/// Uses `label`