https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96542
--- Comment #6 from Andrew Macleod <amacleod at redhat dot com> --- Likewise, for unsigned baz (unsigned int x) { if (x >= 4) return 32; return (-1U >> x) * 16; } =========== BB 2 ============ x_3(D) unsigned int VARYING _4 UNDEFINED <bb 2> : if (x_3(D) > 3) goto <bb 3>; [INV] else goto <bb 4>; [INV] 2->3 (T) x_3(D) : unsigned int [4, +INF] 2->4 (F) x_3(D) : unsigned int [0, 3] =========== BB 3 ============ _4 UNDEFINED <bb 3> : // predicted unlikely by early return (on trees) predictor. goto <bb 5>; [INV] =========== BB 4 ============ x_3(D) unsigned int [0, 3] <bb 4> : _1 = 4294967295 >> x_3(D); _4 = _1 * 16; _1 : unsigned int [536870911, +INF] 0xFFFFFFFF >> [0,3] is currently producing [0x2FFFFFFF, 0xFFFFFFFF] again making operator_rshift capable of generating multi-ranges, 0xFFFFFFFF >> [0,3] should produce [0x2FFFFFFF, 0x2FFFFFFF][0x4FFFFFFF, 0x4FFFFFFF][0x8FFFFFFF, 0x8FFFFFFF][0xFFFFFFFF, 0xFFFFFFFF] and then _4 = _1 *16 should automatically produce: [0xFFFFFFF0, 0xFFFFFFF0] I think multiply does that today, if its given the proper input. =========== BB 5 ============ _4 unsigned int VARYING <bb 5> : # _2 = PHI <32(3), _4(4)> return _2; And then this PHI will have the constant propagated and become: # _2 = PHI <32(3), 0xFFFFFFF0(4)> return _2 ANd given that, presumably phi-opt or maybe even VRPs simplfication will turn that into the desired conditional once the constant is calculated.