builtins.c (expand_cmpstr, [...]): New functions.
authorRichard Sandiford <richard.sandiford@arm.com>
Mon, 24 Aug 2015 17:59:07 +0000 (17:59 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Mon, 24 Aug 2015 17:59:07 +0000 (17:59 +0000)
gcc/
* builtins.c (expand_cmpstr, expand_cmpstrn): New functions.
(expand_builtin_strcmp, expand_builtin_strncmp): Use them.  Remove
references to HAVE_cmpstr{,n}si and CODE_FOR_cmpstr{,n}si.
* config/m32c/blkmov.md (cmpstrsi): Fix predicates of operands 1 and 2.
Add predicates for operands 0 and 3.
* config/rx/rx.md (cmpstrnsi): Remove force_operand for the length
operand.
* config/sh/sh.md (cmpstrnsi): Change the length predicate from
immediate_operand to nonmemory_operand.

From-SVN: r227140

gcc/ChangeLog
gcc/builtins.c
gcc/config/m32c/blkmov.md
gcc/config/rx/rx.md
gcc/config/sh/sh.md

index 5ebafe1fbcc92510eb661d4db17412693382af50..e89afb3e68f22a1aca0a662c016c21d99e95b719 100644 (file)
@@ -1,3 +1,15 @@
+2015-08-24  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * builtins.c (expand_cmpstr, expand_cmpstrn): New functions.
+       (expand_builtin_strcmp, expand_builtin_strncmp): Use them.  Remove
+       references to HAVE_cmpstr{,n}si and CODE_FOR_cmpstr{,n}si.
+       * config/m32c/blkmov.md (cmpstrsi): Fix predicates of operands 1 and 2.
+       Add predicates for operands 0 and 3.
+       * config/rx/rx.md (cmpstrnsi): Remove force_operand for the length
+       operand.
+       * config/sh/sh.md (cmpstrnsi): Change the length predicate from
+       immediate_operand to nonmemory_operand.
+
 2015-08-24  Richard Sandiford  <richard.sandiford@arm.com>
 
        * df-scan.c (df_insn_info_init_fields): New function, split out
index 76c16fa394095a2935040a1cc1b9f82322b1c8b4..ea8ffe2ba6d54fea8a467226dbc30164d4840345 100644 (file)
@@ -3917,6 +3917,53 @@ expand_builtin_bzero (tree exp)
                                     const0_rtx, VOIDmode, exp);
 }
 
+/* Try to expand cmpstr operation ICODE with the given operands.
+   Return the result rtx on success, otherwise return null.  */
+
+static rtx
+expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
+              HOST_WIDE_INT align)
+{
+  machine_mode insn_mode = insn_data[icode].operand[0].mode;
+
+  if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
+    target = NULL_RTX;
+
+  struct expand_operand ops[4];
+  create_output_operand (&ops[0], target, insn_mode);
+  create_fixed_operand (&ops[1], arg1_rtx);
+  create_fixed_operand (&ops[2], arg2_rtx);
+  create_integer_operand (&ops[3], align);
+  if (maybe_expand_insn (icode, 4, ops))
+    return ops[0].value;
+  return NULL_RTX;
+}
+
+/* Try to expand cmpstrn operation ICODE with the given operands.
+   ARG3_TYPE is the type of ARG3_RTX.  Return the result rtx on success,
+   otherwise return null.  */
+
+static rtx
+expand_cmpstrn (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx,
+               tree arg3_type, rtx arg3_rtx, HOST_WIDE_INT align)
+{
+  machine_mode insn_mode = insn_data[icode].operand[0].mode;
+
+  if (target && (!REG_P (target) || HARD_REGISTER_P (target)))
+    target = NULL_RTX;
+
+  struct expand_operand ops[5];
+  create_output_operand (&ops[0], target, insn_mode);
+  create_fixed_operand (&ops[1], arg1_rtx);
+  create_fixed_operand (&ops[2], arg2_rtx);
+  create_convert_operand_from (&ops[3], arg3_rtx, TYPE_MODE (arg3_type),
+                              TYPE_UNSIGNED (arg3_type));
+  create_integer_operand (&ops[4], align);
+  if (maybe_expand_insn (icode, 5, ops))
+    return ops[0].value;
+  return NULL_RTX;
+}
+
 /* Expand expression EXP, which is a call to the memcmp built-in function.
    Return NULL_RTX if we failed and the caller should emit a normal call,
    otherwise try to get the result in TARGET, if convenient (and in mode
@@ -4019,15 +4066,15 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
   if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
     return NULL_RTX;
 
-#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi
-  if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing
-      || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing)
+  insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode);
+  insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
+  if (cmpstr_icode != CODE_FOR_nothing || cmpstrn_icode != CODE_FOR_nothing)
     {
       rtx arg1_rtx, arg2_rtx;
-      rtx result, insn = NULL_RTX;
       tree fndecl, fn;
       tree arg1 = CALL_EXPR_ARG (exp, 0);
       tree arg2 = CALL_EXPR_ARG (exp, 1);
+      rtx result = NULL_RTX;
 
       unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
       unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
@@ -4043,33 +4090,17 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
       arg1_rtx = get_memory_rtx (arg1, NULL);
       arg2_rtx = get_memory_rtx (arg2, NULL);
 
-#ifdef HAVE_cmpstrsi
       /* Try to call cmpstrsi.  */
