https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61409
--- Comment #19 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- Also, unless I'm missing something, in Jeff's analysis, I see no reference to j, which plays a pivotal role. In the testcase in comment 14, we can see that the guard for ptr_14 is actually [i && j==0]: if (i) { if (j) return; /* bar(); */ ptr = init(); } ...because on j != 0, we exit, which is what the .uninit dump is suggesting with: [AFTER NORMALIZATION -- [DEF]: ptr_14 = PHI <ptr_18(D)(9), ptr_22(5)> is guarded by : (.NOT.) j_20(D) != 0 (.AND.) i_17(D) != 0 Meanwhile, the use we are warning on is [i != 0]: [AFTER NORMALIZATION -- [USE]: rw = ptr_14; is guarded by : i_17(D) != 0 So the problem is that while the guard for the DEF is [i != 0 && j == 0], the guard for the USE is only [i != 0]. Uninit should somehow be aware that if PTR was set, then j==0, because otherwise we would've exited the function. You can see that .uninit is expecting the use to be guarded by [i != 0 && j == 0], by adding "&& !j" to the guard and silencing the warning: if (i && !j) { rw=ptr; }