Ping. OK for trunk and 4.8?
> -----Original Message----- > From: Joey Ye [mailto:joey...@arm.com] > Sent: 21 February 2014 19:32 > To: gcc-patches@gcc.gnu.org > Subject: [patch] [arm] Fix PR60169 - thumb1 far jump > > Patch http://gcc.gnu.org/ml/gcc-patches/2012-12/msg01229.html introduced > this ICE: > > 1. thumb1 estimate if far_jump is used based on function insn size 2. During > reload, after stack layout finalized, it does reload_as_needed. It however > increases insn size that changes estimation result of far_jump, which in > return need to save lr and change stack layout again. While there is not > chance to change, GCC crashes. > > Solution: > Do not change estimation result of far_jump if reload_in_progress or > reload_completed is true. > > Not likely need to fix lra according to Vlad: > http://gcc.gnu.org/ml/gcc/2014-02/msg00355.html > > ChangeLog: > * config/arm/arm.c (thumb_far_jump_used_p): Don't change > if reload in progress or completed. > > * gcc.target/arm/thumb1-far-jump-3.c: New case.
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index b562986..2cf362c 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -26255,6 +26255,11 @@ thumb_far_jump_used_p (void) return 0; } + /* We should not change far_jump_used during or after reload, as there is + no chance to change stack frame layout. */ + if (reload_in_progress || reload_completed) + return 0; + /* Check to see if the function contains a branch insn with the far jump attribute set. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) diff --git a/gcc/testsuite/gcc.target/arm/thumb1-far-jump-3.c b/gcc/testsuite/gcc.target/arm/thumb1-far-jump-3.c new file mode 100644 index 0000000..90559ba --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb1-far-jump-3.c @@ -0,0 +1,108 @@ +/* Catch reload ICE on target thumb1 with far jump optimization. + * It is also a valid case for non-thumb1 target. */ + +/* Add -mno-lra option as it is only reproducable with reload. It will + be removed after reload is completely removed. */ +/* { dg-options "-mno-lra -fomit-frame-pointer" } */ +/* { dg-do compile } */ + +#define C 2 +#define A 4 +#define RGB (C | A) +#define GRAY (A) + +typedef unsigned long uint_32; +typedef unsigned char byte; +typedef byte * bytep; + +typedef struct ss +{ + uint_32 w; + uint_32 r; + byte c; + byte b; + byte p; +} info; + +typedef info * infop; + +void +foo(infop info, bytep row) +{ + uint_32 iw = info->w; + if (info->c == RGB) + { + if (info->b == 8) + { + bytep sp = row + info->r; + bytep dp = sp; + byte save; + uint_32 i; + + for (i = 0; i < iw; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + + else + { + bytep sp = row + info->r; + bytep dp = sp; + byte save[2]; + uint_32 i; + + for (i = 0; i < iw; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } + else if (info->c == GRAY) + { + if (info->b == 8) + { + bytep sp = row + info->r; + bytep dp = sp; + byte save; + uint_32 i; + + for (i = 0; i < iw; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + else + { + bytep sp = row + info->r; + bytep dp = sp; + byte save[2]; + uint_32 i; + + for (i = 0; i < iw; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } + } +}