From c43fa1f51a746777e557c1ca99b6111474c5c961 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Sat, 11 Oct 2003 21:11:29 +0000 Subject: [PATCH] builtins.c (expand_builtin_strcmp): Defend against the possibility that gen_cmpstrsi may fail... * 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 | 10 +++ gcc/builtins.c | 76 +++++++++++++------ gcc/config/i386/i386.md | 4 +- gcc/testsuite/ChangeLog | 5 ++ .../gcc.c-torture/execute/string-opt-8.c | 2 +- 5 files changed, 70 insertions(+), 27 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4251bf3a741..a05b7260498 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2003-10-11 Roger Sayle + + * 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 PR optimization/12260 diff --git a/gcc/builtins.c b/gcc/builtins.c index 1af2a2d0889..0214edf4198 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index a1f40e156a0..39a8a2cc8c7 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -16129,7 +16129,7 @@ (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; @@ -16849,7 +16849,7 @@ (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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ad9bafce35c..92b96a26ddf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-10-11 Roger Sayle + + * 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 PR optimization/12260 diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c index 434de33db9b..2316fce87ca 100644 --- a/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c +++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-8.c @@ -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; -- 2.30.2