http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53101
Marc Glisse <glisse at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |glisse at gcc dot gnu.org --- Comment #5 from Marc Glisse <glisse at gcc dot gnu.org> 2012-05-06 19:55:58 UTC --- Getting a BIT_FIELD_REF in gimple is simple enough. If I remember correctly, the patch below was enough (it also fixes the fact the current code will generate a BIT_FIELD_REF for true elements of the vector and one past the end, but not further, and I am not sure why that one-past-the-end behavior would be wanted). I did it because I thought it would be easier to convince the compiler to expand that to a vec_select, and I tried patching get_inner_reference and extract_bit_field_1, but no luck, I give up for now. --- gimplify.c (revision 187205) +++ gimplify.c (working copy) @@ -4262,11 +4262,16 @@ gimple_fold_indirect_ref (tree t) else if (TREE_CODE (optype) == COMPLEX_TYPE && useless_type_conversion_p (type, TREE_TYPE (optype))) return fold_build1 (REALPART_EXPR, type, op); /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */ else if (TREE_CODE (optype) == VECTOR_TYPE - && useless_type_conversion_p (type, TREE_TYPE (optype))) + && (useless_type_conversion_p (type, TREE_TYPE (optype)) + || (TREE_CODE (type) == VECTOR_TYPE + && useless_type_conversion_p (TREE_TYPE (type), + TREE_TYPE (optype)) + && TYPE_VECTOR_SUBPARTS (type) + < TYPE_VECTOR_SUBPARTS (optype)))) { tree part_width = TYPE_SIZE (type); tree index = bitsize_int (0); return fold_build3 (BIT_FIELD_REF, type, op, part_width, index); } @@ -4283,22 +4288,29 @@ gimple_fold_indirect_ref (tree t) STRIP_NOPS (addr); addrtype = TREE_TYPE (addr); /* ((foo*)&vectorfoo)[1] -> BIT_FIELD_REF<vectorfoo,...> */ if (TREE_CODE (addr) == ADDR_EXPR - && TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE - && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (addrtype))) - && host_integerp (off, 1)) + && host_integerp (off, 1) + && ((TREE_CODE (TREE_TYPE (addrtype)) == VECTOR_TYPE + && useless_type_conversion_p (type, + TREE_TYPE (TREE_TYPE (addrtype)))) + || (TREE_CODE (type) == VECTOR_TYPE + && useless_type_conversion_p (TREE_TYPE (type), + TREE_TYPE (TREE_TYPE (addrtype))) + && TYPE_VECTOR_SUBPARTS (type) + < TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))))) { unsigned HOST_WIDE_INT offset = tree_low_cst (off, 1); tree part_width = TYPE_SIZE (type); unsigned HOST_WIDE_INT part_widthi - = tree_low_cst (part_width, 0) / BITS_PER_UNIT; + = tree_low_cst (part_width, 0); + unsigned HOST_WIDE_INT orig_widthi + = tree_low_cst (TYPE_SIZE (TREE_TYPE (addrtype)), 0); unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; tree index = bitsize_int (indexi); - if (offset / part_widthi - <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))) + if (indexi + part_widthi <= orig_widthi) return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0), part_width, index); } /* ((foo*)&complexfoo)[1] -> __imag__ complexfoo */