Take: ``` int f(bool a, int c) { return a * c; } int f0(bool a, int c) { return (-a) & c; } int f1(bool a, int c) { return a ? c : 0; } int f3(int a, int b, int c) { return (a == b) * c; } int g0(bool a, int c) { return a ? 0 : c; } int g1(bool a, int c) { a = !a; return a * c; } ``` Currently for f, f0 we emit: ``` neg a0,a0 and a0,a0,a1 ``` Which is good for riscv without zicond but with we should just get the same as f1. f1 we do we: ``` czero.eqz a0,a1,a0 ``` though without zicond we get: ``` snez a5,a0 neg a5,a5 and a0,a1,a5 ``` Notice the extra snez (note the above is because that is ifcvt.cc doing the emitting). This is all about what is the canonical form of bool ? a : 0.
Mine. requires both a gimple match.pd change and an expansion change.
LoongArch and MIPS64r6 also have similar instructions.
Created attachment 57671 [details] proposed patch This is the same patch I posted in PR114277, it fixes this bug as well.
(In reply to Raphael M Zinsly from comment #3) > Created attachment 57671 [details] > proposed patch > > This is the same patch I posted in PR114277, it fixes this bug as well. The question is which is more Canonical on gimple. the multiply or the cond_expr. I say the multiply. Since the multiply is. then you just need to add the case to "/* Expand X*Y as X&-Y when Y must be zero or one. */" instead in expr.cc. Though it does some costing which also needs/should be handled too.
Multiply as a canonical form of a conditional move/zero seems fairly non-obvious relative to a conditional expression. But I don't mind going with consensus on a canonical form. After all we just need to define one. The bigger question is fixing the expansion. We can expand as a multiply, x&-y or with a conditional-move like sequence.