This patch adds a test to the cmpstrnsi pattern in i386.md so that it
will bail out (FAIL) if neither of the strings is a constant string. It
can only work as a proper strncmp if the length is not longer than both
of the strings. This change is required if expand_builtin_strncmp is
going to try expansion of strncmp when neither string argument is
constant. I've also changed the pattern to indicate that operand 3 may
be clobbered (if it happens to be in cx already).
2016-11-16 Aaron Sawdey <acsaw...@linux.vnet.ibm.com>
* config/i386/i386.md (cmpstrnsi): New test to bail out if neither
string input is a string constant. Clobber length argument.
--
Aaron Sawdey, Ph.D. acsaw...@linux.vnet.ibm.com
050-2/C113 (507) 253-7520 home: 507/263-0782
IBM Linux Technology Center - PPC Toolchain
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md (revision 242428)
+++ gcc/config/i386/i386.md (working copy)
@@ -16898,7 +16898,7 @@
[(set (match_operand:SI 0 "register_operand")
(compare:SI (match_operand:BLK 1 "general_operand")
(match_operand:BLK 2 "general_operand")))
- (use (match_operand 3 "general_operand"))
+ (clobber (match_operand 3 "general_operand"))
(use (match_operand 4 "immediate_operand"))]
""
{
@@ -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);