From 9eb7045b54d2593c5acbb67081be9158bf2d50d0 Mon Sep 17 00:00:00 2001 From: Vladimir Makarov Date: Fri, 27 Jan 2017 16:50:11 +0000 Subject: [PATCH] re PR target/79131 (ICE: in extract_constrain_insn, at recog.c:2213, big-endian ARM) 2017-01-27 Vladimir Makarov PR target/79131 * lra-assigns.c (find_hard_regno_for_1): Take endianess for into account to calculate conflict_set. 2017-01-27 Vladimir Makarov PR target/79131 * gcc.target/arm/pr79131.c: Rename to gcc.target/arm/pr79131-1.c. * gcc.target/arm/pr79131-2.c: New. From-SVN: r244989 --- gcc/ChangeLog | 6 ++ gcc/lra-assigns.c | 65 +++++++++++-------- gcc/testsuite/ChangeLog | 6 ++ .../gcc.target/arm/{pr79131.c => pr79131-1.c} | 0 gcc/testsuite/gcc.target/arm/pr79131-2.c | 17 +++++ 5 files changed, 68 insertions(+), 26 deletions(-) rename gcc/testsuite/gcc.target/arm/{pr79131.c => pr79131-1.c} (100%) create mode 100644 gcc/testsuite/gcc.target/arm/pr79131-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b70acef6953..2c90d06c8d4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-01-27 Vladimir Makarov + + PR target/79131 + * lra-assigns.c (find_hard_regno_for_1): Take endianess for into + account to calculate conflict_set. + 2017-01-27 Bin Cheng PR rtl-optimization/78559 diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c index 74a3195c4db..0ccd42546b7 100644 --- a/gcc/lra-assigns.c +++ b/gcc/lra-assigns.c @@ -564,32 +564,45 @@ find_hard_regno_for_1 (int regno, int *cost, int try_only_hard_regno, offset = lra_reg_info[regno].offset; CLEAR_HARD_REG_SET (impossible_start_hard_regs); EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno) - if (lra_reg_val_equal_p (conflict_regno, val, offset)) - { - conflict_hr = live_pseudos_reg_renumber[conflict_regno]; - nregs = (hard_regno_nregs[conflict_hr] - [lra_reg_info[conflict_regno].biggest_mode]); - /* Remember about multi-register pseudos. For example, 2 hard - register pseudos can start on the same hard register but can - not start on HR and HR+1/HR-1. */ - for (hr = conflict_hr + 1; - hr < FIRST_PSEUDO_REGISTER && hr < conflict_hr + nregs; - hr++) - SET_HARD_REG_BIT (impossible_start_hard_regs, hr); - for (hr = conflict_hr - 1; - hr >= 0 && hr + hard_regno_nregs[hr][biggest_mode] > conflict_hr; - hr--) - SET_HARD_REG_BIT (impossible_start_hard_regs, hr); - } - else - { - add_to_hard_reg_set (&conflict_set, - lra_reg_info[conflict_regno].biggest_mode, - live_pseudos_reg_renumber[conflict_regno]); - if (hard_reg_set_subset_p (reg_class_contents[rclass], - conflict_set)) - return -1; - } + { + conflict_hr = live_pseudos_reg_renumber[conflict_regno]; + if (lra_reg_val_equal_p (conflict_regno, val, offset)) + { + conflict_hr = live_pseudos_reg_renumber[conflict_regno]; + nregs = (hard_regno_nregs[conflict_hr] + [lra_reg_info[conflict_regno].biggest_mode]); + /* Remember about multi-register pseudos. For example, 2 + hard register pseudos can start on the same hard register + but can not start on HR and HR+1/HR-1. */ + for (hr = conflict_hr + 1; + hr < FIRST_PSEUDO_REGISTER && hr < conflict_hr + nregs; + hr++) + SET_HARD_REG_BIT (impossible_start_hard_regs, hr); + for (hr = conflict_hr - 1; + hr >= 0 && hr + hard_regno_nregs[hr][biggest_mode] > conflict_hr; + hr--) + SET_HARD_REG_BIT (impossible_start_hard_regs, hr); + } + else + { + enum machine_mode biggest_conflict_mode + = lra_reg_info[conflict_regno].biggest_mode; + int biggest_conflict_nregs + = hard_regno_nregs[conflict_hr][biggest_conflict_mode]; + + nregs_diff = (biggest_conflict_nregs + - (hard_regno_nregs + [conflict_hr] + [PSEUDO_REGNO_MODE (conflict_regno)])); + add_to_hard_reg_set (&conflict_set, + biggest_conflict_mode, + conflict_hr + - (WORDS_BIG_ENDIAN ? nregs_diff : 0)); + if (hard_reg_set_subset_p (reg_class_contents[rclass], + conflict_set)) + return -1; + } + } EXECUTE_IF_SET_IN_SPARSESET (conflict_reload_and_inheritance_pseudos, conflict_regno) if (!lra_reg_val_equal_p (conflict_regno, val, offset)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f326e408743..9b164d30478 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-01-27 Vladimir Makarov + + PR target/79131 + * gcc.target/arm/pr79131.c: Rename to gcc.target/arm/pr79131-1.c. + * gcc.target/arm/pr79131-2.c: New. + 2017-01-27 Bill Schmidt PR target/65484 diff --git a/gcc/testsuite/gcc.target/arm/pr79131.c b/gcc/testsuite/gcc.target/arm/pr79131-1.c similarity index 100% rename from gcc/testsuite/gcc.target/arm/pr79131.c rename to gcc/testsuite/gcc.target/arm/pr79131-1.c diff --git a/gcc/testsuite/gcc.target/arm/pr79131-2.c b/gcc/testsuite/gcc.target/arm/pr79131-2.c new file mode 100644 index 00000000000..a670f0fec2b --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr79131-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mbig-endian" } */ + +struct nilfs_segment_usage { + int su_flags; +} a; +enum { NILFS_SEGMENT_USAGE_ACTIVE, NILFS_SEGMENT_USAGE_DIRTY } fn1(); +int b; +void fn2(int *, long long); +void fn3() { + int c, d; + struct nilfs_segment_usage e = a; + fn1(); + c = e.su_flags & 1 << NILFS_SEGMENT_USAGE_DIRTY; + d = c; + fn2(&b, d ? -1 : 0); +}