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
This commit is contained in:
parent
5fe353c893
commit
d9df71be90
3 changed files with 34 additions and 20 deletions
|
@ -1,3 +1,10 @@
|
|||
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>
|
||||
|
||||
PR middle-end/78201
|
||||
|
|
|
@ -3918,7 +3918,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
|
|||
insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
|
||||
if (cmpstrn_icode != CODE_FOR_nothing)
|
||||
{
|
||||
tree len, len1, len2;
|
||||
tree len, len1, len2, len3;
|
||||
rtx arg1_rtx, arg2_rtx, arg3_rtx;
|
||||
rtx result;
|
||||
tree fndecl, fn;
|
||||
|
@ -3937,14 +3937,19 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
|
|||
if (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
|
||||
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
|
||||
but neither is constant. For now, assume they're equally cheap,
|
||||
unless one has side effects. If both strings have constant lengths,
|
||||
use the smaller. */
|
||||
|
||||
if (!len1)
|
||||
if (!len1 && !len2)
|
||||
len = len3;
|
||||
else if (!len1)
|
||||
len = len2;
|
||||
else if (!len2)
|
||||
len = len1;
|
||||
|
@ -3961,23 +3966,10 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
|
|||
else
|
||||
len = len2;
|
||||
|
||||
/* If both arguments have side effects, we cannot optimize. */
|
||||
if (!len || TREE_SIDE_EFFECTS (len))
|
||||
return NULL_RTX;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* If we are not using the given length, we must incorporate it here.
|
||||
The actual new length parameter will be MIN(len,arg3) in this case. */
|
||||
if (len != len3)
|
||||
len = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (len), len, len3);
|
||||
arg1_rtx = get_memory_rtx (arg1, len);
|
||||
arg2_rtx = get_memory_rtx (arg2, len);
|
||||
arg3_rtx = expand_normal (len);
|
||||
|
|
|
@ -16911,6 +16911,21 @@
|
|||
if (fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
|
||||
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];
|
||||
if (!REG_P (out))
|
||||
out = gen_reg_rtx (SImode);
|
||||
|
|
Loading…
Add table
Reference in a new issue