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.

-- 
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: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 241743)
+++ config/i386/i386.md	(working copy)
@@ -16909,6 +16909,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);

Reply via email to