builtins.c (expand_builtin_strcmp): Defend against the possibility that gen_cmpstrsi...
authorRoger Sayle <roger@eyesopen.com>
Sat, 11 Oct 2003 21:11:29 +0000 (21:11 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Sat, 11 Oct 2003 21:11:29 +0000 (21:11 +0000)
* builtins.c (expand_builtin_strcmp): Defend against the possibility
that gen_cmpstrsi may fail: Stabilize the argument list against
re-evaluation and expand the library call directly using this saved
argument list if a cmpstrsi sequence can't be generated.
(expand_builtin_strncmp): Likewise.

* config/i386/i386.md (cmpstrsi, movstrsi): Disable with -Os.

* gcc.c-torture/execute/string-opt-8.c: Don't test optimizations
that inline strncmp as cmpstrsi on i386 when compiled with -Os.

From-SVN: r72380

gcc/ChangeLog
gcc/builtins.c
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/string-opt-8.c

index 4251bf3a741ff062220b4b10f9b5228d4f8c7fd5..a05b7260498b2780241297e2f4c9966ae781d3d6 100644 (file)
@@ -1,3 +1,13 @@
+2003-10-11  Roger Sayle  <roger@eyesopen.com>
+
+       * builtins.c (expand_builtin_strcmp): Defend against the possibility
+       that gen_cmpstrsi may fail: Stabilize the argument list against
+       re-evaluation and expand the library call directly using this saved
+       argument list if a cmpstrsi sequence can't be generated.
+       (expand_builtin_strncmp): Likewise.
+
+       * config/i386/i386.md (cmpstrsi, movstrsi): Disable with -Os.
+
 2003-10-11  Roger Sayle  <roger@eyesopen.com>
 
        PR optimization/12260
index 1af2a2d0889a6167e4b7061b7fb927dd5bd25d09..0214edf41986219bc99be602c4c62f583336a921 100644 (file)
@@ -3281,6 +3281,7 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
     tree len, len1, len2;
     rtx arg1_rtx, arg2_rtx, arg3_rtx;
     rtx result, insn;
+    tree fndecl;
 
     int arg1_align
       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
@@ -3336,24 +3337,36 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
           && REGNO (result) >= FIRST_PSEUDO_REGISTER))
       result = gen_reg_rtx (insn_mode);
 
+    /* Stabilize the arguments in case gen_cmpstrsi fails.  */
+    arg1 = save_expr (arg1);
+    arg2 = save_expr (arg2);
+
     arg1_rtx = get_memory_rtx (arg1);
     arg2_rtx = get_memory_rtx (arg2);
     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
     insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
                         GEN_INT (MIN (arg1_align, arg2_align)));
-    if (!insn)
-      return 0;
-
-    emit_insn (insn);
+    if (insn)
+      {
+       emit_insn (insn);
+
+       /* Return the value in the proper mode for this function.  */
+       mode = TYPE_MODE (TREE_TYPE (exp));
+       if (GET_MODE (result) == mode)
+         return result;
+       if (target == 0)
+         return convert_to_mode (mode, result, 0);
+       convert_move (target, result, 0);
+       return target;
+      }
 
-    /* Return the value in the proper mode for this function.  */
-    mode = TYPE_MODE (TREE_TYPE (exp));
-    if (GET_MODE (result) == mode)
-      return result;
-    if (target == 0)
-      return convert_to_mode (mode, result, 0);
-    convert_move (target, result, 0);
-    return target;
+    /* Expand the library call ourselves using a stabilized argument
+       list to avoid re-evaluating the function's arguments twice.  */
+    arglist = build_tree_list (NULL_TREE, arg2);
+    arglist = tree_cons (NULL_TREE, arg1, arglist);
+    fndecl = get_callee_fndecl (exp);
+    exp = build_function_call_expr (fndecl, arglist);
+    return expand_call (exp, target, target == const0_rtx);
   }
 #endif
   return 0;
@@ -3436,6 +3449,7 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
     tree len, len1, len2;
     rtx arg1_rtx, arg2_rtx, arg3_rtx;
     rtx result, insn;
