diff options
author | Martin Liska <mliska@suse.cz> | 2017-08-01 19:10:38 +0200 |
---|---|---|
committer | Martin Liska <marxin@gcc.gnu.org> | 2017-08-01 17:10:38 +0000 |
commit | 7d3eecca8d4cb8d11667a3998820200a439a899a (patch) | |
tree | ed73b5dd4f6c755566a7308b29172ebce2e4cf31 /gcc/builtins.c | |
parent | 32341663e1ead3f8884add1d09c705d1aa8465ce (diff) | |
download | gcc-7d3eecca8d4cb8d11667a3998820200a439a899a.zip gcc-7d3eecca8d4cb8d11667a3998820200a439a899a.tar.gz gcc-7d3eecca8d4cb8d11667a3998820200a439a899a.tar.bz2 |
Revert r250771
2017-08-01 Martin Liska <mliska@suse.cz>
Revert r250771
Make mempcpy more optimal (PR middle-end/70140).
2017-08-01 Martin Liska <mliska@suse.cz>
Revert r250771
Make mempcpy more optimal (PR middle-end/70140).
From-SVN: r250788
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 272 |
1 files changed, 165 insertions, 107 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index b3cc58f..2deef72 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -121,12 +121,12 @@ static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_mode); static rtx expand_builtin_memchr (tree, rtx); static rtx expand_builtin_memcpy (tree, rtx); static rtx expand_builtin_memcpy_with_bounds (tree, rtx); -static rtx expand_builtin_memory_copy_args (tree dest, tree src, tree len, - rtx target, tree exp, int endp); +static rtx expand_builtin_memcpy_args (tree, tree, tree, rtx, tree); static rtx expand_builtin_memmove (tree, rtx); -static rtx expand_builtin_mempcpy (tree, rtx); -static rtx expand_builtin_mempcpy_with_bounds (tree, rtx); -static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, tree, int); +static rtx expand_builtin_mempcpy (tree, rtx, machine_mode); +static rtx expand_builtin_mempcpy_with_bounds (tree, rtx, machine_mode); +static rtx expand_builtin_mempcpy_args (tree, tree, tree, rtx, + machine_mode, int, tree); static rtx expand_builtin_strcat (tree, rtx); static rtx expand_builtin_strcpy (tree, rtx); static rtx expand_builtin_strcpy_args (tree, tree, rtx); @@ -2961,6 +2961,81 @@ determine_block_size (tree len, rtx len_rtx, GET_MODE_MASK (GET_MODE (len_rtx))); } +/* Helper function to do the actual work for expand_builtin_memcpy. */ + +static rtx +expand_builtin_memcpy_args (tree dest, tree src, tree len, rtx target, tree exp) +{ + const char *src_str; + unsigned int src_align = get_pointer_alignment (src); + unsigned int dest_align = get_pointer_alignment (dest); + rtx dest_mem, src_mem, dest_addr, len_rtx; + HOST_WIDE_INT expected_size = -1; + unsigned int expected_align = 0; + unsigned HOST_WIDE_INT min_size; + unsigned HOST_WIDE_INT max_size; + unsigned HOST_WIDE_INT probable_max_size; + + /* If DEST is not a pointer type, call the normal function. */ + if (dest_align == 0) + return NULL_RTX; + + /* If either SRC is not a pointer type, don't do this + operation in-line. */ + if (src_align == 0) + return NULL_RTX; + + if (currently_expanding_gimple_stmt) + stringop_block_profile (currently_expanding_gimple_stmt, + &expected_align, &expected_size); + + if (expected_align < dest_align) + expected_align = dest_align; + dest_mem = get_memory_rtx (dest, len); + set_mem_align (dest_mem, dest_align); + len_rtx = expand_normal (len); + determine_block_size (len, len_rtx, &min_size, &max_size, + &probable_max_size); + src_str = c_getstr (src); + + /* If SRC is a string constant and block move would be done + by pieces, we can avoid loading the string from memory + and only stored the computed constants. */ + if (src_str + && CONST_INT_P (len_rtx) + && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 + && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, + CONST_CAST (char *, src_str), + dest_align, false)) + { + dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), + builtin_memcpy_read_str, + CONST_CAST (char *, src_str), + dest_align, false, 0); + dest_mem = force_operand (XEXP (dest_mem, 0), target); + dest_mem = convert_memory_address (ptr_mode, dest_mem); + return dest_mem; + } + + src_mem = get_memory_rtx (src, len); + set_mem_align (src_mem, src_align); + + /* Copy word part most expediently. */ + dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, + CALL_EXPR_TAILCALL (exp) + ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, + expected_align, expected_size, + min_size, max_size, probable_max_size); + + if (dest_addr == 0) + { + dest_addr = force_operand (XEXP (dest_mem, 0), target); + dest_addr = convert_memory_address (ptr_mode, dest_addr); + } + + return dest_addr; +} + /* Try to verify that the sizes and lengths of the arguments to a string manipulation function given by EXP are within valid bounds and that the operation does not lead to buffer overflow. Arguments other than @@ -3303,8 +3378,7 @@ expand_builtin_memcpy (tree exp, rtx target) check_memop_sizes (exp, dest, src, len); - return expand_builtin_memory_copy_args (dest, src, len, target, exp, - /*endp=*/ 0); + return expand_builtin_memcpy_args (dest, src, len, target, exp); } /* Check a call EXP to the memmove built-in for validity. @@ -3344,8 +3418,7 @@ expand_builtin_memcpy_with_bounds (tree exp, rtx target) tree dest = CALL_EXPR_ARG (exp, 0); tree src = CALL_EXPR_ARG (exp, 2); tree len = CALL_EXPR_ARG (exp, 4); - rtx res = expand_builtin_memory_copy_args (dest, src, len, target, exp, - /*end_p=*/ 0); + rtx res = expand_builtin_memcpy_args (dest, src, len, target, exp); /* Return src bounds with the result. */ if (res) @@ -3367,7 +3440,7 @@ expand_builtin_memcpy_with_bounds (tree exp, rtx target) stpcpy. */ static rtx -expand_builtin_mempcpy (tree exp, rtx target) +expand_builtin_mempcpy (tree exp, rtx target, machine_mode mode) { if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) @@ -3384,7 +3457,8 @@ expand_builtin_mempcpy (tree exp, rtx target) return NULL_RTX; return expand_builtin_mempcpy_args (dest, src, len, - target, exp, /*endp=*/ 1); + target, mode, /*endp=*/ 1, + exp); } /* Expand an instrumented call EXP to the mempcpy builtin. @@ -3393,7 +3467,7 @@ expand_builtin_mempcpy (tree exp, rtx target) mode MODE if that's convenient). */ static rtx -expand_builtin_mempcpy_with_bounds (tree exp, rtx target) +expand_builtin_mempcpy_with_bounds (tree exp, rtx target, machine_mode mode) { if (!validate_arglist (exp, POINTER_TYPE, POINTER_BOUNDS_TYPE, @@ -3406,7 +3480,7 @@ expand_builtin_mempcpy_with_bounds (tree exp, rtx target) tree src = CALL_EXPR_ARG (exp, 2); tree len = CALL_EXPR_ARG (exp, 4); rtx res = expand_builtin_mempcpy_args (dest, src, len, target, - exp, 1); + mode, 1, exp); /* Return src bounds with the result. */ if (res) @@ -3419,111 +3493,94 @@ expand_builtin_mempcpy_with_bounds (tree exp, rtx target) } } -/* Helper function to do the actual work for expand of memory copy family - functions (memcpy, mempcpy, stpcpy). Expansing should assign LEN bytes - of memory from SRC to DEST and assign to TARGET if convenient. - If ENDP is 0 return the - destination pointer, if ENDP is 1 return the end pointer ala - mempcpy, and if ENDP is 2 return the end pointer minus one ala - stpcpy. */ +/* Helper function to do the actual work for expand_builtin_mempcpy. The + arguments to the builtin_mempcpy call DEST, SRC, and LEN are broken out + so that this can also be called without constructing an actual CALL_EXPR. + The other arguments and return value are the same as for + expand_builtin_mempcpy. */ static rtx -expand_builtin_memory_copy_args (tree dest, tree src, tree len, - rtx target, tree exp, int endp) +expand_builtin_mempcpy_args (tree dest, tree src, tree len, + rtx target, machine_mode mode, int endp, + tree orig_exp) { - const char *src_str; - unsigned int src_align = get_pointer_alignment (src); - unsigned int dest_align = get_pointer_alignment (dest); - rtx dest_mem, src_mem, dest_addr, len_rtx; - HOST_WIDE_INT expected_size = -1; - unsigned int expected_align = 0; - unsigned HOST_WIDE_INT min_size; - unsigned HOST_WIDE_INT max_size; - unsigned HOST_WIDE_INT probable_max_size; - - /* If DEST is not a pointer type, call the normal function. */ - if (dest_align == 0) - return NULL_RTX; - - /* If either SRC is not a pointer type, don't do this - operation in-line. */ - if (src_align == 0) - return NULL_RTX; - - if (currently_expanding_gimple_stmt) - stringop_block_profile (currently_expanding_gimple_stmt, - &expected_align, &expected_size); - - if (expected_align < dest_align) - expected_align = dest_align; - dest_mem = get_memory_rtx (dest, len); - set_mem_align (dest_mem, dest_align); - len_rtx = expand_normal (len); - determine_block_size (len, len_rtx, &min_size, &max_size, - &probable_max_size); - src_str = c_getstr (src); + tree fndecl = get_callee_fndecl (orig_exp); - /* If SRC is a string constant and block move would be done - by pieces, we can avoid loading the string from memory - and only stored the computed constants. */ - if (src_str - && CONST_INT_P (len_rtx) - && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 - && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, - CONST_CAST (char *, src_str), - dest_align, false)) + /* If return value is ignored, transform mempcpy into memcpy. */ + if (target == const0_rtx + && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP + && builtin_decl_implicit_p (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP)) { - dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), - builtin_memcpy_read_str, - CONST_CAST (char *, src_str), - dest_align, false, endp); - dest_mem = force_operand (XEXP (dest_mem, 0), target); - dest_mem = convert_memory_address (ptr_mode, dest_mem); - return dest_mem; + tree fn = builtin_decl_implicit (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK_CHKP); + tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3, + dest, src, len); + return expand_expr (result, target, mode, EXPAND_NORMAL); + } + else if (target == const0_rtx + && builtin_decl_implicit_p (BUILT_IN_MEMCPY)) + { + tree fn = builtin_decl_implicit (BUILT_IN_MEMCPY); + tree result = build_call_nofold_loc (UNKNOWN_LOCATION, fn, 3, + dest, src, len); + return expand_expr (result, target, mode, EXPAND_NORMAL); } + else + { + const char *src_str; + unsigned int src_align = get_pointer_alignment (src); + unsigned int dest_align = get_pointer_alignment (dest); + rtx dest_mem, src_mem, len_rtx; - src_mem = get_memory_rtx (src, len); - set_mem_align (src_mem, src_align); + /* If either SRC or DEST is not a pointer type, don't do this + operation in-line. */ + if (dest_align == 0 || src_align == 0) + return NULL_RTX; - /* Copy word part most expediently. */ - dest_addr = emit_block_move_hints (dest_mem, src_mem, len_rtx, - CALL_EXPR_TAILCALL (exp) - ? BLOCK_OP_TAILCALL : BLOCK_OP_NORMAL, - expected_align, expected_size, - min_size, max_size, probable_max_size); + /* If LEN is not constant, call the normal function. */ + if (! tree_fits_uhwi_p (len)) + return NULL_RTX; - if (dest_addr == 0) - { - dest_addr = force_operand (XEXP (dest_mem, 0), target); - dest_addr = convert_memory_address (ptr_mode, dest_addr); - return dest_addr; - } + len_rtx = expand_normal (len); + src_str = c_getstr (src); - if (endp) - { - rtx tmp1 = gen_reg_rtx (ptr_mode); - dest_addr = emit_move_insn (tmp1, gen_rtx_PLUS (ptr_mode, dest_addr, - len_rtx)); - /* stpcpy pointer to last byte. */ - if (endp == 2) + /* If SRC is a string constant and block move would be done + by pieces, we can avoid loading the string from memory + and only stored the computed constants. */ + if (src_str + && CONST_INT_P (len_rtx) + && (unsigned HOST_WIDE_INT) INTVAL (len_rtx) <= strlen (src_str) + 1 + && can_store_by_pieces (INTVAL (len_rtx), builtin_memcpy_read_str, + CONST_CAST (char *, src_str), + dest_align, false)) { - rtx tmp2 = emit_move_insn (tmp1, gen_rtx_MINUS (ptr_mode, dest_addr, - const1_rtx)); - tmp1 = tmp2; + dest_mem = get_memory_rtx (dest, len); + set_mem_align (dest_mem, dest_align); + dest_mem = store_by_pieces (dest_mem, INTVAL (len_rtx), + builtin_memcpy_read_str, + CONST_CAST (char *, src_str), + dest_align, false, endp); + dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); + dest_mem = convert_memory_address (ptr_mode, dest_mem); + return dest_mem; } - emit_move_insn (target, force_operand (tmp1, NULL_RTX)); - return target; - } - return dest_addr; -} + if (CONST_INT_P (len_rtx) + && can_move_by_pieces (INTVAL (len_rtx), + MIN (dest_align, src_align))) + { + dest_mem = get_memory_rtx (dest, len); + set_mem_align (dest_mem, dest_align); + src_mem = get_memory_rtx (src, len); + set_mem_align (src_mem, src_align); + dest_mem = move_by_pieces (dest_mem, src_mem, INTVAL (len_rtx), + MIN (dest_align, src_align), endp); + dest_mem = force_operand (XEXP (dest_mem, 0), NULL_RTX); + dest_mem = convert_memory_address (ptr_mode, dest_mem); + return dest_mem; + } -static rtx -expand_builtin_mempcpy_args (tree dest, tree src, tree len, - rtx target, tree orig_exp, int endp) -{ - return expand_builtin_memory_copy_args (dest, src, len, target, orig_exp, - endp); + return NULL_RTX; + } } /* Expand into a movstr instruction, if one is available. Return NULL_RTX if @@ -3681,7 +3738,8 @@ expand_builtin_stpcpy (tree exp, rtx target, machine_mode mode) lenp1 = size_binop_loc (loc, PLUS_EXPR, len, ssize_int (1)); ret = expand_builtin_mempcpy_args (dst, src, lenp1, - target, exp, /*endp=*/2); + target, mode, /*endp=*/2, + exp); if (ret) return ret; @@ -6844,7 +6902,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, break; case BUILT_IN_MEMPCPY: - target = expand_builtin_mempcpy (exp, target); + target = expand_builtin_mempcpy (exp, target, mode); if (target) return target; break; @@ -7623,7 +7681,7 @@ expand_builtin_with_bounds (tree exp, rtx target, break; case BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK_CHKP: - target = expand_builtin_mempcpy_with_bounds (exp, target); + target = expand_builtin_mempcpy_with_bounds (exp, target, mode); if (target) return target; break; |