diff options
author | Andrey Belevantsev <abel@ispras.ru> | 2016-03-12 20:12:29 +0300 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2016-03-12 10:12:29 -0700 |
commit | d0aca6abdbcbabc103df7a65e1e0dcbbad5e055e (patch) | |
tree | 31fa6bab43160c4b6f903cea42539f8bc86e59e2 /gcc/sel-sched.c | |
parent | cefe08a4ec4ff2e8dadfc26f89e70be5a3f21a1f (diff) | |
download | gcc-d0aca6abdbcbabc103df7a65e1e0dcbbad5e055e.zip gcc-d0aca6abdbcbabc103df7a65e1e0dcbbad5e055e.tar.gz gcc-d0aca6abdbcbabc103df7a65e1e0dcbbad5e055e.tar.bz2 |
re PR rtl-optimization/69307 (wrong code with -O2 -fselective-scheduling @ armv7a)
PR rtl-optimization/69307
* sel-sched.c (choose_best_pseudo_reg): Properly check for hard
registers in modes that span more than one register.
PR rtl-optimization/69307
* gcc.dg/pr69307.c: New test.
From-SVN: r234163
Diffstat (limited to 'gcc/sel-sched.c')
-rw-r--r-- | gcc/sel-sched.c | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c index bd32ab5..09cf028 100644 --- a/gcc/sel-sched.c +++ b/gcc/sel-sched.c @@ -1457,31 +1457,44 @@ choose_best_pseudo_reg (regset used_regs, gcc_assert (mode == GET_MODE (dest)); orig_regno = REGNO (dest); - if (!REGNO_REG_SET_P (used_regs, orig_regno)) - { - if (orig_regno < FIRST_PSEUDO_REGISTER) - { - gcc_assert (df_regs_ever_live_p (orig_regno)); + /* Check that nothing in used_regs intersects with orig_regno. When + we have a hard reg here, still loop over hard_regno_nregs. */ + if (HARD_REGISTER_NUM_P (orig_regno)) + { + int j, n; + for (j = 0, n = hard_regno_nregs[orig_regno][mode]; j < n; j++) + if (REGNO_REG_SET_P (used_regs, orig_regno + j)) + break; + if (j < n) + continue; + } + else + { + if (REGNO_REG_SET_P (used_regs, orig_regno)) + continue; + } + if (HARD_REGISTER_NUM_P (orig_regno)) + { + gcc_assert (df_regs_ever_live_p (orig_regno)); - /* For hard registers, we have to check hardware imposed - limitations (frame/stack registers, calls crossed). */ - if (!TEST_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, - orig_regno)) - { - /* Don't let register cross a call if it doesn't already - cross one. This condition is written in accordance with - that in sched-deps.c sched_analyze_reg(). */ - if (!reg_rename_p->crosses_call - || REG_N_CALLS_CROSSED (orig_regno) > 0) - return gen_rtx_REG (mode, orig_regno); - } + /* For hard registers, we have to check hardware imposed + limitations (frame/stack registers, calls crossed). */ + if (!TEST_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, + orig_regno)) + { + /* Don't let register cross a call if it doesn't already + cross one. This condition is written in accordance with + that in sched-deps.c sched_analyze_reg(). */ + if (!reg_rename_p->crosses_call + || REG_N_CALLS_CROSSED (orig_regno) > 0) + return gen_rtx_REG (mode, orig_regno); + } - bad_hard_regs = true; - } - else - return dest; - } - } + bad_hard_regs = true; + } + else + return dest; + } *is_orig_reg_p_ptr = false; |