Godbolt: https://gcc.godbolt.org/z/fsavMzMo7 ``` void set_bool(bool& fl, __UINT32_TYPE__ value) { fl |= value >> 31; } ``` This code shifts a `uint32` to the right by 31 bits, so the result will only be 0 or 1. Clang outputs: ``` set_bool(bool&, unsigned int): # @set_bool(bool&, unsigned int) shr esi, 31 or byte ptr [rdi], sil ret ``` but GCC emits an additional unnecessary bitwise AND operation on the destination operand: ``` set_bool(bool&, unsigned int): shr esi, 31 or BYTE PTR [rdi], sil and BYTE PTR [rdi], 1 ret ```
The workaround in this case is just to do: ((__INT32_TYPE__)value) < 0 instead of value>>31.
I am messing around in this area ....
So looking into this a little futher. The problem is VRP turns !=0 into (bool) and then expand comes along and decides that a cast to bool needs &1 because well it just. I am going to look into see if I can remove the &1 there ...
VRP starting doing this in GCC 5: Folding statement: _5 = _4 != 0; Folded into: _5 = (bool) _4;
Oh simple way to solve this to convert: t2_7 = (unsigned int) t_4; _1 = t1_6 | t2_7; t_8 = _1 != 0; Into: t3_8 = t1_7 != 0; _1 = t_5 | t3_8; Which is smaller even. (for bit_op (bit_ior bit_and bit_xor) (simplify (ne (bit_op (convert @0) @1) integer_zerop@2) (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE && types_match (type, @0)) (bit_op @0 (ne @1 @2))))
Just for reference here are the functions I tried to see which way was the best (set_bool0 and set_bool0_ produce the best for x86): void set_bool(bool& fl, __UINT32_TYPE__ value) { bool t = fl; __UINT32_TYPE__ t1 = value>>31; __UINT32_TYPE__ t2 = t; t = t2 | t1; fl = t; } void set_bool0(bool& fl, __UINT32_TYPE__ value) { bool t = fl; __UINT32_TYPE__ t1 = value>>31; bool t3 = t1; t = t | t3; fl = t; } void set_bool0_(bool& fl, __INT32_TYPE__ value) { bool t = fl; __UINT32_TYPE__ t1 = value<0; bool t3 = t1; t = t | t3; fl = t; } void set_bool1(bool& fl, __UINT32_TYPE__ value) { fl |= value >> 31; }
Funny, the match pattern in comment #5 is similar to the one which I was working on for PR 52345 .
GCC 14.1 is being released, retargeting bugs to GCC 14.2.
GCC 14.2 is being released, retargeting bugs to GCC 14.3.