[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

From-SVN: r208862
This commit is contained in:
Marcus Shawcroft 2014-03-27 10:13:50 +00:00 committed by Marcus Shawcroft
parent 2f2a7d1543
commit 0b7f81668e
6 changed files with 125 additions and 41 deletions

View File

@ -1,3 +1,11 @@
2014-03-27 Marcus Shawcroft <marcus.shawcroft@arm.com>
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 <dehao@google.com>
* ipa-inline.c (early_inliner): Update node's inline info.

View File

@ -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 *

View File

@ -1,3 +1,10 @@
2014-03-27 Marcus Shawcroft <marcus.shawcroft@arm.com>
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 <dehao@google.com>
* gcc.dg/predict-8.c: New test.

View File

@ -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 } } */

View File

@ -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 } } */

View File

@ -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 } } */