Commit d9df71be by Aaron Sawdey Committed by Aaron Sawdey

i386.md (cmpstrnsi): New test to bail out if neither string input is a string constant.

2016-11-17  Aaron Sawdey  <acsawdey@linux.vnet.ibm.com>

	* config/i386/i386.md (cmpstrnsi): New test to bail out if neither
	string input is a string constant.
	* builtins.c (expand_builtin_strncmp): Attempt expansion of strncmp
	via cmpstrnsi even if neither string is constant.

From-SVN: r242556
parent 5fe353c8
2016-11-17 Aaron Sawdey <acsawdey@linux.vnet.ibm.com>
* config/i386/i386.md (cmpstrnsi): New test to bail out if neither
string input is a string constant.
* builtins.c (expand_builtin_strncmp): Attempt expansion of strncmp
via cmpstrnsi even if neither string is constant.
2016-11-17 Jakub Jelinek <jakub@redhat.com> 2016-11-17 Jakub Jelinek <jakub@redhat.com>
PR middle-end/78201 PR middle-end/78201
...@@ -3918,7 +3918,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, ...@@ -3918,7 +3918,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode); insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
if (cmpstrn_icode != CODE_FOR_nothing) if (cmpstrn_icode != CODE_FOR_nothing)
{ {
tree len, len1, len2; tree len, len1, len2, len3;
rtx arg1_rtx, arg2_rtx, arg3_rtx; rtx arg1_rtx, arg2_rtx, arg3_rtx;
rtx result; rtx result;
tree fndecl, fn; tree fndecl, fn;
...@@ -3937,14 +3937,19 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, ...@@ -3937,14 +3937,19 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
if (len2) if (len2)
len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2); len2 = size_binop_loc (loc, PLUS_EXPR, ssize_int (1), len2);
len3 = fold_convert_loc (loc, sizetype, arg3);
/* If we don't have a constant length for the first, use the length /* If we don't have a constant length for the first, use the length
of the second, if we know it. We don't require a constant for of the second, if we know it. If neither string is constant length,
use the given length argument. We don't require a constant for
this case; some cost analysis could be done if both are available this case; some cost analysis could be done if both are available
but neither is constant. For now, assume they're equally cheap, but neither is constant. For now, assume they're equally cheap,
unless one has side effects. If both strings have constant lengths, unless one has side effects. If both strings have constant lengths,
use the smaller. */ use the smaller. */
if (!len1) if (!len1 && !len2)
len = len3;
else if (!len1)
len = len2; len = len2;
else if (!len2) else if (!len2)
len = len1; len = len1;
...@@ -3961,23 +3966,10 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, ...@@ -3961,23 +3966,10 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
else else
len = len2; len = len2;
/* If both arguments have side effects, we cannot optimize. */ /* If we are not using the given length, we must incorporate it here.
if (!len || TREE_SIDE_EFFECTS (len)) The actual new length parameter will be MIN(len,arg3) in this case. */
return NULL_RTX; if (len != len3)
len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
/* The actual new length parameter is MIN(len,arg3). */
len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len,
fold_convert_loc (loc, TREE_TYPE (len), arg3));
/* If we don't have POINTER_TYPE, call the function. */
if (arg1_align == 0 || arg2_align == 0)
return NULL_RTX;
/* Stabilize the arguments in case gen_cmpstrnsi fails. */
arg1 = builtin_save_expr (arg1);
arg2 = builtin_save_expr (arg2);
len = builtin_save_expr (len);
arg1_rtx = get_memory_rtx (arg1, len); arg1_rtx = get_memory_rtx (arg1, len);
arg2_rtx = get_memory_rtx (arg2, len); arg2_rtx = get_memory_rtx (arg2, len);
arg3_rtx = expand_normal (len); arg3_rtx = expand_normal (len);
......
...@@ -16911,6 +16911,21 @@ ...@@ -16911,6 +16911,21 @@
if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
FAIL; FAIL;
/* One of the strings must be a constant. If so, expand_builtin_strncmp()
will have rewritten the length arg to be the minimum of the const string
length and the actual length arg. If both strings are the same and
shorter than the length arg, repz cmpsb will not stop at the 0 byte and
will incorrectly base the results on chars past the 0 byte. */
tree t1 = MEM_EXPR (operands[1]);
tree t2 = MEM_EXPR (operands[2]);
if (!((t1 && TREE_CODE (t1) == MEM_REF
&& TREE_CODE (TREE_OPERAND (t1, 0)) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (t1, 0), 0)) == STRING_CST)
|| (t2 && TREE_CODE (t2) == MEM_REF
&& TREE_CODE (TREE_OPERAND (t2, 0)) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (TREE_OPERAND (t2, 0), 0)) == STRING_CST)))
FAIL;
out = operands[0]; out = operands[0];
if (!REG_P (out)) if (!REG_P (out))
out = gen_reg_rtx (SImode); out = gen_reg_rtx (SImode);
......
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