https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114331
--- Comment #5 from Andrew Macleod <amacleod at redhat dot com> --- (In reply to Jakub Jelinek from comment #4) > Actually, looking at value-range.h, irange_bitmask doesn't have just the > mask but also value, so I wonder why it isn't able to figure this out. > I'd think m_mask should be ~0xffff and value 111. _1 = (short int) num_5(D); _2 = (int) _1; switch (_1) globally we know _2 : [irange] int [-32768, 32767] and coming into bb 3: _2 : [irange] int [-32768, 32767] 2->3 _1 : [irange] short int [111, 111] 2->3 _2 : [irange] int [111, 111] 2->3 num_5(D) : [irange] int [-INF, -65537][-65425, -65425][111, 111][65536, +INF] I guess what you are looking for is to add known bits to the range produced for num_5 on the outgoing edge. This would have to be done in operator_cast::op1_range where we are reducing it to known range of the switch. I do not believe it makes any attempts to set bitmasks based on casts like that currently. so, GORI working backwards has _1 = [irange] short int [111, 111] , so it would be satisfying the expression: short int [111, 111] = (short int) num_5(D); when evaluating num_5 in operator_cast::op1_range, in the truncating_cast_p section we could also see if there is a bitmask pattern for the LHS that could be applied to the range.. I think that basically what you are asking for. Simple enough for a constant I suppose for starters. Or maybe Aldy has a routine that picks bitmasks and values from ranges somewhere?