Hi, While looking for uses of useless_type_conversion on non-gimple register types I run across few that seem to be completely unnecesary and I would like to get rid of them in hope to get rid of code comparing functions/method type and possibly more.
usless_type_conversion is about operations on the types in gimple expressions, not about memory accesses nor about function calls. First on is in fold-const.c that may be used on MEM_REF of aggregate type. As discussed earlier, the type compare is unnecesary when we only care about address that seems to be the most comon case we get into this path. I also disabled type matching done by operand_equal_p and cleaned up the conditional of MEM_REF into multiple ones - for example it was passing OEP_ADDRESS_OF when comparing TYPE_SIZE which is quite a nonsense. I wonder what to do about OPE_CONSTANT_ADDRESS_OF. This flag does not seem to be used at all in current tree nor documented somehow. I also made operand_equal_p to skip AA compare when -fno-strict-aliasing is used. Bootstrapped/regtested x86_64-linux, OK? Honza * fold-const.c (operand_equal_p): When in OEP_ADDRESS_OF do not require types to match; also relax checking of MEM_REF. Index: fold-const.c =================================================================== --- fold-const.c (revision 228131) +++ fold-const.c (working copy) @@ -2712,26 +2712,31 @@ operand_equal_p (const_tree arg0, const_ if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST) return tree_int_cst_equal (arg0, arg1); - /* If both types don't have the same signedness, then we can't consider - them equal. We must check this before the STRIP_NOPS calls - because they may change the signedness of the arguments. As pointers - strictly don't have a signedness, require either two pointers or - two non-pointers as well. */ - if (TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1)) - || POINTER_TYPE_P (TREE_TYPE (arg0)) != POINTER_TYPE_P (TREE_TYPE (arg1))) - return 0; + if (!(flags & OEP_ADDRESS_OF)) + { + /* If both types don't have the same signedness, then we can't consider + them equal. We must check this before the STRIP_NOPS calls + because they may change the signedness of the arguments. As pointers + strictly don't have a signedness, require either two pointers or + two non-pointers as well. */ + if (TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1)) + || POINTER_TYPE_P (TREE_TYPE (arg0)) + != POINTER_TYPE_P (TREE_TYPE (arg1))) + return 0; - /* We cannot consider pointers to different address space equal. */ - if (POINTER_TYPE_P (TREE_TYPE (arg0)) && POINTER_TYPE_P (TREE_TYPE (arg1)) - && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0))) - != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1))))) - return 0; + /* We cannot consider pointers to different address space equal. */ + if (POINTER_TYPE_P (TREE_TYPE (arg0)) + && POINTER_TYPE_P (TREE_TYPE (arg1)) + && (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0))) + != TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg1))))) + return 0; - /* If both types don't have the same precision, then it is not safe - to strip NOPs. */ - if (element_precision (TREE_TYPE (arg0)) - != element_precision (TREE_TYPE (arg1))) - return 0; + /* If both types don't have the same precision, then it is not safe + to strip NOPs. */ + if (element_precision (TREE_TYPE (arg0)) + != element_precision (TREE_TYPE (arg1))) + return 0; + } STRIP_NOPS (arg0); STRIP_NOPS (arg1); @@ -2935,27 +2940,34 @@ operand_equal_p (const_tree arg0, const_ case TARGET_MEM_REF: case MEM_REF: - /* Require equal access sizes, and similar pointer types. - We can have incomplete types for array references of - variable-sized arrays from the Fortran frontend - though. Also verify the types are compatible. */ - if (!((TYPE_SIZE (TREE_TYPE (arg0)) == TYPE_SIZE (TREE_TYPE (arg1)) - || (TYPE_SIZE (TREE_TYPE (arg0)) - && TYPE_SIZE (TREE_TYPE (arg1)) - && operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)), - TYPE_SIZE (TREE_TYPE (arg1)), flags))) - && types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1)) - && ((flags & OEP_ADDRESS_OF) - || (alias_ptr_types_compatible_p - (TREE_TYPE (TREE_OPERAND (arg0, 1)), - TREE_TYPE (TREE_OPERAND (arg1, 1))) - && (MR_DEPENDENCE_CLIQUE (arg0) - == MR_DEPENDENCE_CLIQUE (arg1)) - && (MR_DEPENDENCE_BASE (arg0) - == MR_DEPENDENCE_BASE (arg1)) - && (TYPE_ALIGN (TREE_TYPE (arg0)) - == TYPE_ALIGN (TREE_TYPE (arg1))))))) - return 0; + if (!(flags & OEP_ADDRESS_OF)) + { + /* Require equal access sizes */ + if (TYPE_SIZE (TREE_TYPE (arg0)) != TYPE_SIZE (TREE_TYPE (arg1)) + && (!TYPE_SIZE (TREE_TYPE (arg0)) + || !TYPE_SIZE (TREE_TYPE (arg1)) + || !operand_equal_p (TYPE_SIZE (TREE_TYPE (arg0)), + TYPE_SIZE (TREE_TYPE (arg1)), + flags & ~OEP_CONSTANT_ADDRESS_OF))) + return 0; + /* Verify that access happens in similar types. */ + if (!types_compatible_p (TREE_TYPE (arg0), TREE_TYPE (arg1))) + return 0; + /* Verify that accesses are TBAA compatible. */ + if ((flag_strict_aliasing + && !alias_ptr_types_compatible_p + (TREE_TYPE (TREE_OPERAND (arg0, 1)), + TREE_TYPE (TREE_OPERAND (arg1, 1)))) + || MR_DEPENDENCE_CLIQUE (arg0) + != MR_DEPENDENCE_CLIQUE (arg1) + || MR_DEPENDENCE_BASE (arg0) + != MR_DEPENDENCE_BASE (arg1)) + return 0; + } + /* Verify that alignment is compatible. */ + if (TYPE_ALIGN (TREE_TYPE (arg0)) + != TYPE_ALIGN (TREE_TYPE (arg1))) + return 0; flags &= ~(OEP_CONSTANT_ADDRESS_OF|OEP_ADDRESS_OF); return (OP_SAME (0) && OP_SAME (1) /* TARGET_MEM_REF require equal extra operands. */