mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
AVR: target/90616 - Improve adding constants that are 0 mod 256.
This patch introduces a new insn that works as an insn combine pattern for (plus:HI (zero_extend:HI (reg:QI)) (const_0mod256_operannd:HI)) which requires at most 2 instructions. When the input register operand is already in HImode, the addhi3 printer only adds the hi8 part when it sees a SYMBOL_REF or CONST aligned to at least 256 bytes. (The CONST_INT case was already handled). gcc/ PR target/90616 * config/avr/predicates.md (const_0mod256_operand): New predicate. * config/avr/constraints.md (Cp8): New constraint. * config/avr/avr.md (*aligned_add_symbol): New insn. * config/avr/avr.cc (avr_out_plus_symbol) [HImode]: When op2 is a multiple of 256, there is no need to add / subtract the lo8 part. (avr_rtx_costs_1) [PLUS && HImode]: Return expected costs for new insn *aligned_add_symbol as it applies.
This commit is contained in:
parent
5104fe4c78
commit
e21fef7da9
@ -9434,6 +9434,12 @@ avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen)
|
||||
|
||||
gcc_assert (mode == HImode || mode == PSImode);
|
||||
|
||||
if (mode == HImode
|
||||
&& const_0mod256_operand (xop[2], HImode))
|
||||
return avr_asm_len (PLUS == code
|
||||
? "subi %B0,hi8(-(%2))"
|
||||
: "subi %B0,hi8(%2)", xop, plen, -1);
|
||||
|
||||
avr_asm_len (PLUS == code
|
||||
? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
|
||||
: "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
|
||||
@ -12759,6 +12765,14 @@ avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
|
||||
*total = COSTS_N_INSNS (3);
|
||||
return true;
|
||||
}
|
||||
// *aligned_add_symbol
|
||||
if (mode == HImode
|
||||
&& GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
|
||||
&& const_0mod256_operand (XEXP (x, 1), HImode))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1.5);
|
||||
return true;
|
||||
}
|
||||
|
||||
// *add<PSISI:mode>3.zero_extend.<QIPSI:mode>
|
||||
// *addhi3_zero_extend
|
||||
|
@ -1617,6 +1617,20 @@
|
||||
"subi %A0,%n2\;sbc %B0,%B0"
|
||||
[(set_attr "length" "2")])
|
||||
|
||||
;; PR90616: Adding symbols that are aligned to 256 bytes can
|
||||
;; save up to two instructions.
|
||||
(define_insn "*aligned_add_symbol"
|
||||
[(set (match_operand:HI 0 "register_operand" "=d")
|
||||
(plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
|
||||
(match_operand:HI 2 "const_0mod256_operand" "Cp8")))]
|
||||
""
|
||||
{
|
||||
return REGNO (operands[0]) == REGNO (operands[1])
|
||||
? "ldi %B0,hi8(%2)"
|
||||
: "mov %A0,%1\;ldi %B0,hi8(%2)";
|
||||
}
|
||||
[(set (attr "length")
|
||||
(symbol_ref ("2 - (REGNO (operands[0]) == REGNO (operands[1]))")))])
|
||||
|
||||
;; Occurs when computing offsets into 16-bit arrays.
|
||||
;; Saves up to 2 instructions.
|
||||
|
@ -253,6 +253,11 @@
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (ival, -255, -1)")))
|
||||
|
||||
(define_constraint "Cp8"
|
||||
"A constant integer or symbolic operand that is at least .p2align 8."
|
||||
(and (match_code "const_int,symbol_ref,const")
|
||||
(match_test "const_0mod256_operand (op, HImode)")))
|
||||
|
||||
;; CONST_FIXED is no element of 'n' so cook our own.
|
||||
;; "i" or "s" would match but because the insn uses iterators that cover
|
||||
;; INT_MODE, "i" or "s" is not always possible.
|
||||
|
@ -171,6 +171,20 @@
|
||||
(define_predicate "symbol_ref_operand"
|
||||
(match_code "symbol_ref"))
|
||||
|
||||
;; Returns true when OP is a SYMBOL_REF, CONST or CONST_INT that is
|
||||
;; a multiple of 256, i.e. lo8(OP) = 0.
|
||||
(define_predicate "const_0mod256_operand"
|
||||
(ior (and (match_code "symbol_ref")
|
||||
(match_test "SYMBOL_REF_DECL (op)
|
||||
&& DECL_P (SYMBOL_REF_DECL (op))
|
||||
&& DECL_ALIGN (SYMBOL_REF_DECL (op)) >= 8 * 256"))
|
||||
(and (match_code "const")
|
||||
(match_test "GET_CODE (XEXP (op, 0)) == PLUS")
|
||||
(match_test "const_0mod256_operand (XEXP (XEXP (op, 0), 0), HImode)")
|
||||
(match_test "const_0mod256_operand (XEXP (XEXP (op, 0), 1), HImode)"))
|
||||
(and (match_code "const_int")
|
||||
(match_test "INTVAL (op) % 256 == 0"))))
|
||||
|
||||
;; Return true if OP is a text segment reference.
|
||||
;; This is needed for program memory address expressions.
|
||||
(define_predicate "text_segment_operand"
|
||||
|
Loading…
Reference in New Issue
Block a user