2016-10-24 13:33 GMT+03:00 Georg-Johann Lay <a...@gjlay.de>: > This fixes issues with casesi that originate from taking hard coded > subreg:HI of the SImode switch value: > > * The subreg is cutting away the upper bytes which is wrong code if the > switch actually operates on a value > 16 bits. > > * The hard-coded subreg will ICE on DImode because of nested subregs. > > The fix is simple: Just avoid subreg in casesi expander. > > What's not so simple is to generate code that performs as efficiently as > with the old solution for switch values <= 16 bits. > > The performance issue is cured by a new pass that scans the insn stream, > recognizes extension + casesi insns and then rectifies the situation by > using the non-extended switch value. This code is straight forward but > somewhat tedious to write down... > > A much superior solution would be to add one more operand to casesi and pass > down, say (zero_extend:SI (reg:QI 42)), to the casesi expander so that be > back-end could take advantage of this information. Again, going across all > targets is beyond what I can do for GCC, even if it would be much less code > compared to the current solution... > > The performance fix assumes that the extension appears right before the > casesi sequence which is due to how the middle-end prepares casesi operands. > > No regressions with ATmega128 and ATmega2560. > > Ok for trunk?
Approved. Please apply. > > Johann > > > gcc/ > PR target/71676 > PR target/71678 > * config/avr/avr.md (casesi): Rewrite avoiding subregs of SI. > (casesi_<mode>_sequence): New insn. > (*cmp<mode>) [qi,qq,uqq,hi,hq,uhq,ha,uha]: Rename to cmp<mode>3. > * config/avr/predicates.md (extend_operator): New. > * config/avr/avr-passes.def (avr_pass_casesi): Register new pass. > * config/avr/avr-protos.h (avr_casei_sequence_check_operands) > (make_avr_pass_casesi): New prototypes. > * config/avr/avr.c (print-rtl.h): Include it. > (pass_data avr_pass_data_casesi): Data for new pass. > (avr_pass_casesi): New class implementing rtl_opt_pass .avr-casesi. > (make_avr_pass_casesi, avr_parallel_insn_from_insns) > (avr_is_casesi_sequence, avr_casei_sequence_check_operands) > (avr_optimize_casesi): New functions. > > gcc/testsuite/ > PR target/71676 > PR target/71678 > * gcc.target/avr/pr71676-1.c: New test. > * gcc.target/avr/pr71676-2.c: New test. > * gcc.target/avr/pr71676-3.c: New test. > * gcc.target/avr/pr71676.c: New test. > * gcc.target/avr/pr71678.c: New test. > >