https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78319
--- Comment #4 from prathamesh3492 at gcc dot gnu.org --- Hi, I think this seems to be an issue with uninit pass. The same behavior can be observed for following test-case on x86_64-unknown-linux-gnu regardless of r241915. (test-case is a slight modification of foo() defined in uninit-pred-8_a.c to generate same CFG on x86_64 as on cortex-m7): int f(int n, int m, int l, int r) { int t1, t2, t3, t4, v; extern int g; void bar(); void blah(int); if ((n || m) || (r || l)) v = r; if (m != 0) g++; else bar (); if ((n || m) || (r || l)) blah (v); if (n != 0) blah (v); if (l != 0) blah (v); return 0; } -O2 -Wuninitialized gives: foo2.c: In function āfā: foo2.c:17:5: warning: āvā may be used uninitialized in this function [-Wmaybe-uninitialized] blah (v); ^~~~~~~~ Input to uninit pass (dump of crited2 pass): http://pastebin.com/wJBak3tS v is assigned the value of r if either _1 is true or _2 is true in above cfg. The warning at uninitialized use of v is for: if ((n || m) || (r || l)) blah(v); IIUC, the above call to blah(v) is duplicated in two blocks: bb10 and bb16. bb10 has only one predecessor bb7. Looking at: <bb 6>: # v_32 = PHI <r_13(D)(18), v_15(D)(17), r_13(D)(15)> bar (); <bb 7>: # v_33 = PHI <r_13(D)(5), v_32(6)> if (_1 != 0) goto <bb 10>; else goto <bb 8>; v is uninitialized if the control reaches to bb6 from bb17, ie the following path is taken: bb2 -> bb3 -> bb17 -> bb6 -> bb7 This path would be taken only if both _1 and _2 are 0. Since control goes from bb7 to bb10 only if _1 is nonzero, we can never reach bb10 if v is uninitialized. Similarly bb16 has only one predecessor bb8 and bb8 has only one predecessor bb7. We reach bb8 from "false edge" of bb7, ie, if _1 is 0. <bb 8>: _5 = r_13(D) | l_14(D); if (_5 != 0) goto <bb 16>; else goto <bb 19>; _5 is same as _2. I wonder why r_13(D) | l_14(D) is re-computed here instead of using _2, which is assigned the same value ? So if _5 is false, we should never reach bb16 and hence I think the warning is a false positive. Does this sound reasonable ? Btw the warning isn't given if vrp is disabled. Input to uninit pass after disabling vrp: http://pastebin.com/index.php IIC after disabling vrp, the cfg has only one block bb10 representing the blah(v) call unlike in the first case of enabled vrp, which duplicated bb10 and bb16 both containing calls to blah(v). There's another strange issue I noticed about folding: Consider following test-case: int f(int n, int m, int l, int r) { if (n || m || r || l) return 1; else return 0; } On x86_64, ssa pass dump shows: http://pastebin.com/Fuy6dGX1 truth_orif_expr's are converted to sequence of bit_ior_exprs: <bb 2>: _1 = n_5(D) | m_6(D); _2 = l_7(D) | _1; _3 = r_8(D) | _2; if (_3 != 0) goto <bb 3>; else goto <bb 4>; However if the expression is parenthesized as: if ((n || m) || (r || l)) then truth_orif_expr is not converted to sequence of bit_ior_exprs as above. x86_64 ssa dump for parenthesized expression: http://pastebin.com/AsQ5qLFu <bb 2>: _1 = n_4(D) | m_5(D); if (_1 != 0) goto <bb 4>; else goto <bb 3>; <bb 3>: _2 = l_6(D) | r_7(D); if (_2 != 0) goto <bb 4>; else goto <bb 5>; Why should parenthesizing the sub-expressions make a difference ? Thanks, Prathamesh