aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-10-11 21:11:29 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-10-11 21:11:29 +0000
commitc43fa1f51a746777e557c1ca99b6111474c5c961 (patch)
tree3038c6d3362d74076b56b1b91ed777dad3dc5708
parentc877353c907f31f7af74452d4eb2c44b6900493d (diff)
downloadgcc-c43fa1f51a746777e557c1ca99b6111474c5c961.zip
gcc-c43fa1f51a746777e557c1ca99b6111474c5c961.tar.gz
gcc-c43fa1f51a746777e557c1ca99b6111474c5c961.tar.bz2
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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/builtins.c76
-rw-r--r--gcc/config/i386/i386.md4
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/string-opt-8.c2
5 files changed, 70 insertions, 27 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4251bf3..a05b726 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
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
* simplify-rtx.c (simplify_unary_operation): Simplify all unary
operations through CONST nodes. Optimize (neg (plus X C)) as
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 1af2a2d..0214edf 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 a1f40e1..39a8a2c 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 ad9bafc..92b96a2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
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
* gcc.c-torture/compile/20031011-2.c: New test case.
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 434de33..2316fce 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;