diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-04-05 18:35:38 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2022-04-05 21:56:25 +0200 |
| commit | ac873367b9d68e1d7b4cf4e5efbe179960dc7557 (patch) | |
| tree | 97476eca40fa2619491c54c1484b4278f8ab5435 /src/arch/wasm/CodeGen.zig | |
| parent | 5fafcc2b629e2ff00755b2bf45e903590f04aa9f (diff) | |
| download | zig-ac873367b9d68e1d7b4cf4e5efbe179960dc7557.tar.gz zig-ac873367b9d68e1d7b4cf4e5efbe179960dc7557.zip | |
wasm: Use 'select' instruction for max/min
Rather than using blocks and control flow to check which operand is the maximum or minimum,
we use wasm's `select` instruction which returns us the operand based on a result from a comparison.
This saves us the need of control flow, as well as reduce the instruction count from 13 to 7.
Diffstat (limited to 'src/arch/wasm/CodeGen.zig')
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 33 |
1 files changed, 16 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; } |
