From: Joey Ye Date: Mon, 15 Apr 2013 07:41:27 +0000 (+0000) Subject: arm.c (thumb1_final_prescan_insn): Assert lr save for real far jump. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=517b1da2746f0abd2151331e18673898fd8dc367;p=gcc.git arm.c (thumb1_final_prescan_insn): Assert lr save for real far jump. 2013-04-15 Joey Ye * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 370ccbb507a..6d664610d2e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2013-04-15 Joey Ye + + * 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 * reorg.c (fill_simple_delay_slots): Reindent block of code. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 982487ec22a..e0667849c70 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -22713,6 +22713,11 @@ thumb1_final_prescan_insn (rtx insn) else if (conds != CONDS_NOCOND) 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 @@ -22738,6 +22743,8 @@ static int thumb_far_jump_used_p (void) { rtx insn; + bool far_jump = false; + unsigned int func_size = 0; /* This test is only important for leaf functions. */ /* assert (!leaf_function_p ()); */ @@ -22788,6 +22795,26 @@ thumb_far_jump_used_p (void) { 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 the function does use far jumps. */ cfun->machine->far_jump_used = 1; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cdff281c930..c8d46d5bd63 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-04-15 Joey Ye + + * 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 PR fortran/56816 diff --git a/gcc/testsuite/gcc.target/arm/thumb1-far-jump-1.c b/gcc/testsuite/gcc.target/arm/thumb1-far-jump-1.c new file mode 100644 index 00000000000..eb16d2fc99e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb1-far-jump-1.c @@ -0,0 +1,34 @@ +/* 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" } } */ + diff --git a/gcc/testsuite/gcc.target/arm/thumb1-far-jump-2.c b/gcc/testsuite/gcc.target/arm/thumb1-far-jump-2.c new file mode 100644 index 00000000000..c6878f8ef8b --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb1-far-jump-2.c @@ -0,0 +1,57 @@ +/* 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" } } */