There's a rather annoying bug in the vectorizer which can cause us to have SSA_NAMEs which are used, but never defined.
Consider this testcase compiled with -msse2 -ftree-vectorize: typedef char achar __attribute__ ((__aligned__(16))); int main1 () { struct { achar *p; achar *q; } s; int i; achar x[16]; achar cb[16]; s.p = x; i = 0; do { s.p[i] = cb[i]; i++; } while (i < 16); if (s.p[0]) abort (); } In the interest of brevity, I'm just going to point out the problematical store from the .ifcvt dump: # x_16 = V_MAY_DEF <x_21>; # SFT.3_20 = V_MAY_DEF <SFT.3_15>; *D.1470_8 = D.1472_11; Which gets vectorized and appears like this in the .vect dump: # x_16 = V_MAY_DEF <x_21>; # SFT.3_20 = V_MAY_DEF <SFT.3_15>; *vect_px.17_36 = vect_var_.10_29; Which looks perfectly fine. Unfortunately, there is a huge problem. If the operands for that statement are rebuilt, then we are going to lose the assignment to SFT.3_20. When we vectorize the store we copy the virtual operands from the original statement to the new vectorized statement via this code: /* Copy the V_MAY_DEFS representing the aliasing of the original array element's definition to the vector's definition then update the defining statement. The original is being deleted so the same SSA_NAMEs can be used. */ copy_virtual_operands (*vec_stmt, stmt); v_may_defs = STMT_V_MAY_DEF_OPS (*vec_stmt); nv_may_defs = NUM_V_MAY_DEFS (v_may_defs); for (i = 0; i < nv_may_defs; i++) { tree ssa_name = V_MAY_DEF_RESULT (v_may_defs, i); SSA_NAME_DEF_STMT (ssa_name) = *vec_stmt; } This is safe if and only if the the operand scanning code will compute the same V_MAY_DEFS for the original scalar statement and the new vectorized statement. ie, *D.1470 must have the same aliasing properties as *vect_px.17. This works in the mainline because nothing ever causes a rescan of the statement's operands. However, with some pending changes I've got to the jump threader, IVopts will later want to change *vect_px.17_36 in the vectorized statement, which causes a rescan of the operands. When we rescan the operands, we get a different set of V_MAY_DEFS, specifically we lose the V_MAY_DEF for SFT.3_20. Which results in uses of SFT.3_20 later, but SFT.3_20 is never defined. You can see this behavior in the mainline with the attached trivial change which forces a rescan of the operands after we change the store statement. This will cause an IL checking failure after vectorizing as we'll have SSA_NAMEs which are used, but never defined. It seems to me the vectorizer needs to ensure that the aliasing properties are the same so that if the statement is later rescanned for some reason we don't suddenly use definition sites for SSA_NAMES. I'm not at all familiar with this code, so I don't know the best way to try and fix it. It would probably be wise to audit the other uses of copy_virtual_operands. We might also consider forcing statement rescans as part of our IL checking code to avoid these kinds of problems in the future. Jeff
Index: tree-vect-transform.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-vect-transform.c,v retrieving revision 2.9 diff -c -p -r2.9 tree-vect-transform.c *** tree-vect-transform.c 29 Mar 2005 17:45:39 -0000 2.9 --- tree-vect-transform.c 8 Apr 2005 16:44:49 -0000 *************** vectorizable_store (tree stmt, block_stm *** 910,915 **** --- 910,916 ---- defining statement. The original is being deleted so the same SSA_NAMEs can be used. */ copy_virtual_operands (*vec_stmt, stmt); + update_stmt (*vec_stmt); v_may_defs = STMT_V_MAY_DEF_OPS (*vec_stmt); nv_may_defs = NUM_V_MAY_DEFS (v_may_defs);