https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107569
--- Comment #3 from Andrew Macleod <amacleod at redhat dot com> --- (In reply to Jakub Jelinek from comment #2) > Perhaps we should in vrp1 defer removal of __builtin_unreachable (), at least > the cases where we don't turn that into some useful range? > That of course doesn't improve the assume attribute case. well we do improve it tho. in vrp1: Global Exported: _5 = [frange] double [0.0 (0x0.0p+0), +Inf] +NAN Global Exported (via unreachable): _9 = [frange] double [-0.0 (-0x0.0p+0), +Inf] +-NAN Removing basic block 3 Merging blocks 2 and 4 double mag (const struct TVec & u) { double _3; double _5; double _6; double _7; double _8; double _9; <bb 2> [local count: 1073741824]: _3 = u_2(D)->x; _6 = _3 * _3; _7 = u_2(D)->y; _8 = _7 * _7; _9 = _6 + _8; _5 = sqrt (_9); return _5; The problem appears to be that the cdce pass runs afterwards, and introduces: _3 = u_2(D)->x; _6 = _3 * _3; _7 = u_2(D)->y; _8 = _7 * _7; _9 = _6 + _8; DCE_COND_LB.7_10 = _9; DCE_COND_LB_TEST.8_11 = DCE_COND_LB.7_10 u>= 0.0; if (DCE_COND_LB_TEST.8_11 != 0) goto <bb 5>; [99.95%] else goto <bb 4>; [0.05%] <bb 5> [local count: 1073204960]: _5 = .SQRT (_9); goto <bb 3>; [100.00%] <bb 4> [local count: 536864]: _12 = sqrt (_9); without checking the there is a global range for _9 which is [frange] double [-0.0 (-0x0.0p+0), +Inf] +-NAN now, does that Nan cause u>= 0 not to be true? I notice we don't fold that in vrp2. I will let aldy pitch in on the rest of this.