From 743de8ed93b48297eb34a8c00e663f1425e874dd Mon Sep 17 00:00:00 2001 From: mshawcroft Date: Thu, 27 Mar 2014 10:13:50 +0000 Subject: [PATCH] [PR 60580, AArch64] Fix __attribute__ ((optimize("no-omit-frame-pointer"))) The implementation of -m[no-]omit-leaf-frame-pointer and -f[no-]omit-frame-pointer in the AArch64 target does not behave correctly in the presence of __attribute__ optimize. This patch adjusts the implementation to work in a similar fashion to the same functionality in the i386 target. The problem occurs because the current implementation uses a global 'faked_omit_frame_pointer' to retain the original value of flag_omit_frame_pointer. The global does not form part of the optimization save state. This solution removes the global and instead tracks required behaviour using only flag_omit_frame_pointer and flag_omit_leaf_frame_pointer. These two form part of the optimziation save state and target save state respectively. The additional complication for AArch64 is that the PCS requires that given -fno-omit-frame-pointer -momit-leave-frame-pointer, a leaf function that kills LR must create a frame record. This is readily handled in aarch64_frame_pointer_required(). I've dropped logic in aarch64_can_eliminate() that attempts to detect this scenario since it git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@208862 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 8 +++ gcc/config/aarch64/aarch64.c | 56 +++++-------------- gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.target/aarch64/pr60580_1.c | 45 +++++++++++++++ .../gcc.target/aarch64/test_fp_attribute_1.c | 26 +++++++++ .../gcc.target/aarch64/test_fp_attribute_2.c | 26 +++++++++ 6 files changed, 126 insertions(+), 42 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/pr60580_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/test_fp_attribute_1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/test_fp_attribute_2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e7acc583bdc58..fcec2ad3aab67 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-03-27 Marcus Shawcroft + + PR target/60580 + * config/aarch64/aarch64.c (faked_omit_frame_pointer): Remove. + (aarch64_frame_pointer_required): Adjust logic. + (aarch64_can_eliminate): Adjust logic. + (aarch64_override_options_after_change): Adjust logic. + 2014-03-27 Dehao Chen * ipa-inline.c (early_inliner): Update node's inline info. diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index e839539fda15d..e2812d22ec973 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -315,10 +315,6 @@ static GTY(()) int gty_dummy; #define AARCH64_NUM_BITMASKS 5334 static unsigned HOST_WIDE_INT aarch64_bitmasks[AARCH64_NUM_BITMASKS]; -/* Did we set flag_omit_frame_pointer just so - aarch64_frame_pointer_required would be called? */ -static bool faked_omit_frame_pointer; - typedef enum aarch64_cond_code { AARCH64_EQ = 0, AARCH64_NE, AARCH64_CS, AARCH64_CC, AARCH64_MI, AARCH64_PL, @@ -1694,17 +1690,15 @@ aarch64_frame_pointer_required (void) if (cfun->calls_alloca) return true; - /* We may have turned flag_omit_frame_pointer on in order to have this - function called; if we did, we also set the 'faked_omit_frame_pointer' flag - and we'll check it here. - If we really did set flag_omit_frame_pointer normally, then we return false - (no frame pointer required) in all cases. */ + /* In aarch64_override_options_after_change + flag_omit_leaf_frame_pointer turns off the frame pointer by + default. Turn it back on now if we've not got a leaf + function. */ + if (flag_omit_leaf_frame_pointer + && (!crtl->is_leaf || df_regs_ever_live_p (LR_REGNUM))) + return true; - if (flag_omit_frame_pointer && !faked_omit_frame_pointer) - return false; - else if (flag_omit_leaf_frame_pointer) - return !crtl->is_leaf || df_regs_ever_live_p (LR_REGNUM); - return true; + return false; } /* Mark the registers that need to be saved by the callee and calculate @@ -4132,23 +4126,8 @@ aarch64_can_eliminate (const int from, const int to) return true; if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) return true; - return false; - } - else - { - /* If we decided that we didn't need a leaf frame pointer but then used - LR in the function, then we'll want a frame pointer after all, so - prevent this elimination to ensure a frame pointer is used. - - NOTE: the original value of flag_omit_frame_pointer gets trashed - IFF flag_omit_leaf_frame_pointer is true, so we check the value - of faked_omit_frame_pointer here (which is true when we always - wish to keep non-leaf frame pointers but only wish to keep leaf frame - pointers when LR is clobbered). */ - if (to == STACK_POINTER_REGNUM - && df_regs_ever_live_p (LR_REGNUM) - && faked_omit_frame_pointer) - return false; + + return false; } return true; @@ -5278,17 +5257,10 @@ aarch64_override_options (void) static void aarch64_override_options_after_change (void) { - faked_omit_frame_pointer = false; - - /* To omit leaf frame pointers, we need to turn flag_omit_frame_pointer on so - that aarch64_frame_pointer_required will be called. We need to remember - whether flag_omit_frame_pointer was turned on normally or just faked. */ - - if (flag_omit_leaf_frame_pointer && !flag_omit_frame_pointer) - { - flag_omit_frame_pointer = true; - faked_omit_frame_pointer = true; - } + if (flag_omit_frame_pointer) + flag_omit_leaf_frame_pointer = false; + else if (flag_omit_leaf_frame_pointer) + flag_omit_frame_pointer = true; } static struct machine_function * diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 98ee981cb234b..2155af3b741e0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-03-27 Marcus Shawcroft + + PR target/60580 + * gcc.target/aarch64/pr60580_1.c: New. + * gcc.target/aarch64/test_fp_attribute_1.c: New. + * gcc.target/aarch64/test_fp_attribute_2.c: New. + 2014-03-26 Dehao Chen * gcc.dg/predict-8.c: New test. diff --git a/gcc/testsuite/gcc.target/aarch64/pr60580_1.c b/gcc/testsuite/gcc.target/aarch64/pr60580_1.c new file mode 100644 index 0000000000000..1adf508cfc041 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr60580_1.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -fomit-frame-pointer -fno-inline --save-temps" } */ + +void +func_leaf (void) +{ + int a = 0; +} + +void +func_no_leaf (void) +{ + int a = 0; + func_leaf (); +} + +void +func1 (void) +{ + int a = 0; + func_no_leaf (); +} + +/* + * This function calls XXX(), which modifies SP. This is incompatible to + * -fomit-frame-pointer generated code as SP is used to access the frame. + */ +__attribute__ ((optimize("no-omit-frame-pointer"))) +void +func2 (void) +{ + int a = 0; + func_no_leaf (); +} + +void +func3 (void) +{ + int a = 0; + func_no_leaf (); +} + +/* { dg-final { scan-assembler-times "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" 1 } } */ + +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/test_fp_attribute_1.c b/gcc/testsuite/gcc.target/aarch64/test_fp_attribute_1.c new file mode 100644 index 0000000000000..7538250c9f304 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/test_fp_attribute_1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -fno-omit-frame-pointer -fno-inline --save-temps" } */ + +void +leaf (void) +{ + int a = 0; +} + +__attribute__ ((optimize("omit-frame-pointer"))) +void +non_leaf_1 (void) +{ + leaf (); +} + +__attribute__ ((optimize("omit-frame-pointer"))) +void +non_leaf_2 (void) +{ + leaf (); +} + +/* { dg-final { scan-assembler-times "str\tx30, \\\[sp\\\]" 2 } } */ + +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/test_fp_attribute_2.c b/gcc/testsuite/gcc.target/aarch64/test_fp_attribute_2.c new file mode 100644 index 0000000000000..675091f841ead --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/test_fp_attribute_2.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -fomit-frame-pointer -fno-inline --save-temps" } */ + +void +leaf (void) +{ + int a = 0; +} + +__attribute__ ((optimize("no-omit-frame-pointer"))) +void +non_leaf_1 (void) +{ + leaf (); +} + +__attribute__ ((optimize("no-omit-frame-pointer"))) +void +non_leaf_2 (void) +{ + leaf (); +} + +/* { dg-final { scan-assembler-times "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" 2 } } */ + +/* { dg-final { cleanup-saved-temps } } */