This makes the vectorizer no longer produce vector types with pointer components as it doesn't properly use POINTER_PLUS_EXPR which then confuses other passes dealing with vectors in a generic way.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Sitting back and waiting for the fireworks. Richard. 2013-09-05 Richard Biener <rguent...@suse.de> PR tree-optimization/58137 * tree-vect-stmts.c (get_vectype_for_scalar_type_and_size): Do not create vectors of pointers. * tree-vect-loop.c (get_initial_def_for_induction): Use proper types for the components of the vector initializer. * tree-cfg.c (verify_gimple_assign_binary): Remove special-casing allowing pointer vectors with PLUS_EXPR/MINUS_EXPR. * gcc.target/i386/pr58137.c: New testcase. Index: gcc/tree-vect-loop.c =================================================================== *** gcc/tree-vect-loop.c (revision 202273) --- gcc/tree-vect-loop.c (working copy) *************** get_initial_def_for_induction (gimple iv *** 3133,3139 **** stmt_vec_info stmt_vinfo = vinfo_for_stmt (iv_phi); loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); - tree scalar_type; tree vectype; int nunits; edge pe = loop_preheader_edge (loop); --- 3133,3138 ---- *************** get_initial_def_for_induction (gimple iv *** 3185,3192 **** gcc_assert (ok); pe = loop_preheader_edge (iv_loop); ! scalar_type = TREE_TYPE (init_expr); ! vectype = get_vectype_for_scalar_type (scalar_type); resvectype = get_vectype_for_scalar_type (TREE_TYPE (PHI_RESULT (iv_phi))); gcc_assert (vectype); nunits = TYPE_VECTOR_SUBPARTS (vectype); --- 3184,3190 ---- gcc_assert (ok); pe = loop_preheader_edge (iv_loop); ! vectype = get_vectype_for_scalar_type (TREE_TYPE (init_expr)); resvectype = get_vectype_for_scalar_type (TREE_TYPE (PHI_RESULT (iv_phi))); gcc_assert (vectype); nunits = TYPE_VECTOR_SUBPARTS (vectype); *************** get_initial_def_for_induction (gimple iv *** 3229,3236 **** /* iv_loop is the loop to be vectorized. Create: vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr) */ ! new_var = vect_get_new_vect_var (scalar_type, vect_scalar_var, "var_"); ! new_name = force_gimple_operand (init_expr, &stmts, false, new_var); if (stmts) { new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); --- 3227,3237 ---- /* iv_loop is the loop to be vectorized. Create: vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr) */ ! new_var = vect_get_new_vect_var (TREE_TYPE (vectype), ! vect_scalar_var, "var_"); ! new_name = force_gimple_operand (fold_convert (TREE_TYPE (vectype), ! init_expr), ! &stmts, false, new_var); if (stmts) { new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); *************** get_initial_def_for_induction (gimple iv *** 3243,3251 **** for (i = 1; i < nunits; i++) { /* Create: new_name_i = new_name + step_expr */ ! enum tree_code code = POINTER_TYPE_P (scalar_type) ! ? POINTER_PLUS_EXPR : PLUS_EXPR; ! new_name = fold_build2 (code, scalar_type, new_name, step_expr); if (!is_gimple_min_invariant (new_name)) { init_stmt = gimple_build_assign (new_var, new_name); --- 3244,3251 ---- for (i = 1; i < nunits; i++) { /* Create: new_name_i = new_name + step_expr */ ! new_name = fold_build2 (PLUS_EXPR, TREE_TYPE (new_name), ! new_name, step_expr); if (!is_gimple_min_invariant (new_name)) { init_stmt = gimple_build_assign (new_var, new_name); Index: gcc/tree-vect-stmts.c =================================================================== *** gcc/tree-vect-stmts.c (revision 202272) --- gcc/tree-vect-stmts.c (working copy) *************** get_vectype_for_scalar_type_and_size (tr *** 6203,6210 **** corresponding to that mode. The theory is that any use that would cause problems with this will disable vectorization anyway. */ else if (!SCALAR_FLOAT_TYPE_P (scalar_type) ! && !INTEGRAL_TYPE_P (scalar_type) ! && !POINTER_TYPE_P (scalar_type)) scalar_type = lang_hooks.types.type_for_mode (inner_mode, 1); /* We can't build a vector type of elements with alignment bigger than --- 6203,6209 ---- corresponding to that mode. The theory is that any use that would cause problems with this will disable vectorization anyway. */ else if (!SCALAR_FLOAT_TYPE_P (scalar_type) ! && !INTEGRAL_TYPE_P (scalar_type)) scalar_type = lang_hooks.types.type_for_mode (inner_mode, 1); /* We can't build a vector type of elements with alignment bigger than Index: gcc/testsuite/gcc.target/i386/pr58137.c =================================================================== *** gcc/testsuite/gcc.target/i386/pr58137.c (revision 0) --- gcc/testsuite/gcc.target/i386/pr58137.c (revision 0) *************** *** 0 **** --- 1,33 ---- + /* { dg-do compile } */ + /* { dg-options "-O3 -mavx2" } */ + + typedef unsigned int U32; + + struct sv { + void* sv_any; + U32 sv_refcnt; + U32 sv_flags; + }; + typedef struct sv SV; + + struct xrv { + SV * xrv_rv; + }; + typedef struct xrv XRV; + + extern XRV * PL_xrv_root; + + void + more_xrv (void) + { + register XRV* xrv; + register XRV* xrvend; + xrv = PL_xrv_root; + xrvend = &xrv[200 / sizeof (XRV) - 1]; + while (xrv < xrvend) + { + xrv->xrv_rv = (SV*)(xrv + 1); + xrv++; + } + xrv->xrv_rv = 0; + } Index: gcc/tree-cfg.c =================================================================== *** gcc/tree-cfg.c (revision 202272) --- gcc/tree-cfg.c (working copy) *************** verify_gimple_assign_binary (gimple stmt *** 3571,3581 **** case PLUS_EXPR: case MINUS_EXPR: { ! /* We use regular PLUS_EXPR and MINUS_EXPR for vectors. ! ??? This just makes the checker happy and may not be what is ! intended. */ ! if (TREE_CODE (lhs_type) == VECTOR_TYPE ! && POINTER_TYPE_P (TREE_TYPE (lhs_type))) { if (TREE_CODE (rhs1_type) != VECTOR_TYPE || TREE_CODE (rhs2_type) != VECTOR_TYPE) --- 3571,3580 ---- case PLUS_EXPR: case MINUS_EXPR: { ! tree lhs_etype = lhs_type; ! tree rhs1_etype = rhs1_type; ! tree rhs2_etype = rhs2_type; ! if (TREE_CODE (lhs_type) == VECTOR_TYPE) { if (TREE_CODE (rhs1_type) != VECTOR_TYPE || TREE_CODE (rhs2_type) != VECTOR_TYPE) *************** verify_gimple_assign_binary (gimple stmt *** 3583,3604 **** error ("invalid non-vector operands to vector valued plus"); return true; } ! lhs_type = TREE_TYPE (lhs_type); ! rhs1_type = TREE_TYPE (rhs1_type); ! rhs2_type = TREE_TYPE (rhs2_type); ! /* PLUS_EXPR is commutative, so we might end up canonicalizing ! the pointer to 2nd place. */ ! if (POINTER_TYPE_P (rhs2_type)) ! { ! tree tem = rhs1_type; ! rhs1_type = rhs2_type; ! rhs2_type = tem; ! } ! goto do_pointer_plus_expr_check; } ! if (POINTER_TYPE_P (lhs_type) ! || POINTER_TYPE_P (rhs1_type) ! || POINTER_TYPE_P (rhs2_type)) { error ("invalid (pointer) operands to plus/minus"); return true; --- 3582,3594 ---- error ("invalid non-vector operands to vector valued plus"); return true; } ! lhs_etype = TREE_TYPE (lhs_type); ! rhs1_etype = TREE_TYPE (rhs1_type); ! rhs2_etype = TREE_TYPE (rhs2_type); } ! if (POINTER_TYPE_P (lhs_etype) ! || POINTER_TYPE_P (rhs1_etype) ! || POINTER_TYPE_P (rhs2_etype)) { error ("invalid (pointer) operands to plus/minus"); return true; *************** verify_gimple_assign_binary (gimple stmt *** 3610,3616 **** case POINTER_PLUS_EXPR: { - do_pointer_plus_expr_check: if (!POINTER_TYPE_P (rhs1_type) || !useless_type_conversion_p (lhs_type, rhs1_type) || !ptrofftype_p (rhs2_type)) --- 3600,3605 ----