-      if (HAVE_cmpstrsi)
-       {
-         machine_mode insn_mode
-           = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
-
-         /* Make a place to write the result of the instruction.  */
-         result = target;
-         if (! (result != 0
-                && REG_P (result) && GET_MODE (result) == insn_mode
-                && REGNO (result) >= FIRST_PSEUDO_REGISTER))
-           result = gen_reg_rtx (insn_mode);
-
-         insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx,
-                              GEN_INT (MIN (arg1_align, arg2_align)));
-       }
-#endif
-#ifdef HAVE_cmpstrnsi
+      if (cmpstr_icode != CODE_FOR_nothing)
+       result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx,
+                               MIN (arg1_align, arg2_align));
+
       /* Try to determine at least one length and call cmpstrnsi.  */
-      if (!insn && HAVE_cmpstrnsi)
+      if (!result && cmpstrn_icode != CODE_FOR_nothing)
        {
          tree len;
          rtx arg3_rtx;
 
-         machine_mode insn_mode
-           = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
          tree len1 = c_strlen (arg1, 1);
          tree len2 = c_strlen (arg2, 1);
 
@@ -4103,30 +4134,19 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
            len = len2;
 
          /* If both arguments have side effects, we cannot optimize.  */
-         if (!len || TREE_SIDE_EFFECTS (len))
-           goto do_libcall;
-
-         arg3_rtx = expand_normal (len);
-
-         /* Make a place to write the result of the instruction.  */
-         result = target;
-         if (! (result != 0
-                && REG_P (result) && GET_MODE (result) == insn_mode
-                && REGNO (result) >= FIRST_PSEUDO_REGISTER))
-           result = gen_reg_rtx (insn_mode);
-
-         insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
-                               GEN_INT (MIN (arg1_align, arg2_align)));
+         if (len && !TREE_SIDE_EFFECTS (len))
+           {
+             arg3_rtx = expand_normal (len);
+             result = expand_cmpstrn (cmpstrn_icode, target, arg1_rtx,
+                                      arg2_rtx, TREE_TYPE (len), arg3_rtx,
+                                      MIN (arg1_align, arg2_align));
+           }
        }
-#endif
 
-      if (insn)
+      if (result)
        {
-         machine_mode mode;
-         emit_insn (insn);
-
          /* Return the value in the proper mode for this function.  */
-         mode = TYPE_MODE (TREE_TYPE (exp));
+         machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
          if (GET_MODE (result) == mode)
            return result;
          if (target == 0)
@@ -4137,16 +4157,12 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target)
 
       /* Expand the library call ourselves using a stabilized argument
         list to avoid re-evaluating the function's arguments twice.  */
-#ifdef HAVE_cmpstrnsi
-    do_libcall:
-#endif
       fndecl = get_callee_fndecl (exp);
       fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2);
       gcc_assert (TREE_CODE (fn) == CALL_EXPR);
       CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
       return expand_call (fn, target, target == const0_rtx);
     }
-#endif
   return NULL_RTX;
 }
 
