Commit 517b1da2 by Joey Ye Committed by Joey Ye

arm.c (thumb1_final_prescan_insn): Assert lr save for real far jump.

2013-04-15  Joey Ye  <joey.ye@arm.com>

    * config/arm/arm.c (thumb1_final_prescan_insn): Assert lr save
    for real far jump.
    (thumb_far_jump_used_p): Count instruction size and set
    far_jump_used.

testsuite:
    * gcc.target/arm/thumb1-far-jump-1.c: New test.
    * gcc.target/arm/thumb1-far-jump-2.c: New test.

From-SVN: r197956
parent c21f34f1
2013-04-15 Joey Ye <joey.ye@arm.com>
* config/arm/arm.c (thumb1_final_prescan_insn): Assert lr save
for real far jump.
(thumb_far_jump_used_p): Count instruction size and set
far_jump_used.
2013-04-14 Eric Botcazou <ebotcazou@adacore.com> 2013-04-14 Eric Botcazou <ebotcazou@adacore.com>
* reorg.c (fill_simple_delay_slots): Reindent block of code. * reorg.c (fill_simple_delay_slots): Reindent block of code.
......
...@@ -22713,6 +22713,11 @@ thumb1_final_prescan_insn (rtx insn) ...@@ -22713,6 +22713,11 @@ thumb1_final_prescan_insn (rtx insn)
else if (conds != CONDS_NOCOND) else if (conds != CONDS_NOCOND)
cfun->machine->thumb1_cc_insn = NULL_RTX; cfun->machine->thumb1_cc_insn = NULL_RTX;
} }
/* Check if unexpected far jump is used. */
if (cfun->machine->lr_save_eliminated
&& get_attr_far_jump (insn) == FAR_JUMP_YES)
internal_error("Unexpected thumb1 far jump");
} }
int int
...@@ -22738,6 +22743,8 @@ static int ...@@ -22738,6 +22743,8 @@ static int
thumb_far_jump_used_p (void) thumb_far_jump_used_p (void)
{ {
rtx insn; rtx insn;
bool far_jump = false;
unsigned int func_size = 0;
/* This test is only important for leaf functions. */ /* This test is only important for leaf functions. */
/* assert (!leaf_function_p ()); */ /* assert (!leaf_function_p ()); */
...@@ -22788,6 +22795,26 @@ thumb_far_jump_used_p (void) ...@@ -22788,6 +22795,26 @@ thumb_far_jump_used_p (void)
{ {
if (JUMP_P (insn) && get_attr_far_jump (insn) == FAR_JUMP_YES) if (JUMP_P (insn) && get_attr_far_jump (insn) == FAR_JUMP_YES)
{ {
far_jump = true;
}
func_size += get_attr_length (insn);
}
/* Attribute far_jump will always be true for thumb1 before
shorten_branch pass. So checking far_jump attribute before
shorten_branch isn't much useful.
Following heuristic tries to estimate more accruately if a far jump
may finally be used. The heuristic is very conservative as there is
no chance to roll-back the decision of not to use far jump.
Thumb1 long branch offset is -2048 to 2046. The worst case is each
2-byte insn is assiociated with a 4 byte constant pool. Using
function size 2048/3 as the threshold is conservative enough. */
if (far_jump)
{
if ((func_size * 3) >= 2048)
{
/* Record the fact that we have decided that /* Record the fact that we have decided that
the function does use far jumps. */ the function does use far jumps. */
cfun->machine->far_jump_used = 1; cfun->machine->far_jump_used = 1;
......
2013-04-15 Joey Ye <joey.ye@arm.com>
* gcc.target/arm/thumb1-far-jump-1.c: New test.
* gcc.target/arm/thumb1-far-jump-2.c: New test.
2013-04-14 Mikael Morin <mikael@gcc.gnu.org> 2013-04-14 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/56816 PR fortran/56816
......
/* Check for thumb1 far jump. Shouldn't save lr for small leaf functions
* even with a branch in it. */
/* { dg-options "-Os" } */
/* { dg-skip-if "" { ! { arm_thumb1 } } } */
void f()
{
for (;;);
}
volatile int g;
void f2(int i)
{
if (i) g=0;
}
void f3(int i)
{
if (i) {
g=0;
g=1;
g=2;
g=3;
g=4;
g=5;
g=6;
g=7;
g=8;
g=9;
}
}
/* { dg-final { scan-assembler-not "push.*lr" } } */
/* Check for thumb1 far jump. This is the extreme case that far jump
* will be used with minimum number of instructions. By passing this case
* it means the heuristic of saving lr for far jump meets the most extreme
* requirement. */
/* { dg-options "-Os" } */
/* { dg-skip-if "" { ! { arm_thumb1 } } } */
volatile register r4 asm("r4");
void f3(int i)
{
#define GO(n) \
extern volatile int g_##n; \
r4=(int)&g_##n;
#define GO8(n) \
GO(n##_0) \
GO(n##_1) \
GO(n##_2) \
GO(n##_3) \
GO(n##_4) \
GO(n##_5) \
GO(n##_6) \
GO(n##_7)
#define GO64(n) \
GO8(n##_0) \
GO8(n##_1) \
GO8(n##_2) \
GO8(n##_3) \
GO8(n##_4) \
GO8(n##_5) \
GO8(n##_6) \
GO8(n##_7) \
#define GO498(n) \
GO64(n##_0) \
GO64(n##_1) \
GO64(n##_2) \
GO64(n##_3) \
GO64(n##_4) \
GO64(n##_5) \
GO64(n##_6) \
GO8(n##_0) \
GO8(n##_1) \
GO8(n##_2) \
GO8(n##_3) \
GO8(n##_4) \
GO8(n##_5) \
GO(n##_0) \
GO(n##_1) \
if (i) {
GO498(0);
}
}
/* { dg-final { scan-assembler "push.*lr" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment