This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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
--


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]