diff options
author | Xuepeng Guo <xguo@gcc.gnu.org> | 2013-05-30 08:11:30 +0000 |
---|---|---|
committer | Xuepeng Guo <xguo@gcc.gnu.org> | 2013-05-30 08:11:30 +0000 |
commit | 24d5b0970a7d07a30430b17b2a837832c3b1b38e (patch) | |
tree | 7d5df32b06814b7ade77dd32dec02366031c6158 | |
parent | c1cccc15b70ec9a7afba448343c98c8c3eacf506 (diff) | |
download | gcc-24d5b0970a7d07a30430b17b2a837832c3b1b38e.zip gcc-24d5b0970a7d07a30430b17b2a837832c3b1b38e.tar.gz gcc-24d5b0970a7d07a30430b17b2a837832c3b1b38e.tar.bz2 |
arm-protos.h: Add and update function protos.
gcc/ChangeLog:
2013-05-30 Bernd Schmidt <bernds@codesourcery.com>
Zhenqiang Chen <zhenqiang.chen@linaro.org>
* config/arm/arm-protos.h: Add and update function protos.
* config/arm/arm.c (use_simple_return_p): New added.
(thumb2_expand_return): Check simple_return flag.
* config/arm/arm.md: Add simple_return and conditional simple_return.
* config/arm/iterators.md: Add iterator for return and simple_return.
gcc/testsuite/ChangeLog:
2013-05-30 Zhenqiang Chen <zhenqiang.chen@linaro.org>
* gcc.dg/shrink-wrap-alloca.c: New added.
* gcc.dg/shrink-wrap-pretend.c: New added.
* gcc.dg/shrink-wrap-sibcall.c: New added.
From-SVN: r199439
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 24 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 26 | ||||
-rw-r--r-- | gcc/config/arm/iterators.md | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/shrink-wrap-alloca.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/shrink-wrap-pretend.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/shrink-wrap-sibcall.c | 26 |
9 files changed, 136 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 963403d..6d540e7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-05-30 Bernd Schmidt <bernds@codesourcery.com> + Zhenqiang Chen <zhenqiang.chen@linaro.org> + + * config/arm/arm-protos.h: Add and update function protos. + * config/arm/arm.c (use_simple_return_p): New added. + (thumb2_expand_return): Check simple_return flag. + * config/arm/arm.md: Add simple_return and conditional simple_return. + * config/arm/iterators.md: Add iterator for return and simple_return. + 2013-05-30 Zhenqiang Chen <zhenqiang.chen@linaro.org> * config/arm/arm.c (arm_add_cfa_adjust_cfa_note): New added. diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index c791341..04284177 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -24,12 +24,13 @@ extern enum unwind_info_type arm_except_unwind_info (struct gcc_options *); extern int use_return_insn (int, rtx); +extern bool use_simple_return_p (void); extern enum reg_class arm_regno_class (int); extern void arm_load_pic_register (unsigned long); extern int arm_volatile_func (void); extern void arm_expand_prologue (void); extern void arm_expand_epilogue (bool); -extern void thumb2_expand_return (void); +extern void thumb2_expand_return (bool); extern const char *arm_strip_name_encoding (const char *); extern void arm_asm_output_labelref (FILE *, const char *); extern void thumb2_asm_output_opcode (FILE *); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index ac41d93..55a5123 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -2169,6 +2169,14 @@ arm_option_override (void) global_options.x_param_values, global_options_set.x_param_values); + /* Disable shrink-wrap when optimizing function for size, since it tends to + generate additional returns. */ + if (optimize_function_for_size_p (cfun) && TARGET_THUMB2) + flag_shrink_wrap = false; + /* TBD: Dwarf info for apcs frame is not handled yet. */ + if (TARGET_APCS_FRAME) + flag_shrink_wrap = false; + /* Register global variables with the garbage collector. */ arm_add_gc_roots (); } @@ -2518,6 +2526,18 @@ use_return_insn (int iscond, rtx sibling) return 1; } +/* Return TRUE if we should try to use a simple_return insn, i.e. perform + shrink-wrapping if possible. This is the case if we need to emit a + prologue, which we can test by looking at the offsets. */ +bool +use_simple_return_p (void) +{ + arm_stack_offsets *offsets; + + offsets = arm_get_frame_offsets (); + return offsets->outgoing_args != 0; +} + /* Return TRUE if int I is a valid immediate ARM constant. */ int @@ -24035,7 +24055,7 @@ thumb1_expand_prologue (void) all we really need to check here is if single register is to be returned, or multiple register return. */ void -thumb2_expand_return (void) +thumb2_expand_return (bool simple_return) { int i, num_regs; unsigned long saved_regs_mask; @@ -24048,7 +24068,7 @@ thumb2_expand_return (void) if (saved_regs_mask & (1 << i)) num_regs++; - if (saved_regs_mask) + if (!simple_return && saved_regs_mask) { if (num_regs == 1) { diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 4b45c98..b7db361 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -9276,17 +9276,17 @@ [(set_attr "type" "call")] ) -(define_expand "return" - [(return)] +(define_expand "<return_str>return" + [(returns)] "(TARGET_ARM || (TARGET_THUMB2 && ARM_FUNC_TYPE (arm_current_func_type ()) == ARM_FT_NORMAL && !IS_STACKALIGN (arm_current_func_type ()))) - && USE_RETURN_INSN (FALSE)" + <return_cond_false>" " { if (TARGET_THUMB2) { - thumb2_expand_return (); + thumb2_expand_return (<return_simple_p>); DONE; } } @@ -9311,13 +9311,13 @@ (set_attr "predicable" "yes")] ) -(define_insn "*cond_return" +(define_insn "*cond_<return_str>return" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) - (return) + (returns) (pc)))] - "TARGET_ARM && USE_RETURN_INSN (TRUE)" + "TARGET_ARM <return_cond_true>" "* { if (arm_ccfsm_state == 2) @@ -9325,20 +9325,21 @@ arm_ccfsm_state += 2; return \"\"; } - return output_return_instruction (operands[0], true, false, false); + return output_return_instruction (operands[0], true, false, + <return_simple_p>); }" [(set_attr "conds" "use") (set_attr "length" "12") (set_attr "type" "load1")] ) -(define_insn "*cond_return_inverted" +(define_insn "*cond_<return_str>return_inverted" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) (pc) - (return)))] - "TARGET_ARM && USE_RETURN_INSN (TRUE)" + (returns)))] + "TARGET_ARM <return_cond_true>" "* { if (arm_ccfsm_state == 2) @@ -9346,7 +9347,8 @@ arm_ccfsm_state += 2; return \"\"; } - return output_return_instruction (operands[0], true, true, false); + return output_return_instruction (operands[0], true, true, + <return_simple_p>); }" [(set_attr "conds" "use") (set_attr "length" "12") diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index b3ad42b..d84929f 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -496,3 +496,11 @@ (define_int_attr nvrint_variant [(UNSPEC_NVRINTZ "z") (UNSPEC_NVRINTP "p") (UNSPEC_NVRINTA "a") (UNSPEC_NVRINTM "m") (UNSPEC_NVRINTX "x") (UNSPEC_NVRINTN "n")]) +;; Both kinds of return insn. +(define_code_iterator returns [return simple_return]) +(define_code_attr return_str [(return "") (simple_return "simple_")]) +(define_code_attr return_simple_p [(return "false") (simple_return "true")]) +(define_code_attr return_cond_false [(return " && USE_RETURN_INSN (FALSE)") + (simple_return " && use_simple_return_p ()")]) +(define_code_attr return_cond_true [(return " && USE_RETURN_INSN (TRUE)") + (simple_return " && use_simple_return_p ()")]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d51376d..6af7155 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-05-30 Zhenqiang Chen <zhenqiang.chen@linaro.org> + + * gcc.dg/shrink-wrap-alloca.c: New added. + * gcc.dg/shrink-wrap-pretend.c: New added. + * gcc.dg/shrink-wrap-sibcall.c: New added. + 2013-05-30 Tobias Burnus <burnus@net-b.de> PR fortran/57458 diff --git a/gcc/testsuite/gcc.dg/shrink-wrap-alloca.c b/gcc/testsuite/gcc.dg/shrink-wrap-alloca.c new file mode 100644 index 0000000..9e69ca1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/shrink-wrap-alloca.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -g" } */ + +extern int * alloca (int); + +int *p; + +void +test (int a) +{ + if (a > 0) + p = alloca (4); +} diff --git a/gcc/testsuite/gcc.dg/shrink-wrap-pretend.c b/gcc/testsuite/gcc.dg/shrink-wrap-pretend.c new file mode 100644 index 0000000..6e20ca1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/shrink-wrap-pretend.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -g" } */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +#define DEBUG_BUFFER_SIZE 80 +int unifi_debug = 5; + +void +unifi_trace (void* ospriv, int level, const char *fmt, ...) +{ + static char s[DEBUG_BUFFER_SIZE]; + va_list args; + unsigned int len; + + if (!ospriv) + return; + + if (unifi_debug >= level) + { + va_start (args, fmt); + len = vsnprintf (&(s)[0], (DEBUG_BUFFER_SIZE), fmt, args); + va_end (args); + + if (len >= DEBUG_BUFFER_SIZE) + { + (s)[DEBUG_BUFFER_SIZE - 2] = '\n'; + (s)[DEBUG_BUFFER_SIZE - 1] = 0; + } + + printf ("%s", s); + } +} + diff --git a/gcc/testsuite/gcc.dg/shrink-wrap-sibcall.c b/gcc/testsuite/gcc.dg/shrink-wrap-sibcall.c new file mode 100644 index 0000000..193bec2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/shrink-wrap-sibcall.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -g" } */ + +unsigned char a, b, d, f, g; + +int test (void); + +int +baz (int c) +{ + if (c == 0) return test (); + if (b & 1) + { + g = 0; + int e = (a & 0x0f) - (g & 0x0f); + + if (!a) b |= 0x80; + a = e + test (); + f = g/5 + a*3879 + b *2985; + } + else + { + f = g + a*39879 + b *25; + } + return test (); +} |