aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/avr
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2024-03-08 13:29:13 +0100
committerGeorg-Johann Lay <avr@gjlay.de>2024-03-08 13:40:20 +0100
commit40209cb15a3f2af8233ee887dc960992f358ad86 (patch)
tree14fc73534ca31b218612a135408021d9de4bd6c2 /gcc/config/avr
parentd6bcc2e257026b383ac3e6ccdee13f7763b38621 (diff)
downloadgcc-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.cc11
-rw-r--r--gcc/config/avr/avr.md33
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"))