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 */