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] |
Hi all. Evaluating avr-gcc 4.x I observed some deficiencies of its coce quality for single bit operations. A specific case is this one: #define REG (*(((unsigned char volatile *) 0x20))) unsigned char extract_sfrbit_1() { unsigned char i = 0; if (REG & 64) i = 1; return i; } avr-gcc 4.4.0 (same for 4.3.2) compiles this with -O[123s] to extract_sfrbit_1: /* prologue: function */ /* frame size = 0 */ in r24,32-0x20 ; 6 *movqi/4 [length = 1] ldi r25,lo8(0) ; 26 *movqi/2 [length = 1] ldi r18,6 ; 31 *lshrhi3_const/5 [length = 5] 1: lsr r25 ror r24 dec r18 brne 1b andi r24,lo8(1) ; 14 andqi3/2 [length = 1] /* epilogue start */ ret ; 29 return [length = 1] I added a patch that fixes some problems of that kind. Consider the patch as a proposal. I did not investigate in expanding "extzv" in order to keep changes minimal. The patch -- defines new, anonymous insns that enable insn combine (pass .combine) to optimize this -- introduces a new insn attribute "adjust_len" in {"no","yes"} -- introduces some mode iterators for int modes -- introduces %. to ease outputting of a bit in print_operand() -- introduce some constraints and an operator predicate -- most insns use BST and/or BLD to manipulate the bit -- with the exception of mode iterators, the patch works the same way even for GCC 3.x There is also a C file bitmov.c attached that can be used to show the effects of the patch. Compiled with -Os -fno-split-wide-types the size if the object file is (without/with patch): text data bss dec hex filename 814 0 16 830 33e bitmov-nopatch.o 586 0 16 602 25a bitmov-patch.o The C snippet above is translated to extract_sfrbit_1: /* prologue: function */ /* frame size = 0 */ in r24,32-0x20 ; 6 *movqi/4 [length = 1] bst r24,6 ; 14 *extract_bitQIqi [length = 3] clr r24 bld r24,0 /* epilogue start */ ret ; 27 return [length = 1] This is not optimal but better than a shift loop. regards Georg-Johann
Attachment:
bitmov-patch.s
Description: Binary data
Attachment:
bitmov-nopatch.s
Description: Binary data
#define REG (*(((unsigned char volatile *) 0x20))) typedef union { struct { unsigned b0:1; unsigned b1:1; unsigned b2:1; unsigned b3:1; unsigned b4:1; unsigned b5:1; unsigned b6:1; unsigned b7:1; }; unsigned char c; } u_t; u_t s, t; unsigned char i; unsigned short g, h; char z,y; /**************************************/ void test_andsi3 (long long a, long b) { static long l1, l2; l1 = b & ~(1l << 0); l2 = a & ~(1l << 12); } void test_iori3 (long long a, long b) { static long l1, l2; l1 = b | (1l << 0); l2 = a | (1l << 12); } unsigned char extract_sfrbit_1() { unsigned char i = 0; if (REG & 64) i = 1; return i; } void insert_1_bitashift (unsigned char b) { s.b6 = t.b6; } unsigned char shiftrt_and1 (unsigned char c) { i = (c >> 4) & 1; return c; } unsigned char shiftrt_1_bit (unsigned char c) { i = (c >> 4) & 2; return c; } unsigned char ashift_1_bit (unsigned char c) { i = (c << 5) & 64; return c; } void extract_sfrbit_2() { unsigned char j = 0; if (REG & 64) j = 1; i = j; } int extract_gprbit (int i) { return (i & (1 << 14)) ? 1 : 0; } void bar() { if (REG & 64) i = 0; s.b6 = i; if (i & 2) REG |= 64; } void movebit_ashift() { s.b6 = s.b5; s.b7 = s.b3; } void movebit_shiftrt() { s.b3 = s.b7; s.b5 = s.b6; } void movebit_07() { s.b0 = s.b7; } void movebit_71() { s.b7 = s.b1; } void movebit_70() { s.b7 = s.b0; } unsigned char revert (unsigned char n) { u_t u = {.c = n}; u_t v; v.b0 = u.b7; v.b1 = u.b6; v.b2 = u.b5; v.b3 = u.b4; v.b4 = u.b3; v.b5 = u.b2; v.b6 = u.b1; v.b7 = u.b0; return v.c; } void test_sfrbit () { if ((REG >> 6) & 1) y = 1; } void test_gprbit (unsigned char reg) { if (1 & (reg >> 6)) y = 1; } void get_longbit (long x) { i = (x >> 25) & 1; s.b3 = (x & (1ul << 14)) ? 1 : 0; s.b0 = (x & (1ul << 24)) ? 1 : 0; } unsigned char copy (unsigned char n) { u_t u = {.c = n}; u_t v = {.c = i}; v.b0 = u.b0; v.b4 = u.b4; v.b7 = u.b7; return v.c; } unsigned char is_ne0 (unsigned char n) { u_t u = {.c = n}; return u.b0 | u.b1 | u.b2 | u.b3 | u.b4 | u.b5 | u.b6 | u.b7; }
Attachment:
bit1-trunk-142584.patch
Description: Binary data
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |