This fixes the 6 ACATS failures present at -O2 on PowerPC/Linux: FAIL: cd1009a FAIL: cd1009i FAIL: cd1c03a FAIL: cd2a21c FAIL: cd2a24a FAIL: cd2a32a
The problem is a very aggressive SCCVN pass looking through a special view conversion we build in gigi. The optimization relies exclusively on types of bitfields in lieu of their sizes and this doesn't play nice with this view conversion. The patch adjusts the types so as to make the pass happy. Tested on x86-64/Linux and PowerPC/Linux, applied on the mainline. 2011-09-08 Eric Botcazou <ebotca...@adacore.com> * gcc-interface/utils.c (unchecked_convert): Use a field of the right precision when converting to or from an integral type whose precision is not equal to its size. -- Eric Botcazou
Index: gcc-interface/utils.c =================================================================== --- gcc-interface/utils.c (revision 178601) +++ gcc-interface/utils.c (working copy) @@ -4403,39 +4403,60 @@ unchecked_convert (tree type, tree expr, } /* If we are converting to an integral type whose precision is not equal - to its size, first unchecked convert to a record that contains an - object of the output type. Then extract the field. */ + to its size, first unchecked convert to a record type that contains an + field of the given precision. Then extract the field. */ else if (INTEGRAL_TYPE_P (type) && TYPE_RM_SIZE (type) && 0 != compare_tree_int (TYPE_RM_SIZE (type), GET_MODE_BITSIZE (TYPE_MODE (type)))) { tree rec_type = make_node (RECORD_TYPE); - tree field = create_field_decl (get_identifier ("OBJ"), type, rec_type, - NULL_TREE, NULL_TREE, 1, 0); + unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (type)); + tree field_type, field; + + if (TYPE_UNSIGNED (type)) + field_type = make_unsigned_type (prec); + else + field_type = make_signed_type (prec); + SET_TYPE_RM_SIZE (field_type, TYPE_RM_SIZE (type)); + + field = create_field_decl (get_identifier ("OBJ"), field_type, rec_type, + NULL_TREE, NULL_TREE, 1, 0); TYPE_FIELDS (rec_type) = field; layout_type (rec_type); expr = unchecked_convert (rec_type, expr, notrunc_p); expr = build_component_ref (expr, NULL_TREE, field, false); + expr = fold_build1 (NOP_EXPR, type, expr); } - /* Similarly if we are converting from an integral type whose precision - is not equal to its size. */ + /* Similarly if we are converting from an integral type whose precision is + not equal to its size, first copy into a field of the given precision + and unchecked convert the record type. */ else if (INTEGRAL_TYPE_P (etype) && TYPE_RM_SIZE (etype) && 0 != compare_tree_int (TYPE_RM_SIZE (etype), GET_MODE_BITSIZE (TYPE_MODE (etype)))) { tree rec_type = make_node (RECORD_TYPE); - tree field = create_field_decl (get_identifier ("OBJ"), etype, rec_type, - NULL_TREE, NULL_TREE, 1, 0); + unsigned HOST_WIDE_INT prec = TREE_INT_CST_LOW (TYPE_RM_SIZE (etype)); VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 1); + tree field_type, field; + + if (TYPE_UNSIGNED (etype)) + field_type = make_unsigned_type (prec); + else + field_type = make_signed_type (prec); + SET_TYPE_RM_SIZE (field_type, TYPE_RM_SIZE (etype)); + + field = create_field_decl (get_identifier ("OBJ"), field_type, rec_type, + NULL_TREE, NULL_TREE, 1, 0); TYPE_FIELDS (rec_type) = field; layout_type (rec_type); + expr = fold_build1 (NOP_EXPR, field_type, expr); CONSTRUCTOR_APPEND_ELT (v, field, expr); expr = gnat_build_constructor (rec_type, v); expr = unchecked_convert (type, expr, notrunc_p);