From 147a0bcfc784a28e4ef09e32b23703e0ecc8bd55 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 25 Jan 2011 17:22:34 +0100 Subject: [PATCH] re PR target/45701 (Fail to prefer using r3 for padding a push/pop multiple to 8-byte alignment) PR target/45701 * config/arm/arm.c (any_sibcall_uses_r3): New function. (arm_get_frame_offsets): Use it. 2011-01-25 Yao Qi PR target/45701 * gcc.target/arm/pr45701-1.c: New test. * gcc.target/arm/pr45701-2.c: New test. * gcc.target/arm/pr45701-3.c: New test. From-SVN: r169240 --- gcc/ChangeLog | 6 +++++ gcc/config/arm/arm.c | 29 ++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 7 ++++++ gcc/testsuite/gcc.target/arm/pr45701-1.c | 24 ++++++++++++++++++++ gcc/testsuite/gcc.target/arm/pr45701-2.c | 26 +++++++++++++++++++++ gcc/testsuite/gcc.target/arm/pr45701-3.c | 27 ++++++++++++++++++++++ 6 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr45701-1.c create mode 100644 gcc/testsuite/gcc.target/arm/pr45701-2.c create mode 100644 gcc/testsuite/gcc.target/arm/pr45701-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac512392e79..9b9700ef27b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-01-25 Jakub Jelinek + + PR target/45701 + * config/arm/arm.c (any_sibcall_uses_r3): New function. + (arm_get_frame_offsets): Use it. + 2011-01-25 Sebastian Pop Jakub Jelinek diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 3e75d7c9c4d..be09282c17d 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1,6 +1,6 @@ /* Output routines for GCC for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). @@ -15188,6 +15188,31 @@ thumb_force_lr_save (void) } +/* Return true if r3 is used by any of the tail call insns in the + current function. */ + +static bool +any_sibcall_uses_r3 (void) +{ + edge_iterator ei; + edge e; + + if (!crtl->tail_call_emit) + return false; + FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds) + if (e->flags & EDGE_SIBCALL) + { + rtx call = BB_END (e->src); + if (!CALL_P (call)) + call = prev_nonnote_nondebug_insn (call); + gcc_assert (CALL_P (call) && SIBLING_CALL_P (call)); + if (find_regno_fusage (call, USE, 3)) + return true; + } + return false; +} + + /* Compute the distance from register FROM to register TO. These can be the arg pointer (26), the soft frame pointer (25), the stack pointer (13) or the hard frame pointer (11). @@ -15352,7 +15377,7 @@ arm_get_frame_offsets (void) /* If it is safe to use r3, then do so. This sometimes generates better code on Thumb-2 by avoiding the need to use 32-bit push/pop instructions. */ - if (!crtl->tail_call_emit + if (! any_sibcall_uses_r3 () && arm_size_return_regs () <= 12 && (offsets->saved_regs_mask & (1 << 3)) == 0) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7b5efca3b62..90469599887 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-01-25 Yao Qi + + PR target/45701 + * gcc.target/arm/pr45701-1.c: New test. + * gcc.target/arm/pr45701-2.c: New test. + * gcc.target/arm/pr45701-3.c: New test. + 2011-01-25 Sebastian Pop Jakub Jelinek diff --git a/gcc/testsuite/gcc.target/arm/pr45701-1.c b/gcc/testsuite/gcc.target/arm/pr45701-1.c new file mode 100644 index 00000000000..f94f5784b3e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr45701-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv7-a -mthumb -Os" } */ +/* { dg-final { scan-assembler "push\t\{r3" } } */ +/* { dg-final { scan-assembler-not "r8" } } */ + +extern int hist_verify; +extern char *pre_process_line (char*); +extern char* str_cpy (char*, char*); +extern int str_len (char*); +extern char* x_malloc (int); +#define savestring(x) (char *)str_cpy (x_malloc (1 + str_len (x)), (x)) + +char * +history_expand_line_internal (char* line) +{ + char *new_line; + int old_verify; + + old_verify = hist_verify; + hist_verify = 0; + new_line = pre_process_line (line); + hist_verify = old_verify; + return (new_line == line) ? savestring (line) : new_line; +} diff --git a/gcc/testsuite/gcc.target/arm/pr45701-2.c b/gcc/testsuite/gcc.target/arm/pr45701-2.c new file mode 100644 index 00000000000..68d51781a94 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr45701-2.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv7-a -mthumb -Os" } */ +/* { dg-final { scan-assembler "push\t\{r3" } } */ +/* { dg-final { scan-assembler-not "r8" } } */ + +extern int hist_verify; +extern char *pre_process_line (char*); +extern char* savestring1 (char*, char*); +extern char* str_cpy (char*, char*); +extern int str_len (char*); +extern char* x_malloc (int); +#define savestring(x) (char *)str_cpy (x_malloc (1 + str_len (x)), (x)) + +char * +history_expand_line_internal (char* line) +{ + char *new_line; + int old_verify; + + old_verify = hist_verify; + hist_verify = 0; + new_line = pre_process_line (line); + hist_verify = old_verify; + /* Two tail calls here, but r3 is not used to pass values. */ + return (new_line == line) ? savestring (line) : savestring1 (new_line, line); +} diff --git a/gcc/testsuite/gcc.target/arm/pr45701-3.c b/gcc/testsuite/gcc.target/arm/pr45701-3.c new file mode 100644 index 00000000000..8255bae1143 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr45701-3.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv7-a -mthumb -Os" } */ +/* { dg-final { scan-assembler "push\t.*r8" } } */ +/* { dg-final { scan-assembler-not "push\t*r3" } } */ + +extern int hist_verify; +extern char *pre_process_line (char*); +extern char* savestring1 (char*, char*, int, int); +extern char* str_cpy (char*, char*); +extern int str_len (char*); +extern char* x_malloc (int); +#define savestring(x) (char *)str_cpy (x_malloc (1 + str_len (x)), (x)) + +char * +history_expand_line_internal (char* line) +{ + char *new_line; + int old_verify; + + old_verify = hist_verify; + hist_verify = 0; + new_line = pre_process_line (line); + hist_verify = old_verify; + /* Two tail calls here, but r3 is used to pass values. */ + return (new_line == line) ? savestring (line) : + savestring1 (new_line, line, 0, old_verify+1); +} -- 2.30.2