Commit 10a0e2a9 by Jakub Jelinek Committed by Jakub Jelinek

re PR tree-optimization/86526 (ICE in builtin_memcpy_read_str, at builtins.c:3017)

	PR tree-optimization/86526
	* builtins.c (expand_builtin_memcmp): Formatting fixes.
	(inline_expand_builtin_string_cmp): Likewise.
	(inline_string_cmp): Likewise.  Use c_readstr instead of
	builtin_memcpy_read_str.  Add unit_mode temporary.

	* gcc.c-torture/compile/pr86526.c: New test.

From-SVN: r262750
parent ce04dc3f
2018-07-16 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/86526
* builtins.c (expand_builtin_memcmp): Formatting fixes.
(inline_expand_builtin_string_cmp): Likewise.
(inline_string_cmp): Likewise. Use c_readstr instead of
builtin_memcpy_read_str. Add unit_mode temporary.
2018-07-16 Bernd Edlinger <bernd.edlinger@hotmail.de> 2018-07-16 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR middle-end/86528 PR middle-end/86528
......
...@@ -4458,19 +4458,19 @@ expand_builtin_memcmp (tree exp, rtx target, bool result_eq) ...@@ -4458,19 +4458,19 @@ expand_builtin_memcmp (tree exp, rtx target, bool result_eq)
no_overflow = check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE, no_overflow = check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE,
len, /*maxread=*/NULL_TREE, size, len, /*maxread=*/NULL_TREE, size,
/*objsize=*/NULL_TREE); /*objsize=*/NULL_TREE);
if (no_overflow) if (no_overflow)
{ {
size = compute_objsize (arg2, 0); size = compute_objsize (arg2, 0);
no_overflow = check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE, no_overflow = check_access (exp, /*dst=*/NULL_TREE, /*src=*/NULL_TREE,
len, /*maxread=*/NULL_TREE, size, len, /*maxread=*/NULL_TREE, size,
/*objsize=*/NULL_TREE); /*objsize=*/NULL_TREE);
} }
/* Due to the performance benefit, always inline the calls first /* Due to the performance benefit, always inline the calls first
when result_eq is false. */ when result_eq is false. */
rtx result = NULL_RTX; rtx result = NULL_RTX;
if (!result_eq && fcode != BUILT_IN_BCMP && no_overflow) if (!result_eq && fcode != BUILT_IN_BCMP && no_overflow)
{ {
result = inline_expand_builtin_string_cmp (exp, target, true); result = inline_expand_builtin_string_cmp (exp, target, true);
if (result) if (result)
...@@ -6752,7 +6752,7 @@ expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore) ...@@ -6752,7 +6752,7 @@ expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
return target; return target;
} }
/* Expand a string compare operation using a sequence of char comparison /* Expand a string compare operation using a sequence of char comparison
to get rid of the calling overhead, with result going to TARGET if to get rid of the calling overhead, with result going to TARGET if
that's convenient. that's convenient.
...@@ -6761,7 +6761,7 @@ expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore) ...@@ -6761,7 +6761,7 @@ expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
LENGTH is the number of chars to compare; LENGTH is the number of chars to compare;
CONST_STR_N indicates which source string is the constant string; CONST_STR_N indicates which source string is the constant string;
IS_MEMCMP indicates whether it's a memcmp or strcmp. IS_MEMCMP indicates whether it's a memcmp or strcmp.
to: (assume const_str_n is 2, i.e., arg2 is a constant string) to: (assume const_str_n is 2, i.e., arg2 is a constant string)
target = var_str[0] - const_str[0]; target = var_str[0] - const_str[0];
...@@ -6776,41 +6776,38 @@ expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore) ...@@ -6776,41 +6776,38 @@ expand_builtin_goacc_parlevel_id_size (tree exp, rtx target, int ignore)
*/ */
static rtx static rtx
inline_string_cmp (rtx target, tree var_str, const char* const_str, inline_string_cmp (rtx target, tree var_str, const char *const_str,
unsigned HOST_WIDE_INT length, unsigned HOST_WIDE_INT length,
int const_str_n, machine_mode mode, int const_str_n, machine_mode mode,
bool is_memcmp) bool is_memcmp)
{ {
HOST_WIDE_INT offset = 0; HOST_WIDE_INT offset = 0;
rtx var_rtx_array rtx var_rtx_array
= get_memory_rtx (var_str, build_int_cst (unsigned_type_node,length)); = get_memory_rtx (var_str, build_int_cst (unsigned_type_node,length));
rtx var_rtx = NULL_RTX; rtx var_rtx = NULL_RTX;
rtx const_rtx = NULL_RTX; rtx const_rtx = NULL_RTX;
rtx result = target ? target : gen_reg_rtx (mode); rtx result = target ? target : gen_reg_rtx (mode);
rtx_code_label *ne_label = gen_label_rtx (); rtx_code_label *ne_label = gen_label_rtx ();
tree unit_type_node = is_memcmp ? unsigned_char_type_node : char_type_node; tree unit_type_node = is_memcmp ? unsigned_char_type_node : char_type_node;
scalar_int_mode unit_mode
= as_a <scalar_int_mode> TYPE_MODE (unit_type_node);
start_sequence (); start_sequence ();
for (unsigned HOST_WIDE_INT i = 0; i < length; i++) for (unsigned HOST_WIDE_INT i = 0; i < length; i++)
{ {
var_rtx var_rtx
= adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset); = adjust_address (var_rtx_array, TYPE_MODE (unit_type_node), offset);
const_rtx const_rtx = c_readstr (const_str + offset, unit_mode);
= builtin_memcpy_read_str (CONST_CAST (char *, const_str),
offset,
as_a <scalar_int_mode>
TYPE_MODE (unit_type_node));
rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx; rtx op0 = (const_str_n == 1) ? const_rtx : var_rtx;
rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx; rtx op1 = (const_str_n == 1) ? var_rtx : const_rtx;
result = expand_simple_binop (mode, MINUS, op0, op1, result = expand_simple_binop (mode, MINUS, op0, op1,
result, is_memcmp ? 1 : 0, OPTAB_WIDEN); result, is_memcmp ? 1 : 0, OPTAB_WIDEN);
if (i < length - 1) if (i < length - 1)
emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX, emit_cmp_and_jump_insns (result, CONST0_RTX (mode), NE, NULL_RTX,
mode, true, ne_label); mode, true, ne_label);
offset offset += GET_MODE_SIZE (unit_mode);
+= GET_MODE_SIZE (as_a <scalar_int_mode> TYPE_MODE (unit_type_node));
} }
emit_label (ne_label); emit_label (ne_label);
...@@ -6821,7 +6818,7 @@ inline_string_cmp (rtx target, tree var_str, const char* const_str, ...@@ -6821,7 +6818,7 @@ inline_string_cmp (rtx target, tree var_str, const char* const_str,
return result; return result;
} }
/* Inline expansion a call to str(n)cmp, with result going to /* Inline expansion a call to str(n)cmp, with result going to
TARGET if that's convenient. TARGET if that's convenient.
If the call is not been inlined, return NULL_RTX. */ If the call is not been inlined, return NULL_RTX. */
static rtx static rtx
...@@ -6833,7 +6830,7 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp) ...@@ -6833,7 +6830,7 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp)
bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP); bool is_ncmp = (fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_MEMCMP);
gcc_checking_assert (fcode == BUILT_IN_STRCMP gcc_checking_assert (fcode == BUILT_IN_STRCMP
|| fcode == BUILT_IN_STRNCMP || fcode == BUILT_IN_STRNCMP
|| fcode == BUILT_IN_MEMCMP); || fcode == BUILT_IN_MEMCMP);
tree arg1 = CALL_EXPR_ARG (exp, 0); tree arg1 = CALL_EXPR_ARG (exp, 0);
...@@ -6846,7 +6843,7 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp) ...@@ -6846,7 +6843,7 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp)
const char *src_str1 = c_getstr (arg1, &len1); const char *src_str1 = c_getstr (arg1, &len1);
const char *src_str2 = c_getstr (arg2, &len2); const char *src_str2 = c_getstr (arg2, &len2);
/* If neither strings is constant string, the call is not qualify. */ /* If neither strings is constant string, the call is not qualify. */
if (!src_str1 && !src_str2) if (!src_str1 && !src_str2)
return NULL_RTX; return NULL_RTX;
...@@ -6871,16 +6868,16 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp) ...@@ -6871,16 +6868,16 @@ inline_expand_builtin_string_cmp (tree exp, rtx target, bool is_memcmp)
if (is_ncmp && (len3 = tree_to_uhwi (len3_tree)) < length) if (is_ncmp && (len3 = tree_to_uhwi (len3_tree)) < length)
length = len3; length = len3;
/* If the length of the comparision is larger than the threshold, /* If the length of the comparision is larger than the threshold,
do nothing. */ do nothing. */
if (length > (unsigned HOST_WIDE_INT) if (length > (unsigned HOST_WIDE_INT)
PARAM_VALUE (BUILTIN_STRING_CMP_INLINE_LENGTH)) PARAM_VALUE (BUILTIN_STRING_CMP_INLINE_LENGTH))
return NULL_RTX; return NULL_RTX;
machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
/* Now, start inline expansion the call. */ /* Now, start inline expansion the call. */
return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1, return inline_string_cmp (target, (const_str_n == 1) ? arg2 : arg1,
(const_str_n == 1) ? src_str1 : src_str2, length, (const_str_n == 1) ? src_str1 : src_str2, length,
const_str_n, mode, is_memcmp); const_str_n, mode, is_memcmp);
} }
...@@ -7286,7 +7283,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, ...@@ -7286,7 +7283,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
return target; return target;
break; break;
/* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it /* Expand it as BUILT_IN_MEMCMP_EQ first. If not successful, change it
back to a BUILT_IN_STRCMP. Remember to delete the 3rd paramater back to a BUILT_IN_STRCMP. Remember to delete the 3rd paramater
when changing it to a strcmp call. */ when changing it to a strcmp call. */
case BUILT_IN_STRCMP_EQ: case BUILT_IN_STRCMP_EQ:
...@@ -7295,7 +7292,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, ...@@ -7295,7 +7292,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
return target; return target;
/* Change this call back to a BUILT_IN_STRCMP. */ /* Change this call back to a BUILT_IN_STRCMP. */
TREE_OPERAND (exp, 1) TREE_OPERAND (exp, 1)
= build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP)); = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRCMP));
/* Delete the last parameter. */ /* Delete the last parameter. */
...@@ -7321,7 +7318,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, ...@@ -7321,7 +7318,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
return target; return target;
/* Change it back to a BUILT_IN_STRNCMP. */ /* Change it back to a BUILT_IN_STRNCMP. */
TREE_OPERAND (exp, 1) TREE_OPERAND (exp, 1)
= build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP)); = build_fold_addr_expr (builtin_decl_explicit (BUILT_IN_STRNCMP));
/* FALLTHROUGH */ /* FALLTHROUGH */
......
2018-07-16 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/86526
* gcc.c-torture/compile/pr86526.c: New test.
2018-07-16 Carl Love <cel@us.ibm.com> 2018-07-16 Carl Love <cel@us.ibm.com>
* gcc.target/powerpc/divkc3-2.c: Add dg-require-effective-target * gcc.target/powerpc/divkc3-2.c: Add dg-require-effective-target
......
/* PR tree-optimization/86526 */
void
foo (char *x)
{
if (__builtin_memcmp (x, "\0a", 3))
__builtin_abort ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment