This trivial function: unsigned short f(unsigned char a, unsigned char b) { return a | (b << 8); } generates the code: f: /* prologue: function */ /* frame size = 0 */ mov r21,r22 ldi r20,lo8(0) mov r18,r24 ldi r19,lo8(0) or r18,r20 or r19,r21 mov r24,r18 mov r25,r19 /* epilogue start */ ret In other words, GCC is first zero-extending the two 8-bit quantities to 16 bits, then performing a 16-bit logical OR operation on the result. For each half of the OR operation, though, one side is a constant zero and hence these operations are redundant. In this particular trivial case, the function could be implemented as: mov r25, r21 ret with all the other operations omitted.
because this is what C says you are doing: return (unsigned short) ((int) a | ((int) b << 8)); which is harder to transform back into what you expect.
Author: gjl Date: Mon May 16 14:20:19 2011 New Revision: 173792 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=173792 Log: PR target/27663 PR target/41076 * config/avr/predicates.md (const_8_16_24_operand): New predicate. * config/avr/avr.md ("*ior<mode>qi.byte0", "*ior<mode>qi.byte1-3"): New define_insn_and_split patterns. Modified: trunk/gcc/ChangeLog trunk/gcc/config/avr/avr.md trunk/gcc/config/avr/predicates.md
Created attachment 25242 [details] Some test cases
GCC 4.7.0 is being released, adjusting target milestone.
Fixed I suppose.
(In reply to comment #5) > Fixed I suppose. Unfortunately, not extern unsigned char read8 (void); unsigned short read16 (void) { unsigned char lo, hi; hi = read8(); lo = read8(); return lo | hi << 8; } with 4.8.0 -S -Os the compiler needs 5 instructions (29, 37, 30, 38) for an operation that is basically a no-op: read16: push r28 ; 31 pushqi1/1 [length = 1] /* prologue: function */ /* frame size = 0 */ /* stack size = 1 */ .L__stack_usage = 1 call read8 ; 5 call_value_insn/2 [length = 2] mov r28,r24 ; 6 movqi_insn/1 [length = 1] call read8 ; 7 call_value_insn/2 [length = 2] mov r18,r28 ; 28 movqi_insn/1 [length = 1] ldi r19,0 ; 29 movqi_insn/1 [length = 1] mov r19,r18 ; 37 *ashlhi3_const/3 [length = 2] clr r18 or r18,r24 ; 30 iorqi3/1 [length = 1] movw r24,r18 ; 38 *movhi/1 [length = 1] /* epilogue start */ pop r28 ; 34 popqi [length = 1] ret ; 35 return_from_epilogue [length = 1]
*** Bug 60145 has been marked as a duplicate of this bug. ***
Author: gjl Date: Mon Nov 28 08:40:11 2016 New Revision: 242907 URL: https://gcc.gnu.org/viewcvs?rev=242907&root=gcc&view=rev Log: PR 41076 * config/avr/avr.md (SPLIT34): New mode iterator. (bitop): New code iterator. (*iorhi3.ashift8-*). New insn-and-split patterns. (*movhi): Post-reload split reg = 0. [!MOVW]: Post-reload split reg = reg. (*mov<mode>) [SI,SF,PSI,SQ,USQ,SA,USA]: Post-reload split reg = reg. (andhi3, andpsi3, andsi3): Post-reload split reg-reg operations. (iorhi3, iorpsi3, iorsi3): Same. (xorhi3, xorpsi3, xorsi3): Same. * config/avr/avr.c (avr_rtx_costs_1) [IOR && HImode]: Adjust rtx costs to *iorhi3.ashift8-* patterns. Modified: trunk/gcc/ChangeLog trunk/gcc/config/avr/avr.c trunk/gcc/config/avr/avr.md
Fixed in v7 (hope so).
Author: gjl Date: Mon Oct 2 11:31:03 2017 New Revision: 253343 URL: https://gcc.gnu.org/viewcvs?rev=253343&root=gcc&view=rev Log: PR target/41076 * confg/avr/avr.md (*iorhi3.ashift8-ext.zerox): Add "r,r,0" alternative. Modified: trunk/gcc/ChangeLog trunk/gcc/config/avr/avr.md