[RFT] PR19154: New AVR bit extraction pattern

Andrew Hutchinson andrewhutchinson@cox.net
Fri Mar 18 04:26:00 GMT 2005


Here seems to be the best compromise. Comments PLEASE!

It uses both the zero_extract and the related shift/and combination.

It will still be sub-optimum under the following conditions:

1) Bit is in sign  bit postion (c & 0x80, i & 0x8000 etc)
 -gcc prefers >>15. Which will generate same code length :-)
 BUT will  fail to eliminate redundant sign extend on QImode source 
operand :-(

2) Operand is SImode
- gcc splits pattern with various subreg/extend arrangements and fail to 
match.

3) If CSE trys to keep intermediate left shift result.


Note that the shift/and comination is required to match the common case 
where src/dest modes are both HImode. Zero_extract:HI (HI...  just isn't 
tried under that circumstance.

 I use mode macros so we actually get 3x3 +3 total define_insn.

; Define patterns for efficient 1/0 result of bit tests
(define_mode_macro QHSMODE1 [ QI HI SI])
(define_mode_macro QHSMODE2 [ QI HI SI])
(define_mode_attr LEN345 [(SI "5") (HI "4") (QI "3")])

(define_insn "*ext1bit<QHSMODE1:mode><QHSMODE2:mode>"
  [(set (match_operand:QHSMODE2 0 "register_operand" "=r")
        (zero_extract:QHSMODE2 (match_operand:QHSMODE1 1 
"register_operand" "r")
        (const_int 1)
        (match_operand 2 "const_int_operand" "n")))]
  "INTVAL (operands[2]) >= 0
   && INTVAL (operands[2]) < (8 * GET_MODE_SIZE (<QHSMODE1:MODE>mode))"
  "*{
    rtx ops[4];
    int i;
    int size = GET_MODE_SIZE (GET_MODE (operands[0]));
    int byte = INTVAL (operands[2]) / 8;
    int bit = INTVAL (operands[2]) % 8;
    ops[0] = operands[0];
    ops[1] = gen_rtx_REG (QImode, REGNO (operands[1]) + byte);
    ops[2] = gen_int_mode (bit,QImode);
    output_asm_insn (AS2 (bst,%A1,%2), ops);
    output_asm_insn (AS2 (mov,%A0,__zero_reg__), ops);
    output_asm_insn (AS2 (bld,%A0,1), ops);
    for (i = 1;i < size;i++)
      {
        ops[0] = gen_rtx_REG (QImode, REGNO (operands[0]) + i);
        output_asm_insn (AS2 (mov, %A0, __zero_reg__), ops );
      }
      return \"\";
}"
  [(set_attr "length" "<QHSMODE2:LEN345>")
  (set_attr "cc" "none")])


; matched same where gcc does not offer zero_extract pattern
(define_insn "*lsrand1bit<QHSMODE2:mode>"
  [(set (match_operand:QHSMODE2 0 "register_operand" "=r")
    (and:QHSMODE2
            (lshiftrt:QHSMODE2 (match_operand:QHSMODE2 1 
"register_operand" "r")
                       (match_operand 2 "const_int_operand" "n"))
        (const_int 1))
       
        )]
  "INTVAL (operands[2]) >= 0
   && INTVAL (operands[2]) < (8 * GET_MODE_SIZE (<QHSMODE2:MODE>mode))
  "
  "*{
    rtx ops[4];
    int i;
    int size = GET_MODE_SIZE (GET_MODE (operands[0]));
    int byte = INTVAL (operands[2]) / 8;
    int bit = INTVAL (operands[2]) % 8;
    ops[0] = operands[0];
    ops[1] = gen_rtx_REG (QImode, REGNO (operands[1]) + byte);
    ops[2] = gen_int_mode (bit,QImode);
    output_asm_insn (AS2 (bst,%A1,%2), ops);
    output_asm_insn (AS2 (mov,%A0,__zero_reg__), ops);
    output_asm_insn (AS2 (bld,%A0,1), ops);
    for (i = 1;i < size;i++)
      {
        ops[0] = gen_rtx_REG (QImode, REGNO (operands[0]) + i);
        output_asm_insn (AS2 (mov, %A0, __zero_reg__), ops );
      }
      return \"\";
}"
  [(set_attr "length" "<QHSMODE2:LEN345>")
  (set_attr "cc" "none")])





More information about the Gcc-patches mailing list