https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125707
Drea Pinski <pinskia at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Severity|normal |enhancement
Last reconfirmed| |2026-06-10
Ever confirmed|0 |1
Summary|Possible missed |(~a)>>a should be
|optimization at O3 (also O2 |simplified into -1
|and O1) |
Keywords| |easyhack,
| |missed-optimization
--- Comment #1 from Drea Pinski <pinskia at gcc dot gnu.org> ---
# RANGE [irange] int8_t [0, 2] MASK 0x3 VALUE 0x0
int8_t v3_i8_5(D) = v3_i8;
# RANGE [irange] int8_t [-3, -1] MASK 0x3 VALUE 0xfc
i0_i8_6 = ~v3_i8_5(D);
# RANGE [irange] int [-3, -1] MASK 0x3 VALUE 0xfffffffc
_2 = (int) i0_i8_6;
# RANGE [irange] int [0, 2] MASK 0x3 VALUE 0x0
_3 = (int) v3_i8_5(D);
# RANGE [irange] int [-3, -1] MASK 0x3 VALUE 0xfffffffc
_4 = _2 >> _3;
GCC does not see the relationship between _2 and _3.
I am not even sure this is worth it.
Changing to use int/unsigned, GCC gets:
# RANGE [irange] unsigned int [0, 2] MASK 0x3 VALUE 0x0
v3_i8.0_1 = (unsigned int) v3_i8_2(D);
# RANGE [irange] int [-3, -1] MASK 0x3 VALUE 0xfffffffc
i0_i8_3 = ~v3_i8_2(D);
# RANGE [irange] int [-3, -1] MASK 0x3 VALUE 0xfffffffc
i1_i8_4 = i0_i8_3 >> v3_i8.0_1;
So this is (~a)>>a; with a range of [0,2]. -3>>2 is -1.
So the Actually missed optimization is just:
int src(int a) {
return (~a)>>a;
}
is -1.