On 6/7/23 02:41, Georg-Johann Lay wrote:
Subject:
[patch,avr]: Improve bit-extractions as of PR109907.
From:
Georg-Johann Lay <a...@gjlay.de>
Date:
6/7/23, 02:41
To:
gcc-patches@gcc.gnu.org
CC:
Jeff Law <jeffreya...@gmail.com>, Denis Chertykov <cherty...@gmail.com>
This patch improves bit-extractions on AVR.
Andrew added some patches so that more bit extractions are
recognized in the middle-end and rtl optimizers.
The patch adds pattern for "extzv<mode>" and replaces the
deprecated "extzv".
There are still situations where expensive shifts are passed
down to the backend though , and in one situation the backend
uses better sequences for right-shift with an offset of MSB:
Instead of ROL/CLR/ROL sequence that needs constraint "0" for
operand $1, BST/CLR/BLD just requires "r" for $1 thus less
register pressure. Moreover, no scratch is required.
Asm out for (inverted) bit-extraction was out-sourced to a
C function which is more convenient.
Ok for master?
Johann
--
target/19907: Overhaul bit extractions.
o Logical right shift that shifts the MSB to position 0 can be performed in
such a way that the input operand constraint can be relaxed from "0"
to "r".
This results in less register pressure. Moreover, no scratch
register is
required in that case.
o The deprecated "extzv" pattern is replaced by "extzv<mode>" that allows
inputs of scalar integer modes of different sizes (1 up to 4 bytes).
o Existing patterns are adjusted to the more generic "extzv<mode>" pattern.
Some patterns are added as the middle-end has been reworked to spot
more bit-extraction opportunities.
o A C function is used to print the asm for bit extractions, which is more
convenient for complex output logic.
gcc/
PR target/109907
* config/avr/avr.md (adjust_len) [extr, extr_not]: New elements.
(MSB, SIZE): New mode attributes.
(any_shift): New code iterator.
(*lshr<mode>3_split, *lshr<mode>3, lshr<mode>3)
(*lshr<mode>3_const_split): Add constraint alternative for
the case of shift-offset = MSB. Ditch "length" attribute.
(extzv<mode): New. replaces extzv. Adjust following patterns.
Use avr_out_extr, avr_out_extr_not to print asm.
(*extzv.subreg.<mode>, *extzv.<mode>.subreg, *extzv.xor)
(*extzv<mode>.ge, *neg.ashiftrt<mode>.msb, *extzv.io.lsr7): New.
* config/avr/constraints.md (C15, C23, C31, Yil): New
* config/avr/predicates.md (reg_or_low_io_operand)
(const7_operand, reg_or_low_io_operand)
(const15_operand, const_0_to_15_operand)
(const23_operand, const_0_to_23_operand)
(const31_operand, const_0_to_31_operand): New.
* config/avr/avr-protos.h (avr_out_extr, avr_out_extr_not): New.
* config/avr/avr.cc (avr_out_extr, avr_out_extr_not): New funcs.
(lshrqi3_out, lshrhi3_out, lshrpsi3_out, lshrsi3_out): Adjust
MSB case to new insn constraint "r" for operands[1].
(avr_adjust_insn_length) [ADJUST_LEN_EXTR_NOT, ADJUST_LEN_EXTR]:
Handle these cases.
(avr_rtx_costs_1): Adjust cost for a new pattern.
gcc/testsuite/
* gcc.target/avr/pr109907.c: New test.
* gcc.target/avr/torture/pr109907-1.c: New test.
* gcc.target/avr/torture/pr109907-2.c: New test.
pr109907-v2.diff
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index ec96fd45865..229854a19db 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index a90cade35c7..f69d79bf14e 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -7142,9 +7142,9 @@ lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
case 7:
*len = 3;
- return ("rol %0" CR_TAB
- "clr %0" CR_TAB
- "rol %0");
+ return ("bst %1,7" CR_TAB
+ "clr %0" CR_TAB
+ "bld %0,0");
}
[ ... ]
Reminds me a lot of the H8 port. The basic H8/300 variants can only
shift a single bit at a time and the H8/S can only shift 2 at a time.
So we synthesize all kinds of sequences to try and optimize shifts and
bitfield extractions.
Anyway, much like the other patch, I did a cursory review, but you're
really in a better position to judge correctness and profitability for
the AVR bits. So OK for the trunk.
jeff