diff options
author | Kyrylo Tkachov <ktkachov@gcc.gnu.org> | 2016-01-11 12:13:50 +0000 |
---|---|---|
committer | Kyrylo Tkachov <ktkachov@gcc.gnu.org> | 2016-01-11 12:13:50 +0000 |
commit | 5baf45323b70abe259bffc89425e9f0155a1a7a3 (patch) | |
tree | 590458ee63e277d05bcf8da716d1961107023f90 /gcc | |
parent | 1c5211b13cb66b65f92a8289d221e2c3f4a3dfe2 (diff) | |
download | gcc-5baf45323b70abe259bffc89425e9f0155a1a7a3.zip gcc-5baf45323b70abe259bffc89425e9f0155a1a7a3.tar.gz gcc-5baf45323b70abe259bffc89425e9f0155a1a7a3.tar.bz2 |
[RTL-ifcvt] PR rtl-optimization/68841: Make sure one basic block doesn't clobber CC reg usage of the other
PR rtl-optimization/68841
* ifcvt.c (struct noce_if_info): Add orig_x field.
(bbs_ok_for_cmove_arith): Add to_rename parameter.
Don't record conflicts on to_rename if it's present.
Allow memory destinations in sets.
(noce_try_cmove_arith): Call bbs_ok_for_cmove_arith even on simple
blocks, passing orig_x to the checks.
(noce_process_if_block): Set if_info->orig_x appropriately.
* gcc.dg/pr68841.c: New test.
* gcc.c-torture/execute/pr68841.c: New test.
From-SVN: r232223
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/ifcvt.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr68841.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr68841.c | 34 |
5 files changed, 106 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5124d69..c910e89 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2016-01-11 Bernd Schmidt <bschmidt@redhat.com> + Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR rtl-optimization/68841 + * ifcvt.c (struct noce_if_info): Add orig_x field. + (bbs_ok_for_cmove_arith): Add to_rename parameter. + Don't record conflicts on to_rename if it's present. + Allow memory destinations in sets. + (noce_try_cmove_arith): Call bbs_ok_for_cmove_arith even on simple + blocks, passing orig_x to the checks. + (noce_process_if_block): Set if_info->orig_x appropriately. + 2016-01-11 Tom de Vries <tom@codesourcery.com> PR tree-optimization/69069 diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 723ea3e..7d94e75 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -793,6 +793,9 @@ struct noce_if_info /* The SET_DEST of INSN_A. */ rtx x; + /* The original set destination that the THEN and ELSE basic blocks finally + write their result to. */ + rtx orig_x; /* True if this if block is not canonical. In the canonical form of if blocks, the THEN_BB is the block reached via the fallthru edge from TEST_BB. For the noce transformations, we allow the symmetric @@ -1867,11 +1870,13 @@ insn_valid_noce_process_p (rtx_insn *insn, rtx cc) } -/* Return true iff the registers that the insns in BB_A set do not - get used in BB_B. */ +/* Return true iff the registers that the insns in BB_A set do not get + used in BB_B. If TO_RENAME is non-NULL then it is a location that will be + renamed later by the caller and so conflicts on it should be ignored + in this function. */ static bool -bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b) +bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename) { rtx_insn *a_insn; bitmap bba_sets = BITMAP_ALLOC (®_obstack); @@ -1891,10 +1896,10 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b) BITMAP_FREE (bba_sets); return false; } - /* Record all registers that BB_A sets. */ FOR_EACH_INSN_DEF (def, a_insn) - bitmap_set_bit (bba_sets, DF_REF_REGNO (def)); + if (!(to_rename && DF_REF_REG (def) == to_rename)) + bitmap_set_bit (bba_sets, DF_REF_REGNO (def)); } rtx_insn *b_insn; @@ -1913,8 +1918,15 @@ bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b) } /* Make sure this is a REG and not some instance - of ZERO_EXTRACT or SUBREG or other dangerous stuff. */ - if (!REG_P (SET_DEST (sset_b))) + of ZERO_EXTRACT or SUBREG or other dangerous stuff. + If we have a memory destination then we have a pair of simple + basic blocks performing an operation of the form [addr] = c ? a : b. + bb_valid_for_noce_process_p will have ensured that these are + the only stores present. In that case [addr] should be the location + to be renamed. Assert that the callers set this up properly. */ + if (MEM_P (SET_DEST (sset_b))) + gcc_assert (rtx_equal_p (SET_DEST (sset_b), to_rename)); + else if (!REG_P (SET_DEST (sset_b))) { BITMAP_FREE (bba_sets); return false; @@ -2083,9 +2095,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info) } } - if (then_bb && else_bb && !a_simple && !b_simple - && (!bbs_ok_for_cmove_arith (then_bb, else_bb) - || !bbs_ok_for_cmove_arith (else_bb, then_bb))) + if (then_bb && else_bb + && (!bbs_ok_for_cmove_arith (then_bb, else_bb, if_info->orig_x) + || !bbs_ok_for_cmove_arith (else_bb, then_bb, if_info->orig_x))) return FALSE; start_sequence (); @@ -3403,6 +3415,7 @@ noce_process_if_block (struct noce_if_info *if_info) /* Only operate on register destinations, and even then avoid extending the lifetime of hard registers on small register class machines. */ orig_x = x; + if_info->orig_x = orig_x; if (!REG_P (x) || (HARD_REGISTER_P (x) && targetm.small_register_classes_for_mode_p (GET_MODE (x)))) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c1ae6ef..8157e43 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-01-11 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR rtl-optimization/68841 + * gcc.dg/pr68841.c: New test. + * gcc.c-torture/execute/pr68841.c: New test. + 2016-01-11 Yuri Rumyantsev <ysrumyan@gmail.com> PR rtl-optimization/68920 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr68841.c b/gcc/testsuite/gcc.c-torture/execute/pr68841.c new file mode 100644 index 0000000..15a27e7 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr68841.c @@ -0,0 +1,31 @@ +static inline int +foo (int *x, int y) +{ + int z = *x; + while (y > z) + z *= 2; + return z; +} + +int +main () +{ + int i; + for (i = 1; i < 17; i++) + { + int j; + int k; + j = foo (&i, 7); + if (i >= 7) + k = i; + else if (i >= 4) + k = 8 + (i - 4) * 2; + else if (i == 3) + k = 12; + else + k = 8; + if (j != k) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr68841.c b/gcc/testsuite/gcc.dg/pr68841.c new file mode 100644 index 0000000..470048c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr68841.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-Og -fif-conversion -flive-range-shrinkage -fpeel-loops -frerun-cse-after-loop" } */ + +static inline int +foo (int *x, int y) +{ + int z = *x; + while (y > z) + z *= 2; + return z; +} + +int +main () +{ + int i; + for (i = 1; i < 17; i++) + { + int j; + int k; + j = foo (&i, 7); + if (i >= 7) + k = i; + else if (i >= 4) + k = 8 + (i - 4) * 2; + else if (i == 3) + k = 12; + else + k = 8; + if (j != k) + __builtin_abort (); + } + return 0; +} |