This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFT] PR19154: New AVR bit extraction patterns
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 13 Mar 2005 14:19:19 -0700 (MST)
- Subject: [RFT] PR19154: New AVR bit extraction patterns
The following patch is my attempt to resolve PR middle-end/19154. The
proposed solution is to introduce new patterns to the AVR backend that
can be used to efficiently extract a bit from a register. GCC's default
approach for bitfield manipulation is to perform a right shift followed
by a bitwise AND to extract the bitfield. Unfortunately, this performs
poorly on AVR that only supports single bit shifts in hardware, requiring
loop unrolling or a loop for such bitfield extractions.
What the AVR does have is a useful "skip following instruction if bit
in register is set/cleared" instruction. This provides a clever idiom
for extracting a single bitfield in only three AVR instructions by
performing the equivalent of a conditional move based on the source bit.
For the reduced testcase in PR19154, we get the following improvement:
char g(char c)
{
return (c & 8) != 0;
}
Before: asr r24
asr r24
asr r24
clr r25
sbrc r24,7
com r25
andi r24,lo8(1)
andi r25,hi8(1)
ret
After: and r24,8
sbrc r24,3
mov r24,1
clr r25
ret
Could one of the AVR folks that have a working test framework see
whether the following patching patch doesn't break anything? I've
confirmed that the patch compiles to build a cross cc1 from
i686-pc-linux-gnu to avr-elf, but I'm unable to test any further.
Thanks in advance,
2005-03-13 Roger Sayle <roger@eyesopen.com>
PR middle-end/19154
* config/avr.md (*extbitqi2, *extbithiqi): New patterns to extract
a single bit from a QImode register.
Index: avr.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/avr.md,v
retrieving revision 1.51
diff -c -3 -p -r1.51 avr.md
*** avr.md 13 Mar 2005 10:09:53 -0000 1.51
--- avr.md 13 Mar 2005 19:48:18 -0000
***************
*** 2514,2516 ****
--- 2514,2556 ----
(pc)))]
"jump_over_one_insn_p (insn, operands[2])"
"cpse %0,%1")
+
+ ;; Single Bit Extraction
+ (define_insn "*extbitqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (zero_extract:QI (match_operand:QI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand 2 "const_int_operand" "n")))]
+ "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 7"
+ "*{
+ if (REGNO (operands[0]) != REGNO (operands[1]))
+ return (AS1 (clr,%A0) CR_TAB
+ AS2 (sbrc,%A1,%2) CR_TAB
+ AS2 (mov,%A0,1));
+ operands[3] = GEN_INT (1 << INTVAL (operands[2]));
+ return (AS2 (and,%A0,%3) CR_TAB
+ AS2 (sbrc,%A0,%2) CR_TAB
+ AS2 (mov,%A0,1));
+ }"
+ [(set_attr "length" "3")])
+
+ (define_insn "*extbithiqi"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extract:HI (match_operand:QI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand 2 "const_int_operand" "n")))]
+ "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 7"
+ "*{
+ if (REGNO (operands[0]) != REGNO (operands[1]))
+ return (AS1 (clr,%A0) CR_TAB
+ AS2 (sbrc,%A1,%2) CR_TAB
+ AS2 (mov,%A0,1) CR_TAB
+ AS1 (clr,%B0));
+ operands[3] = GEN_INT (1 << INTVAL (operands[2]));
+ return (AS2 (and,%A0,%3) CR_TAB
+ AS2 (sbrc,%A0,%2) CR_TAB
+ AS2 (mov,%A0,1) CR_TAB
+ AS1 (clr,%B0));
+ }"
+ [(set_attr "length" "4")])
+
Roger
--