+    tree fndecl;
 
     int arg1_align
       = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
@@ -3494,24 +3508,38 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
           && REGNO (result) >= FIRST_PSEUDO_REGISTER))
       result = gen_reg_rtx (insn_mode);
 
+    /* Stabilize the arguments in case gen_cmpstrsi fails.  */
+    arg1 = save_expr (arg1);
+    arg2 = save_expr (arg2);
+    len = save_expr (len);
+
     arg1_rtx = get_memory_rtx (arg1);
     arg2_rtx = get_memory_rtx (arg2);
     arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
     insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
                         GEN_INT (MIN (arg1_align, arg2_align)));
-    if (!insn)
-      return 0;
-
-    emit_insn (insn);
+    if (insn)
+      {
+       emit_insn (insn);
+
+       /* Return the value in the proper mode for this function.  */
+       mode = TYPE_MODE (TREE_TYPE (exp));
+       if (GET_MODE (result) == mode)
+         return result;
+       if (target == 0)
+         return convert_to_mode (mode, result, 0);
+       convert_move (target, result, 0);
+       return target;
+      }
 
-    /* Return the value in the proper mode for this function.  */
-    mode = TYPE_MODE (TREE_TYPE (exp));
-    if (GET_MODE (result) == mode)
-      return result;
-    if (target == 0)
-      return convert_to_mode (mode, result, 0);
-    convert_move (target, result, 0);
-    return target;
+    /* Expand the library call ourselves using a stabilized argument
+       list to avoid re-evaluating the function's arguments twice.  */
+    arglist = build_tree_list (NULL_TREE, len);
+    arglist = tree_cons (NULL_TREE, arg2, arglist);
+    arglist = tree_cons (NULL_TREE, arg1, arglist);
+    fndecl = get_callee_fndecl (exp);
+    exp = build_function_call_expr (fndecl, arglist);
+    return expand_call (exp, target, target == const0_rtx);
   }
 #endif
   return 0;
index a1f40e156a0b7fe4248e819ef66edfab8a8925cd..39a8a2cc8c70b93fea67f7fd1d12ddc3e48c0f8f 100644 (file)
    (use (match_operand:BLK 1 "memory_operand" ""))
    (use (match_operand:SI 2 "nonmemory_operand" ""))
    (use (match_operand:SI 3 "const_int_operand" ""))]
-  ""
+  "! optimize_size"
 {
  if (ix86_expand_movstr (operands[0], operands[1], operands[2], operands[3]))
    DONE;
                    (match_operand:BLK 2 "general_operand" "")))
    (use (match_operand 3 "general_operand" ""))
    (use (match_operand 4 "immediate_operand" ""))]
-  ""
+  "! optimize_size"
 {
   rtx addr1, addr2, out, outlow, count, countreg, align;
 
index ad9bafce35c0c927db38bd4086dba81957daf1a4..92b96a26ddf7088b81b81d5cb480439568d6bbf2 100644 (file)
@@ -1,3 +1,8 @@
+2003-10-11  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.c-torture/execute/string-opt-8.c: Don't test optimizations
+       that inline strncmp as cmpstrsi on i386 when compiled with -Os.
+
 2003-10-11  Roger Sayle  <roger@eyesopen.com>
 
        PR optimization/12260
index 434de33db9ba64f819e8041f28327a8ed686b611..2316fce87cab3a0ec34efd8b6a42872dca4e04cf 100644 (file)
@@ -65,7 +65,7 @@ int main ()
   s2 = s1; s3 = s1+4;
   if (strncmp (++s2, ++s3+2, 1) >= 0 || s2 != s1+1 || s3 != s1+5)
     abort();
-#if !defined(__OPTIMIZE__) || defined(__i386__)
+#if !defined(__OPTIMIZE__) || (defined(__i386__) && !defined(__OPTIMIZE_SIZE__))
   /* These tests work on platforms which support cmpstrsi.  We test it
      at -O0 on all platforms to ensure the strncmp logic is correct.  */
   s2 = s1;