Commit 078134e5 by Georg-Johann Lay Committed by Georg-Johann Lay

New avt target pass to work around performance loss by PR fix.

gcc/
	New avt target pass to work around performance loss by PR fix.
	PR target/71676
	PR target/71678
	* config/avr/avr.md (casesi_<mode>_sequence) [qi,hi]: 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-2.c: New test.

From-SVN: r241504
parent c7212a15
2016-10-25 Georg-Johann Lay <avr@gjlay.de> 2016-10-25 Georg-Johann Lay <avr@gjlay.de>
New avt target pass to work around performance loss by PR fix.
PR target/71676
PR target/71678
* config/avr/avr.md (casesi_<mode>_sequence) [qi,hi]: 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.
2016-10-25 Georg-Johann Lay <avr@gjlay.de>
Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com> Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
PR target/71676 PR target/71676
......
...@@ -17,6 +17,17 @@ ...@@ -17,6 +17,17 @@
along with GCC; see the file COPYING3. If not see along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
/* casesi uses a SImode switch index which is quite costly as most code will
work on HImode or QImode. The following pass runs right after .expand and
tries to fix such situations by operating on the original mode. This
reduces code size and register pressure.
The assertion is that the code generated by casesi is unaltered and a
a sign-extend or zero-extend from QImode or HImode precedes the casesi
insns withaout any insns in between. */
INSERT_PASS_AFTER (pass_expand, 1, avr_pass_casesi);
/* This avr-specific pass (re)computes insn notes, in particular REG_DEAD /* This avr-specific pass (re)computes insn notes, in particular REG_DEAD
notes which are used by `avr.c::reg_unused_after' and branch offset notes which are used by `avr.c::reg_unused_after' and branch offset
computations. These notes must be correct, i.e. there must be no computations. These notes must be correct, i.e. there must be no
......
...@@ -129,6 +129,7 @@ extern bool avr_mem_memx_p (rtx); ...@@ -129,6 +129,7 @@ extern bool avr_mem_memx_p (rtx);
extern bool avr_load_libgcc_p (rtx); extern bool avr_load_libgcc_p (rtx);
extern bool avr_xload_libgcc_p (machine_mode); extern bool avr_xload_libgcc_p (machine_mode);
extern rtx avr_eval_addr_attrib (rtx x); extern rtx avr_eval_addr_attrib (rtx x);
extern bool avr_casei_sequence_check_operands (rtx *xop);
static inline unsigned static inline unsigned
regmask (machine_mode mode, unsigned regno) regmask (machine_mode mode, unsigned regno)
...@@ -158,6 +159,7 @@ namespace gcc { class context; } ...@@ -158,6 +159,7 @@ namespace gcc { class context; }
class rtl_opt_pass; class rtl_opt_pass;
extern rtl_opt_pass *make_avr_pass_recompute_notes (gcc::context *); extern rtl_opt_pass *make_avr_pass_recompute_notes (gcc::context *);
extern rtl_opt_pass *make_avr_pass_casesi (gcc::context *);
/* From avr-log.c */ /* From avr-log.c */
......
...@@ -4598,9 +4598,9 @@ ...@@ -4598,9 +4598,9 @@
(set_attr "length" "4")]) (set_attr "length" "4")])
;; "*cmpqi" ;; "cmpqi3"
;; "*cmpqq" "*cmpuqq" ;; "cmpqq3" "cmpuqq3"
(define_insn "*cmp<mode>" (define_insn "cmp<mode>3"
[(set (cc0) [(set (cc0)
(compare (match_operand:ALL1 0 "register_operand" "r ,r,d") (compare (match_operand:ALL1 0 "register_operand" "r ,r,d")
(match_operand:ALL1 1 "nonmemory_operand" "Y00,r,i")))] (match_operand:ALL1 1 "nonmemory_operand" "Y00,r,i")))]
...@@ -4640,10 +4640,10 @@ ...@@ -4640,10 +4640,10 @@
[(set_attr "cc" "compare") [(set_attr "cc" "compare")
(set_attr "length" "2")]) (set_attr "length" "2")])
;; "*cmphi" ;; "cmphi3"
;; "*cmphq" "*cmpuhq" ;; "cmphq3" "cmpuhq3"
;; "*cmpha" "*cmpuha" ;; "cmpha3" "cmpuha3"
(define_insn "*cmp<mode>" (define_insn "cmp<mode>3"
[(set (cc0) [(set (cc0)
(compare (match_operand:ALL2 0 "register_operand" "!w ,r ,r,d ,r ,d,r") (compare (match_operand:ALL2 0 "register_operand" "!w ,r ,r,d ,r ,d,r")
(match_operand:ALL2 1 "nonmemory_operand" "Y00,Y00,r,s ,s ,M,n Ynn"))) (match_operand:ALL2 1 "nonmemory_operand" "Y00,Y00,r,s ,s ,M,n Ynn")))
...@@ -5153,6 +5153,27 @@ ...@@ -5153,6 +5153,27 @@
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
;; FIXME: casesi comes up with an SImode switch value $0 which
;; is quite some overhead because most code would use HI or
;; even QI. We add an AVR specific pass .avr-casesi which
;; tries to recover from the superfluous extension to SImode.
;;
;; Using "tablejump" could be a way out, but this also does
;; not perform in a satisfying manner as the middle end will
;; already multiply the table index by 2. Note that this
;; multiplication is performed by libgcc's __tablejump2__.
;; The multiplication there, however, runs *after* the table
;; start (a byte address) has been added, not before it like
;; "tablejump" will do.
;;
;; The preferred solution would be to let the middle ends pass
;; down information on the index as an additional casesi operand.
;;
;; If this expander is changed, you'll likely have to go through
;; "casesi_<mode>_sequence" (used to recog + extract casesi
;; sequences in pass .avr-casesi) and propagate all adjustments
;; also to that pattern and the code of the extra pass.
(define_expand "casesi" (define_expand "casesi"
[(parallel [(set (match_dup 5) [(parallel [(set (match_dup 5)
(plus:SI (match_operand:SI 0 "register_operand") (plus:SI (match_operand:SI 0 "register_operand")
...@@ -5198,6 +5219,49 @@ ...@@ -5198,6 +5219,49 @@
}) })
;; This insn is used only for easy operand extraction.
;; The elements must match an extension to SImode plus
;; a sequence generated by casesi above.
;; "casesi_qi_sequence"
;; "casesi_hi_sequence"
(define_insn "casesi_<mode>_sequence"
[(set (match_operand:SI 0 "register_operand")
(match_operator:SI 9 "extend_operator"
[(match_operand:QIHI 10 "register_operand")]))
;; What follows is a matcher for code from casesi.
;; We keep the same operand numbering (except for $9 and $10
;; which don't appear in casesi).
(parallel [(set (match_operand:SI 5 "register_operand")
(plus:SI (match_dup 0)
(match_operand:SI 1 "const_int_operand")))
(clobber (scratch:QI))])
(parallel [(set (cc0)
(compare (match_dup 5)
(match_operand:SI 2 "const_int_operand")))
(clobber (scratch:QI))])
(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 4))
(pc)))
(set (match_operand:HI 7 "register_operand")
(match_operand:HI 6))
(parallel [(set (pc)
(unspec:HI [(match_dup 7)] UNSPEC_INDEX_JMP))
(use (label_ref (match_operand 3)))
(clobber (match_dup 7))
(clobber (match_operand:QI 8))])]
"optimize
&& avr_casei_sequence_check_operands (operands)"
{ gcc_unreachable(); }
)
;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;; This instruction sets Z flag ;; This instruction sets Z flag
...@@ -5550,7 +5614,7 @@ ...@@ -5550,7 +5614,7 @@
;; This peephole avoids code like ;; This peephole avoids code like
;; ;;
;; TST Rn ; *cmpqi ;; TST Rn ; cmpqi3
;; BREQ .+2 ; branch ;; BREQ .+2 ; branch
;; RJMP .Lm ;; RJMP .Lm
;; ;;
......
...@@ -178,6 +178,10 @@ ...@@ -178,6 +178,10 @@
(and (match_operand 0 "comparison_operator") (and (match_operand 0 "comparison_operator")
(not (match_code "gt,gtu,le,leu")))) (not (match_code "gt,gtu,le,leu"))))
;; True for SIGN_EXTEND, ZERO_EXTEND.
(define_predicate "extend_operator"
(match_code "sign_extend,zero_extend"))
;; Return true if OP is a valid call operand. ;; Return true if OP is a valid call operand.
(define_predicate "call_insn_operand" (define_predicate "call_insn_operand"
(and (match_code "mem") (and (match_code "mem")
......
2016-10-25 Georg-Johann Lay <avr@gjlay.de> 2016-10-25 Georg-Johann Lay <avr@gjlay.de>
PR target/71676
PR target/71678
* gcc.target/avr/pr71676-2.c: New test.
2016-10-25 Georg-Johann Lay <avr@gjlay.de>
Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com> Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
PR target/71676 PR target/71676
......
/* { dg-do compile } */
/* { dg-options "-dp -w -Os -fno-tree-switch-conversion" } */
#define MK_FUN(NAME, TYP, V) \
unsigned char __attribute__((noinline,noclone)) \
select_## NAME (TYP x, unsigned char y) \
{ \
switch (x) \
{ \
case V + 0: return 0 + y; \
case V + 1: return 1; \
case V + 2: return 2 + y; \
case V + 3: return 3; \
case V + 4: return 4 + y; \
case V + 5: return 5; \
case V + 6: return 6 + y; \
case V + 7: return 7; \
case V + 8: return 8 + y; \
case V + 9: return 9; \
case V + 10: return 10 + y; \
case V + 11: return 11; \
case V + 12: return 12 + y; \
case V + 13: return 13; \
case V + 14: return 14 + y; \
case V + 15: return 15; \
} \
return x; \
}
MK_FUN (0_s8, signed char, 0)
MK_FUN (0_u8, unsigned char, 0)
MK_FUN (0_s16, signed int, 0)
MK_FUN (0_u16, unsigned int, 0)
MK_FUN (m4_s8, signed char, -4)
MK_FUN (m4_u8, unsigned char, -4)
MK_FUN (m4_s16, signed int, -4)
MK_FUN (m4_u16, unsigned int, -4)
MK_FUN (4_s8, signed char, 4)
MK_FUN (4_u8, unsigned char, 4)
MK_FUN (4_s16, signed int, 4)
MK_FUN (4_u16, unsigned int, 4)
/* { dg-final { scan-assembler-not "extendqisi" } } */
/* { dg-final { scan-assembler-not "extendhisi" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment