https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114277
--- Comment #11 from Jeffrey A. Law <law at gcc dot gnu.org> --- Hmm, I think we got side-tracked on the conditional move representation. For this BZ I think a simple match.pd pattern may be sufficient. x * ((x || y) != 0) -> x x * ((x || y) == 0) -> 0 There's simplifications for the "&&" case as well, though they don't show up in gimple as we've missed the necessary if-conversions. (simplify (mult:c (convert? (ne (bit_ior:c @0 @1) integer_zerop@2)) @0) @0) (simplify (mult:c (convert? (eq (bit_ior:c @0 @1) integer_zerop@2)) @0) { build_zero_cst (type); }) So given this source: int a,b; void func_0(int x){ a=x*(x||b); } void func_1(int x){ a=x*!(x||b); } We can compile that down to this code on riscv: func_0: lui a5,%hi(a) sw a0,%lo(a)(a5) ret func_1: lui a5,%hi(a) sw zero,%lo(a)(a5) ret Am I missing something here?