AVR: Overhaul the avr-ifelse RTL optimization pass.
Mini-pass avr-ifelse realizes optimizations that replace two cbranch insns with one comparison and two branches. This patch adds the following improvements: - The right operand of the comparisons may also be REGs. Formerly only CONST_INT was handled. - The RTX code of the first comparison in no more restricted to (effectively) EQ. - When the second cbranch is located in the fallthrough path of the first cbranch, then difficult (expensive) comparisons can always be avoided. This may require to swap the branch targets. (When the second cbranch is located after the target label of the first one, then getting rid of difficult branches would require to reorder blocks.) - The code has been cleaned up: avr_rest_of_handle_ifelse() now just scans the insn stream for optimization candidates. The code that actually performs the transformation has been outsourced to the new function avr_optimize_2ifelse(). - The code to find a better representation for reg-const_int comparisons has been split into two parts: First try to find codes such that the right-hand sides of the comparisons are the same (avr_2comparisons_rhs). When this succeeds then one comparison can serve two branches, and that function tries to get rid of difficult branches. This is always possible when the second cbranch is located in the fallthrough path of the first one. Some final notes on why we don't use compare-elim: 1) The two cbranch insns may come with different scratch operands depending on the chosen constraint alternatives. There are cases where the outgoing comparison requires a scratch but only one incoming cbranch has one. 2) Avoiding difficult branches can be achieved by rewiring basic blocks. compare-elim doesn't do that; it doesn't even know the costs of the branch codes. 3) avr_2comparisons_rhs() may de-canonicalize a comparison to achieve its goal. compare-elim doesn't know how to do that. 4) There are more reasons, see for example the commit message and discussion for PR115830. avr_2comparisons_rhs tries to decompose the interval as given by some [u]intN_t into three intervals using the new Ranges struct that implemens set operations on finite unions of intervals. Sadly, value-range.h is not well suited for that, and writing a wrapper around it that avoids all corner case ICEs would be more laborious than struct Ranges. gcc/ * config/avr/avr.cc (INCLUDE_VECTOR): Define it. (cfganal.h): Include it. (Ranges): New struct. (avr_2comparisons_rhs, avr_redundant_compare_regs) (avr_strict_signed_p, avr_strict_unsigned_p): New static functions. (avr_redundant_compare): Overhaul: Allow more cases. (avr_optimize_2ifelse): New static function, outsourced from... (avr_rest_of_handle_ifelse): ...this method. gcc/testsuite/ * gcc.target/avr/torture/ifelse-c.h: New file. * gcc.target/avr/torture/ifelse-d.h: New file. * gcc.target/avr/torture/ifelse-q.h: New file. * gcc.target/avr/torture/ifelse-r.h: New file. * gcc.target/avr/torture/ifelse-c-i8.c: New test. * gcc.target/avr/torture/ifelse-d-i8.c: New test. * gcc.target/avr/torture/ifelse-q-i8.c: New test. * gcc.target/avr/torture/ifelse-r-i8.c: New test. * gcc.target/avr/torture/ifelse-c-i16.c: New test. * gcc.target/avr/torture/ifelse-d-i16.c: New test. * gcc.target/avr/torture/ifelse-q-i16.c: New test. * gcc.target/avr/torture/ifelse-r-i16.c: New test. * gcc.target/avr/torture/ifelse-c-u16.c: New test. * gcc.target/avr/torture/ifelse-d-u16.c: New test. * gcc.target/avr/torture/ifelse-q-u16.c: New test. * gcc.target/avr/torture/ifelse-r-u16.c: New test.
Showing
- gcc/config/avr/avr.cc 758 additions, 229 deletionsgcc/config/avr/avr.cc
- gcc/testsuite/gcc.target/avr/torture/ifelse-c-i16.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-c-i16.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-c-i8.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-c-i8.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-c-u16.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-c-u16.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-c.h 99 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-c.h
- gcc/testsuite/gcc.target/avr/torture/ifelse-d-i16.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-d-i16.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-d-i8.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-d-i8.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-d-u16.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-d-u16.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-d.h 82 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-d.h
- gcc/testsuite/gcc.target/avr/torture/ifelse-q-i16.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-q-i16.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-q-i8.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-q-i8.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-q-u16.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-q-u16.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-q.h 92 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-q.h
- gcc/testsuite/gcc.target/avr/torture/ifelse-r-i16.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-r-i16.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-r-i8.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-r-i8.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-r-u16.c 12 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-r-u16.c
- gcc/testsuite/gcc.target/avr/torture/ifelse-r.h 100 additions, 0 deletionsgcc/testsuite/gcc.target/avr/torture/ifelse-r.h
Loading
Please register or sign in to comment