https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91645
--- Comment #9 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- It looks like what we want for this test is actually !isgreaterequal() not isless(), since we want to exclude the possibility of a NAN. Like this: float test (float x) { if (!__builtin_isgreaterequal (x, 0.0)) __builtin_unreachable(); return sqrtf (x); } After VRP1 removes the unreachable, the range for x_1 is correctly exported as >= -0.0 without a NAN: Global Exported (via unreachable): x_1(D) = [frange] float [-0.0 (-0x0.0p+0), +Inf] We end up with this: float test (float x) { float _4; <bb 2> [local count: 1073741824]: _4 = sqrtf (x_1(D)); return _4; } which then CDCE expands with the unnecessary checking code: <bb 2> [local count: 1073741824]: DCE_COND_LB.2_5 = x_1(D); DCE_COND_LB_TEST.3_6 = DCE_COND_LB.2_5 u>= 0.0; if (DCE_COND_LB_TEST.3_6 != 0) goto <bb 5>; [99.95%] else goto <bb 4>; [0.05%] <bb 5> [local count: 1073204960]: _4 = .SQRT (x_1(D)); goto <bb 3>; [100.00%] <bb 4> [local count: 536864]: _7 = sqrtf (x_1(D)); So the CDCE pass needs to be enhanced to use the ranger, instead of heuristics, to determine that the argument to sqrtf is neither negative nor NAN. In this particular case, we could use global ranges for free, but there's no reason we can't use an actual on-demand ranger for more complex scenarios. Just a guess here, but use_internal_fn() in CDCE shrink wraps the call to sqrt into a check with appropriate dispatch. We could emit the .SQRT call directly if the range of x_1 is not NAN and not negative.