gcc -S -O1 -Wuninitialized uninitialized.c GCC 4.4.0 20081121: warning: 's' is used uninitialized in this function GCC 4.3.2: warning: ‘i’ may be used uninitialized in this function
Created attachment 16772 [details] testcase
What the *#$^*(#^&$*(: SR.3_5 = p_1(D)->c; SR.4_6 = VIEW_CONVERT_EXPR<long long unsigned int>(*p_1(D)); SR.4_7 = SR.4_6 & 4294967295; SR.5_8 = (unsigned int) SR.4_7; s.0.c ={v} SR.3_5; SR.6_10 = VIEW_CONVERT_EXPR<long long unsigned int>(s.0); SR.7_11 = SR.6_10 & 0x0ffffffff00000000; SR.8_12 = (long long unsigned int) SR.5_8; SR.9_13 = SR.7_11 | SR.8_12; s.0 ={v} VIEW_CONVERT_EXPR<struct xxx>(SR.9_13); This is so wrong.
Doesn't happen on 64bit x86_64. Testcase which doesn't warn with 4.3: struct xxx { short a; short b; void *c; }; void bar(struct xxx); void foo(struct xxx *p, int i) { struct xxx s = *p; if (s.a) i++; bar(s); } but indeed, SRA does bullshit here, cost-wise and correctness-wise.
I can't reproduce this any longer since http://gcc.gnu.org/viewcvs?view=rev&revision=142396
Still warns for truct xxx { short a; short b; void *c; }; void bar(struct xxx); void foo(struct xxx *p, int i) { struct xxx s0 = *p; struct xxx s = s0; if (s.a) i++; bar(s); } at -O -m32 -Wuninitialized.
This is sra_build_assignment/sra_build_bf_assignments way of "lowering" a BIT_FIELD_REF to integer arithmetic. We hit the !INTEGRAL_TYPE_P (TREE_TYPE (var)) paths and for BIT_FIELD_REF <*p_1(D), 32, 0> we create VIEW_CONVERT_EXPR <long long> (*p) and extract the lower/upper 32 bits by shifting and masking. This obviously "uses" possibly uninitialized parts of *p or s0. The problem here is that we interestingly split the initialization of s0 to the upper part s0.c ={v} s0$c_7; and the lower part SR.3_8 = VIEW_CONVERT_EXPR<long long unsigned int>(s0); SR.4_9 = SR.3_8 & 0xffffffff00000000; SR.5_10 = (long long unsigned int) s0$B0F32_5; SR.6_11 = SR.4_9 | SR.5_10; s0 ={v} VIEW_CONVERT_EXPR<struct xxx>(SR.6_11); this is likely because SRA really wants to have two 32bit fields but it cannot deal with the larger struct with a VIEW_CONVERT_EXPR. With just disabling all these code-paths we get <bb 2>: s0$B0F32_4 = 0; s0$c_5 = p_1(D)->c; s0$B0F32_6 = BIT_FIELD_REF <*p_1(D), 32, 0>; s0.c ={v} s0$c_5; BIT_FIELD_REF <s0, 32, 0> ={v} s0$B0F32_6; s ={v} s0; s$a_7 = s.a; D.1242_2 = s$a_7; and no warning. But of course we now have bitfield refs that are not optimized (not scalarizing in this case would be better). Of course even with the current scalarization we finally arrive with <bb 2>: # VUSE <SMT.16_13(D)> s0$c_7 = p_1(D)->c; # VUSE <SMT.16_13(D)> D.1249_4 = VIEW_CONVERT_EXPR<long long unsigned int>(*p_1(D)); s0$B0F32_5 = (unsigned int) D.1249_4; # VUSE <s0_14(D)> SR.21_24 = VIEW_CONVERT_EXPR<long long unsigned int>(s0); SR.22_25 = SR.21_24 & 0xffffffff00000000; # s0_28 = VDEF <s0_14(D)> s0 = VIEW_CONVERT_EXPR<struct xxx>(SR.22_25); # s0_29 = VDEF <s0_28> s0.c = s0$c_7; # VUSE <s0_29> SR.3_8 = VIEW_CONVERT_EXPR<long long unsigned int>(s0); SR.4_9 = SR.3_8 & 0xffffffff00000000; SR.5_10 = (long long unsigned int) s0$B0F32_5; SR.6_11 = SR.5_10 | SR.4_9; s0$B0F32_21 = (unsigned int) SR.6_11; s0$c_30 = VIEW_CONVERT_EXPR<struct xxx>(SR.6_11).c; # VUSE <s0_29> SR.25_31 = VIEW_CONVERT_EXPR<long long unsigned int>(s0); SR.26_32 = SR.25_31 & 0xffffffff00000000; SR.27_33 = (long long unsigned int) s0$B0F32_21; SR.28_34 = SR.27_33 | SR.26_32; # s0_35 = VDEF <s0_29> s0 = VIEW_CONVERT_EXPR<struct xxx>(SR.28_34); # s0_36 = VDEF <s0_35> s0.c = s0$c_30; # VUSE <s0_36> # s_18 = VDEF <s_17(D)> s = s0; # VUSE <s_18> s$a_37 = s.a; # s_39 = VDEF <s_18> s.a = s$a_37; # VUSE <s_39> # SMT.16_20 = VDEF <SMT.16_13(D)> bar (s); return; because we seem to scalarize again. Ugh.
The following would make SRA only combine all of the struct or nothing. That avoids these messy situations: Index: tree-sra.c =================================================================== --- tree-sra.c (revision 142469) +++ tree-sra.c (working copy) @@ -1695,7 +1695,10 @@ try_instantiate_multiple_fields (struct gcc_assert (~alchk < align); - /* Create the field group as a single variable. */ + /* Create the field group as a single variable if the group covers + the whole element. */ + if (size != TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (elt->element)))) + return f; /* We used to create a type for the mode above, but size turns to be out not of mode-size. As we need a matching type
(In reply to comment #7) The patch causes segfault. This is how it happens: tree-sra.c:1612 for (f = TYPE_FIELDS (elt->type); f; f = TREE_CHAIN (f)) { tree-sra.c:1700 if (size != TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (elt->element)))) return f; // NULL tree-sra.c:1764 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f)) if (TREE_CODE (f) == FIELD_DECL) { tree last = try_instantiate_multiple_fields (elt, f); if (last != f) { f = last; continue; }
Subject: Bug 38271 Author: aoliva Date: Wed Dec 10 17:20:50 2008 New Revision: 142651 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=142651 Log: gcc/ChangeLog: PR middle-end/38271 * tree-sra.c (sra_build_bf_assignment): Avoid warnings for variables initialized from SRAed bit fields. gcc/testsuite/ChangeLog: PR middle-end/38271 * gcc.dg/torture/pr38271.c: New. Added: trunk/gcc/testsuite/gcc.dg/torture/pr38271.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-sra.c
Fixed.