Interesting and clever use of mul by 0 or 1, but if you have MIPS32 extensions like mul (not classic MIPS mult/mflo) then you also have movz / movn conditional moves. In fact those were introduced with MIPS IV (first commercial release in 1994, R8000), earlier than 1999's MIPS 4K (MIPS32 ISA) MIPS 5K (MIPS64 ISA).
movn and movz are very much like x86 cmov, AArch64 csel, and equivalent instructions on other ISAs. Since MIPS has a zero register, you can condition-move from it to conditionally zero something based on another register being zero (movz) or non-zero (movn).
That allows GCC to compile your logic into 3 instructions, when I put it in front of a tailcall that uses the values in their incoming registers.
int bar(int,int);
int foo(int a, int b){
if (a <= b)
a = 0;
else
b = 0;
return bar(a, b);
}
Godbolt MIPS GCC 11.2 -O3 -march=mips4 -fno-delayed-branch
foo:
slt $2,$5,$4
movn $5,$0,$2
movz $4,$0,$2
j bar
nop
This is pretty much unbeatable.
Note that in your proposed version, the dynamic instruction count is at worst 4 (no path of execution runs both all 5), and at best 3 (if the bne is taken). But it avoid branching which is good, and does save static code size.
(If you assemble for a real MIPS with an assembler that tries but fails to fill branch-delay slots here, the branchy version might get an extra NOP after one or both branches, widening the advantage of branchless.)
On a fast wide machine (like 4-wide MIPS R8000 or R10000 although those are MIPS IV CPUs with movn/z but not mul) it's certainly interesting to consider mul if you don't do this often; the front-end can decode these instructions and then get more into the pipeline while it chews on these. Modern x86 CPUs have fully pipelined integer multiply units with 3 cycle latency, 1 cycle throughput (so they can start a new multiply every clock cycle). But much older MIPS CPUs almost certainly didn't, likely not even fully pipelined, and probably higher latency. (This is why until MIPS32/64 they only had mult, which wrote the result to a special hi/lo registers, to decouple that logic from the regular integer pipeline.)
I don't know where the tradeoff might be in terms of how predictable the branch would have to be (by the older simpler predictors in old MIPS CPUs) before that would be better than mul, for some realistic historical mul latency/throughput numbers. MIPS pipelines are shorter than modern CPUs; it helps some that the ISA is literally designed from the ground up to pipeline easily. But the branch delay slot only really helps scalar CPUs.
With a slow enough mul (or mult / mfo), even worst-case branch prediction might be better.
See also Modern Microprocessors
A 90-Minute Guide!
I didn't look at details of MIPS III CPUs to see if any had longer pipelines / superscalar or out-of-order exec which might favour less branchy code even without movn / movz
But as Erik showed in his answer, it's possible to just use bitwise operations even if you don't have MIPS IV movn/movz, so this consideration of mul only goes from purely hypothetical on MIPS IV to basically hypothetical on MIPS III CPUs.
(Or I guess if you have code that needs to be able to run on old MIPS CPUs, but is being run on a newer MIPS.)