diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2024-03-08 13:29:13 +0100 |
---|---|---|
committer | Georg-Johann Lay <avr@gjlay.de> | 2024-03-08 13:40:20 +0100 |
commit | 40209cb15a3f2af8233ee887dc960992f358ad86 (patch) | |
tree | 14fc73534ca31b218612a135408021d9de4bd6c2 /gcc/config/avr | |
parent | d6bcc2e257026b383ac3e6ccdee13f7763b38621 (diff) | |
download | gcc-40209cb15a3f2af8233ee887dc960992f358ad86.zip gcc-40209cb15a3f2af8233ee887dc960992f358ad86.tar.gz gcc-40209cb15a3f2af8233ee887dc960992f358ad86.tar.bz2 |
AVR: Add an insn combine pattern for offset computation.
Computing uint16_t += 2 * uint8_t can occur when an offset
into a 16-bit array is computed. Without this pattern is costs
six instructions: A move (1), a zero-extend (1), a shift (2) and
an addition (2). With this pattern it costs 4.
gcc/
* config/avr/avr.md (*addhi3_zero_extend.ashift1): New pattern.
* config/avr/avr.cc (avr_rtx_costs_1) [PLUS]: Compute its cost.
Diffstat (limited to 'gcc/config/avr')
-rw-r--r-- | gcc/config/avr/avr.cc | 11 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 33 |
2 files changed, 44 insertions, 0 deletions
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index b87ae6a..1fa4b55 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -12513,6 +12513,17 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code, return true; case PLUS: + // uint16_t += 2 * uint8_t; + if (mode == HImode + && GET_CODE (XEXP (x, 0)) == ASHIFT + && REG_P (XEXP (x, 1)) + && XEXP (XEXP (x, 0), 1) == const1_rtx + && GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND) + { + *total = COSTS_N_INSNS (4); + return true; + } + if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND && REG_P (XEXP (x, 1))) { diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index bc8a59c..52b6cff 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -1630,6 +1630,39 @@ "subi %A0,%n2\;sbc %B0,%B0" [(set_attr "length" "2")]) + +;; Occurs when computing offsets into 16-bit arrays. +;; Saves up to 2 instructions. +(define_insn_and_split "*addhi3_zero_extend.ashift1.split" + [(set (match_operand:HI 0 "register_operand" "=r") + (plus:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) + (const_int 1)) + (match_operand:HI 2 "register_operand" "0")))] + "" + "#" + "&& reload_completed" + [(parallel [(set (match_dup 0) + (plus:HI (ashift:HI (zero_extend:HI (match_dup 1)) + (const_int 1)) + (match_dup 2))) + (clobber (reg:CC REG_CC))])]) + +(define_insn "*addhi3_zero_extend.ashift1" + [(set (match_operand:HI 0 "register_operand" "=r") + (plus:HI (ashift:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r")) + (const_int 1)) + (match_operand:HI 2 "register_operand" "0"))) + (clobber (reg:CC REG_CC))] + "reload_completed" + { + return reg_overlap_mentioned_p (operands[1], operands[0]) + ? "mov __tmp_reg__,%1\;add %A0,__tmp_reg__\;adc %B0,__zero_reg__\;add %A0,__tmp_reg__\;adc %B0,__zero_reg__" + : "add %A0,%1\;adc %B0,__zero_reg__\;add %A0,%1\;adc %B0,__zero_reg__"; + } + [(set (attr "length") + (symbol_ref ("4 + reg_overlap_mentioned_p (operands[1], operands[0])")))]) + + (define_insn_and_split "*usum_widenqihi3_split" [(set (match_operand:HI 0 "register_operand" "=r") (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "0")) |