@@ -4167,12 +4183,12 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
   /* If c_strlen can determine an expression for one of the string
      lengths, and it doesn't have side effects, then emit cmpstrnsi
      using length MIN(strlen(string)+1, arg3).  */
-#ifdef HAVE_cmpstrnsi
-  if (HAVE_cmpstrnsi)
+  insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode);
+  if (cmpstrn_icode != CODE_FOR_nothing)
   {
     tree len, len1, len2;
     rtx arg1_rtx, arg2_rtx, arg3_rtx;
-    rtx result, insn;
+    rtx result;
     tree fndecl, fn;
     tree arg1 = CALL_EXPR_ARG (exp, 0);
     tree arg2 = CALL_EXPR_ARG (exp, 1);
@@ -4180,8 +4196,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
 
     unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT;
     unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT;
-    machine_mode insn_mode
-      = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode;
 
     len1 = c_strlen (arg1, 1);
     len2 = c_strlen (arg2, 1);
@@ -4227,13 +4241,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
     if (arg1_align == 0 || arg2_align == 0)
       return NULL_RTX;
 
-    /* Make a place to write the result of the instruction.  */
-    result = target;
-    if (! (result != 0
-          && REG_P (result) && GET_MODE (result) == insn_mode
-          && REGNO (result) >= FIRST_PSEUDO_REGISTER))
-      result = gen_reg_rtx (insn_mode);
-
     /* Stabilize the arguments in case gen_cmpstrnsi fails.  */
     arg1 = builtin_save_expr (arg1);
     arg2 = builtin_save_expr (arg2);
@@ -4242,12 +4249,11 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
     arg1_rtx = get_memory_rtx (arg1, len);
     arg2_rtx = get_memory_rtx (arg2, len);
     arg3_rtx = expand_normal (len);
-    insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
-                         GEN_INT (MIN (arg1_align, arg2_align)));
-    if (insn)
+    result = expand_cmpstrn (cmpstrn_icode, target, arg1_rtx, arg2_rtx,
+                            TREE_TYPE (len), arg3_rtx,
+                            MIN (arg1_align, arg2_align));
+    if (result)
       {
-       emit_insn (insn);
-
        /* Return the value in the proper mode for this function.  */
        mode = TYPE_MODE (TREE_TYPE (exp));
        if (GET_MODE (result) == mode)
@@ -4267,7 +4273,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
     CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
     return expand_call (fn, target, target == const0_rtx);
   }
-#endif
   return NULL_RTX;
 }
 
index 88d04066d16bda07a23fbcb80c57b7bbad509460..02ad3455bd1b8365276cb739c90f51325596195a 100644 (file)
 ;; 3 = alignment
 
 (define_expand "cmpstrsi"
-  [(match_operand:HI 0 "" "")
-   (match_operand 1 "ap_operand" "")
-   (match_operand 2 "ap_operand" "")
-   (match_operand 3 "" "")
+  [(match_operand:HI 0 "register_operand" "")
+   (match_operand 1 "memory_operand" "")
+   (match_operand 2 "memory_operand" "")
+   (match_operand 3 "const_int_operand" "")
    ]
   "TARGET_A24"
   "if (m32c_expand_cmpstr(operands)) DONE; FAIL;"
index 8b124759b0bac6567d192a1d9f4f5d9b90f02e0a..6faf7719a9a6e52cd0d80d11d249d5e66cd88e0f 100644 (file)
   
     emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
     emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
-    emit_move_insn (len, force_operand (operands[3], NULL_RTX));
+    emit_move_insn (len, operands[3]);
 
     emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
     DONE;
index ad49f72c68d8648e9eeea84fa55dd0aef66cac12..facce836def892571bfb63ad67b6b26f49b7acf6 100644 (file)
@@ -12731,7 +12731,7 @@ label:
   [(set (match_operand:SI 0 "register_operand")
        (compare:SI (match_operand:BLK 1 "memory_operand")
                    (match_operand:BLK 2 "memory_operand")))
-   (use (match_operand:SI 3 "immediate_operand"))
+   (use (match_operand:SI 3 "nonmemory_operand"))
    (use (match_operand:SI 4 "immediate_operand"))]
   "TARGET_SH1 && optimize"
 {