diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-07-19 22:48:25 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-07-19 22:48:25 +0200 |
commit | f9fef34989a9d1974943ec3e835a547b56150c6a (patch) | |
tree | 0b64e6d9e88dfbc57439877cbb5bccdfdbdd43ed /gcc | |
parent | fdb45c0cc3c8be240927799dfca7b297b177cc7d (diff) | |
download | gcc-f9fef34989a9d1974943ec3e835a547b56150c6a.zip gcc-f9fef34989a9d1974943ec3e835a547b56150c6a.tar.gz gcc-f9fef34989a9d1974943ec3e835a547b56150c6a.tar.bz2 |
re PR rtl-optimization/53942 (unable to find a register to spill in class 'CREG')
PR rtl-optimization/53942
* function.c (assign_parm_setup_reg): Avoid zero/sign extension
directly from likely spilled non-fixed hard registers, move them
to pseudo first.
* gcc.dg/pr53942.c: New test.
From-SVN: r189681
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/function.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr53942.c | 34 |
4 files changed, 63 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5142eb8..a14b3d9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2012-07-19 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/53942 + * function.c (assign_parm_setup_reg): Avoid zero/sign extension + directly from likely spilled non-fixed hard registers, move them + to pseudo first. + 2012-07-19 Steve Ellcey <sellcey@mips.com> * config/mips/mips.c (mips_set_mips16_mode): Clear SYNCI_MASK in diff --git a/gcc/function.c b/gcc/function.c index c567588..f1e0b2d3 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -2987,11 +2987,26 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, && insn_operand_matches (icode, 1, op1)) { enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND; - rtx insn, insns; + rtx insn, insns, t = op1; HARD_REG_SET hardregs; start_sequence (); - insn = gen_extend_insn (op0, op1, promoted_nominal_mode, + /* If op1 is a hard register that is likely spilled, first + force it into a pseudo, otherwise combiner might extend + its lifetime too much. */ + if (GET_CODE (t) == SUBREG) + t = SUBREG_REG (t); + if (REG_P (t) + && HARD_REGISTER_P (t) + && ! TEST_HARD_REG_BIT (fixed_reg_set, REGNO (t)) + && targetm.class_likely_spilled_p (REGNO_REG_CLASS (REGNO (t)))) + { + t = gen_reg_rtx (GET_MODE (op1)); + emit_move_insn (t, op1); + } + else + t = op1; + insn = gen_extend_insn (op0, t, promoted_nominal_mode, data->passed_mode, unsignedp); emit_insn (insn); insns = get_insns (); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c406d7e..d3a7c88 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-07-19 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/53942 + * gcc.dg/pr53942.c: New test. + 2012-07-19 Jason Merrill <jason@redhat.com> PR c++/54021 diff --git a/gcc/testsuite/gcc.dg/pr53942.c b/gcc/testsuite/gcc.dg/pr53942.c new file mode 100644 index 0000000..6a51d26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr53942.c @@ -0,0 +1,34 @@ +/* PR rtl-optimization/53942 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-mtune=pentium2" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */ + +struct S +{ + unsigned short w[3]; + unsigned int x, y; +}; + +struct S *baz (void); + +__attribute__ ((noinline)) +static unsigned char +foo (struct S *x, unsigned char y) +{ + unsigned char c = 0; + unsigned char v = x->w[0]; + c |= v; + v = ((x->w[1]) & (1 << y)) ? 1 : 0; + c |= v << 1; + v = ((x->w[2]) & 0xff) & (1 << y); + c |= v << 2; + return c; +} + +void +bar (void) +{ + struct S *s = baz (); + s->x = foo (s, 6); + s->y = foo (s, 7); +} |