diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 963403d5ced399e312a84e0ce88675960ddde71b..6d540e759e41cf0991892488e7b592865fb79d00 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 c791341f69b80244980d0e3524ceb35c97cd0b0a..04284177c962d52902df9016af9f307f82a433a9 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 ac41d93ae1e43c2d78aff3b643969aef9265dfe1..55a512349cca64da023f2fdb09ffbdc1ff4e78a0 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 4b45c984bf43923412d62188008a97761a6732e7..b7db3616cdf974faee36c27fb9d0dabcd296c279 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 b3ad42b376f8a4085c2c8d5844bd14285be1793d..d84929f3d1fb9836207b1f79c6f0ddcb39055c07 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 d51376dff39783dfb4e4ef671ec426609415bafa..6af715564c9a54cd7c1358a61da21a37c7c4653a 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 0000000000000000000000000000000000000000..9e69ca166458ae9a3b793afb6deae57052076f69 --- /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 0000000000000000000000000000000000000000..6e20ca12e98d1b81861b7396cb1e4683efe0cc3e --- /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 0000000000000000000000000000000000000000..193bec2ce697f79bf26b801877216d1131ae311a --- /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 (); +}