https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82889
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org, | |law at gcc dot gnu.org, | |uros at gcc dot gnu.org --- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- That is because the signed integer pos needs to be extended to 64-bit sizetype for the array index and we only have the knowledge that pos is >= 0 in that part of code during vrp passes and so the expansion or REE pass or similar can't easily figure out that ZERO_EXTEND could be used the same as SIGN_EXTEND and pick one that is cheaper. Note, even using: int foo (int *table, int *ht, unsigned hash, unsigned mask) { unsigned long probe, i; for (probe = hash & mask, i = 1;; ++i) { int pos = ht[probe]; if (pos >= 0) { if (table[(unsigned) pos] == 42) return 1; } else if (pos & 1) return 0; probe += i; probe &= mask; } } doesn't help, because vrp pass optimize away the unsigned cast, because it knows that pos in that chunk of code is >= 0, but not in others, so it can't be preserved in range information. Note we don't even optimize int x; long long foo (void) { if (x < -1) return 73; int y = x + 1; return y; } where the value range for y is known to be [0, INT_MAX] and so we should know that when extending y to wider type both zero and sign extension give the same result. Dunno how the middle-end would know that zero_extend is cheaper though (in this case really for free), perhaps the REE pass ought to know that.