https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98703
--- Comment #4 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- I can't remember what Andrew's plan was for complex numbers, possibly for next release when we handle floats. We have somewhat of a kludge to know that the result of REALPART_EXPR and IMAGPART_EXPR are [0,1] for this case (gimple_range_adjustment), but not much else. We are interested in the 2->3 edge for this IL: =========== BB 2 ============ Imports: _2 Exports: _2 _3 _3 : _2(I) x_5(D) unsigned int VARYING <bb 2> : _7 = .MUL_OVERFLOW (x_5(D), y_6(D)); _1 = REALPART_EXPR <_7>; *res_9(D) = _1; _2 = IMAGPART_EXPR <_7>; _3 = (bool) _2; if (_3 != 0) goto <bb 3>; [INV] else goto <bb 4>; [INV] _2 : unsigned int [0, 1] 2->3 (T) _2 : unsigned int [1, 1] 2->3 (T) _3 : bool [1, 1] 2->4 (F) _2 : unsigned int [0, 0] 2->4 (F) _3 : bool [0, 0] On the 2->3 edge we know that _2 is [1,1], which means thee multiplication doesn't overflow and that IMAGPART_EXPR<_7> is [1,1]. If we could handle complex ints, we could unwind to _7 = .MUL_OVERFLOW (x_5(D), y_6(D)); and register that x_5 is not 0 plus all the goodies Jakub mentions in comment 2 (*). We don't do any of this, as we don't handle complex numbers, which _7 is one. (*) Clearly, Jakub is the person to contribute copious knowledge to range-op.cc, since he always has such great ideas in this space. And it's so easy to do so ;-).