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]

Re: [RFT] PR19154: New AVR bit extraction pattern


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")])





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