Index: builtins.c =================================================================== --- builtins.c (revision 114340) +++ builtins.c (working copy) @@ -47,6 +47,7 @@ Software Foundation, 51 Franklin Street, #include "langhooks.h" #include "basic-block.h" #include "tree-mudflap.h" +#include "tree-ssa-propagate.h" #ifndef PAD_VARARGS_DOWN #define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN @@ -163,7 +164,7 @@ static tree fold_builtin_int_roundingfn static tree fold_builtin_bitop (tree, tree); static tree fold_builtin_memcpy (tree, tree); static tree fold_builtin_mempcpy (tree, tree, int); -static tree fold_builtin_memmove (tree, tree); +static tree fold_builtin_memmove (tree, tree, bool); static tree fold_builtin_strchr (tree, tree); static tree fold_builtin_memcmp (tree); static tree fold_builtin_strcmp (tree); @@ -3017,7 +3018,7 @@ expand_builtin_memmove (tree arglist, tr unsigned int src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT); unsigned int dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT); - tree result = fold_builtin_memmove (arglist, type); + tree result = fold_builtin_memmove (arglist, type, false); if (result) return expand_expr (result, target, mode, EXPAND_NORMAL); @@ -7835,17 +7836,29 @@ fold_builtin_mempcpy (tree arglist, tree NULL_TREE if no simplification can be made. */ static tree -fold_builtin_memmove (tree arglist, tree type) +fold_builtin_memmove (tree arglist, tree type, bool bcopy_p) { tree dest, src, len; + tree arg0, arg1; if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return 0; - dest = TREE_VALUE (arglist); - src = TREE_VALUE (TREE_CHAIN (arglist)); + arg0 = TREE_VALUE (arglist); + arg1 = TREE_VALUE (TREE_CHAIN (arglist)); len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))); + + if (bcopy_p) + { + src = arg0; + dest = arg1; + } + else + { + src = arg1; + dest = arg0; + } /* If the LEN parameter is zero, return DEST. */ if (integer_zerop (len)) @@ -7854,6 +7867,23 @@ fold_builtin_memmove (tree arglist, tree /* If SRC and DEST are the same (and not volatile), return DEST. */ if (operand_equal_p (src, dest, 0)) return omit_one_operand (type, dest, len); + + /* If src is categorized for a readonly section or the length is one, + we can use normal memcpy. */ + if (readonly_data_expr (src) || integer_onep (len)) + { + tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; + if (!fn) + return 0; + if (bcopy_p) + { + arglist = build_tree_list (NULL_TREE, len); + arglist = tree_cons (NULL_TREE, src, arglist); + arglist = tree_cons (NULL_TREE, dest, arglist); + } + fn = build_function_call_expr (fn, arglist); + return fn; + } return 0; } @@ -8752,8 +8782,9 @@ fold_builtin_1 (tree fndecl, tree arglis case BUILT_IN_MEMPCPY: return fold_builtin_mempcpy (arglist, type, /*endp=*/1); + case BUILT_IN_BCOPY: case BUILT_IN_MEMMOVE: - return fold_builtin_memmove (arglist, type); + return fold_builtin_memmove (arglist, type, fcode == BUILT_IN_BCOPY); CASE_FLT_FN (BUILT_IN_SIGNBIT): return fold_builtin_signbit (fndecl, arglist); @@ -8958,6 +8989,13 @@ static bool readonly_data_expr (tree exp) { STRIP_NOPS (exp); + + if (TREE_CODE (exp) == SSA_NAME) + { + tree tmp = SSA_NAME_DEF_STMT (exp); + tmp = get_rhs (tmp); + return readonly_data_expr (tmp); + } if (TREE_CODE (exp) != ADDR_EXPR) return false; Index: tree-ssa.c =================================================================== --- tree-ssa.c (revision 114340) +++ tree-ssa.c (working copy) @@ -934,19 +934,6 @@ tree_ssa_useless_type_conversion_1 (tree if (lang_hooks.types_compatible_p (inner_type, outer_type)) return true; - /* If both types are pointers and the outer type is a (void *), then - the conversion is not necessary. The opposite is not true since - that conversion would result in a loss of information if the - equivalence was used. Consider an indirect function call where - we need to know the exact type of the function to correctly - implement the ABI. */ - else if (POINTER_TYPE_P (inner_type) - && POINTER_TYPE_P (outer_type) - && TYPE_REF_CAN_ALIAS_ALL (inner_type) - == TYPE_REF_CAN_ALIAS_ALL (outer_type) - && TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE) - return true; - /* Don't lose casts between pointers to volatile and non-volatile qualified types. Doing so would result in changing the semantics of later accesses. */ Index: Makefile.in =================================================================== --- Makefile.in (revision 114340) +++ Makefile.in (working copy) @@ -2212,7 +2212,7 @@ builtins.o : builtins.c $(CONFIG_H) $(SY $(EXPR_H) $(OPTABS_H) insn-config.h $(RECOG_H) output.h typeclass.h \ hard-reg-set.h toplev.h hard-reg-set.h except.h $(TM_P_H) $(PREDICT_H) \ libfuncs.h $(REAL_H) langhooks.h $(BASIC_BLOCK_H) tree-mudflap.h \ - $(BUILTINS_DEF) $(MACHMODE_H) + $(BUILTINS_DEF) $(MACHMODE_H) tree-ssa-propagate.h calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) langhooks.h $(TARGET_H) \ libfuncs.h $(REGS_H) toplev.h output.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_P_H) \