From: Richard Sandiford Date: Mon, 24 Aug 2015 17:59:07 +0000 (+0000) Subject: builtins.c (expand_cmpstr, [...]): New functions. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a666df609a95f9a569b6d09472933ff898bd805d;p=gcc.git builtins.c (expand_cmpstr, [...]): New functions. 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5ebafe1fbcc..e89afb3e68f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2015-08-24 Richard Sandiford + + * 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 * df-scan.c (df_insn_info_init_fields): New function, split out diff --git a/gcc/builtins.c b/gcc/builtins.c index 76c16fa3940..ea8ffe2ba6d 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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; } diff --git a/gcc/config/m32c/blkmov.md b/gcc/config/m32c/blkmov.md index 88d04066d16..02ad3455bd1 100644 --- a/gcc/config/m32c/blkmov.md +++ b/gcc/config/m32c/blkmov.md @@ -178,10 +178,10 @@ ;; 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;" diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 8b124759b0b..6faf7719a9a 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -2315,7 +2315,7 @@ 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; diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index ad49f72c68d..facce836def 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -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" {