Interestingly enough, if I do this instead: typedef struct sTest { int a:12; int b:20; int c:7; int d:15; }STest;
int64_t bar2 (STest *a) { int64_t res = a->b; return res; } I get at the expand pass : (insn 6 5 7 3 struct3.c:27 (set (reg:SI 75) (mem/s:SI (reg/v/f:DI 73 [ a ]) [0 S4 A32])) -1 (nil)) -> Actually get the data (insn 7 6 8 3 struct3.c:27 (set (reg:DI 77) (zero_extract:DI (subreg:DI (reg:SI 75) 0) (const_int 20 [0x14]) (const_int 12 [0xc]))) -1 (nil)) -> Extract the bits we want but this is zero_extracted (insn 8 7 9 3 struct3.c:27 (set (reg:DI 78) (ashift:DI (reg:DI 77) (const_int 43 [0x2b]))) -1 (nil)) (insn 9 8 10 3 struct3.c:27 (set (subreg:DI (reg:SI 76) 0) (ashiftrt:DI (reg:DI 78) (const_int 43 [0x2b]))) -1 (nil)) -> These two instructions actually sign extend it (insn 10 9 11 3 struct3.c:27 (set (reg:DI 79) (ashift:DI (reg:SI 76) (const_int 32 [0x20]))) -1 (nil)) (insn 11 10 12 3 struct3.c:27 (set (reg:DI 74) (ashiftrt:DI (reg:DI 79) (const_int 32 [0x20]))) -1 (expr_list:REG_EQUAL (sign_extend:DI (reg:SI 76)) (nil))) -> Because it's seen as a SI, these last two sign extend it again... And I get later on in the passes (the instructions are removed by the combine pass): (insn 6 3 7 2 struct3.c:27 (set (reg:SI 75) (mem/s:SI (reg:DI 8 r8 [ a ]) [0 S4 A32])) 74 {movsi_internal2} (expr_list:REG_DEAD (reg:DI 8 r8 [ a ]) (nil))) (note 7 6 8 2 NOTE_INSN_DELETED) (note 8 7 9 2 NOTE_INSN_DELETED) (note 9 8 10 2 NOTE_INSN_DELETED) (note 10 9 11 2 NOTE_INSN_DELETED) (note 11 10 16 2 NOTE_INSN_DELETED) (insn 16 11 22 2 struct3.c:30 (set (reg/i:DI 6 r6) (zero_extract:DI (subreg:DI (reg:SI 75) 0) (const_int 20 [0x14]) (const_int 12 [0xc]))) 63 {extzvdi} (expr_list:REG_DEAD (reg:SI 75) (nil))) So now I have two issues that I can't seem to figure out : - Why can combine remove these 4 instructions ? - Why do I have such a difference between a local variable that is not a pointer, a pointer and a global variable ? I remember having a different behavior if the variable was a global variable or if it was a parameter. It seems that this is the case also for here. However, this is worse, since it transforms my signed extract into a simple zero_extract. Thanks for your help, Jc PS: here is the combine pass debug information: ;; Function bar2 (bar2) starting the processing of deferred insns ending the processing of deferred insns df_analyze called insn_cost 2: 4 insn_cost 6: 4 insn_cost 7: 36 insn_cost 8: 4 insn_cost 9: 4 insn_cost 10: 4 insn_cost 11: 4 insn_cost 16: 4 insn_cost 22: 0 deferring deletion of insn with uid = 2. modifying insn i3 6 r75:SI=[r8:DI] REG_DEAD: r8:DI deferring rescan insn with uid = 6. deferring deletion of insn with uid = 8. modifying insn i3 9 r76:SI#0=r77:DI REG_DEAD: r77:DI deferring rescan insn with uid = 9. deferring deletion of insn with uid = 7. modifying insn i3 9 r76:SI#0=zero_extract(r75:SI#0,0x14,0xc) REG_DEAD: r75:SI deferring rescan insn with uid = 9. deferring deletion of insn with uid = 10. modifying insn i3 11 r74:DI=r76:SI#0&0xfffff REG_DEAD: r76:SI deferring rescan insn with uid = 11. deferring deletion of insn with uid = 9. modifying insn i3 11 r74:DI=zero_extract(r75:SI#0,0x14,0xc) REG_DEAD: r75:SI deferring rescan insn with uid = 11. deferring deletion of insn with uid = 11. modifying insn i3 16 r6:DI=zero_extract(r75:SI#0,0x14,0xc) REG_DEAD: r75:SI deferring rescan insn with uid = 16. (note 1 0 4 NOTE_INSN_DELETED) (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK) (note 2 4 3 2 NOTE_INSN_DELETED) (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG) (insn 6 3 7 2 struct3.c:27 (set (reg:SI 75) (mem/s:SI (reg:DI 8 r8 [ a ]) [0 S4 A32])) 74 {movsi_internal2} (expr_list:REG_DEAD (reg:DI 8 r8 [ a ]) (nil))) (note 7 6 8 2 NOTE_INSN_DELETED) (note 8 7 9 2 NOTE_INSN_DELETED) (note 9 8 10 2 NOTE_INSN_DELETED) (note 10 9 11 2 NOTE_INSN_DELETED) (note 11 10 16 2 NOTE_INSN_DELETED) (insn 16 11 22 2 struct3.c:30 (set (reg/i:DI 6 r6) (zero_extract:DI (subreg:DI (reg:SI 75) 0) (const_int 20 [0x14]) (const_int 12 [0xc]))) 63 {extzvdi} (expr_list:REG_DEAD (reg:SI 75) (nil))) (insn 22 16 0 2 struct3.c:30 (use (reg/i:DI 6 r6)) -1 (nil)) starting the processing of deferred insns deleting insn with uid = 2. deleting insn with uid = 7. deleting insn with uid = 8. deleting insn with uid = 9. deleting insn with uid = 10. deleting insn with uid = 11. rescanning insn with uid = 6. deleting insn with uid = 6. rescanning insn with uid = 16. deleting insn with uid = 16. ending the processing of deferred insns ;; Combiner totals: 16 attempts, 16 substitutions (2 requiring new space), ;; 6 successes. On Fri, Dec 11, 2009 at 11:57 AM, Jean Christophe Beyler <jean.christophe.bey...@gmail.com> wrote: > As I continue my work on the machine description file, I currently > worked on the bitfields again to try to get a good code generation > working. Right now, I've followed what was done in the ia64 for signed > extractions : > > (define_insn "extv" > [(set (match_operand:DI 0 "gr_register_operand" "=r") > (sign_extract:DI (match_operand:DI 1 "gr_register_operand" "r") > (match_operand:DI 2 "extr_len_operand" "n") > (match_operand:DI 3 "shift_count_operand" "M")))] > "" > "extr %0 = %1, %3, %2" > [(set_attr "itanium_class" "ishf")]) > > > now this works for me except that I get for this code: > > typedef struct sTest { > int64_t a:1; > int64_t b:5; > int64_t c:7; > int64_t d:15; > }STest; > > int64_t bar2 (STest a) > { > int64_t res = a.d; > return res; > } > > Here is what I get at the final cleanup: > > ;; Function bar2 (bar2) > > bar2 (a) > { > short unsigned int SR.44; > short unsigned int SR.43; > short unsigned int SR.41; > short unsigned int SR.40; > short unsigned int SR.22; > short unsigned int SR.3; > > <bb 2>: > SR.22 = (short unsigned int) (<unnamed-signed:15>) ((short unsigned > int) a.d & 32767); > SR.43 = SR.22 & 32767; > SR.44 = SR.43 ^ 16384; > SR.3 = (short unsigned int) (<unnamed-signed:15>) ((short unsigned > int) (<unnamed-signed:15>) (SR.44 + 49152) & 32767); > SR.40 = SR.3 & 32767; > SR.41 = SR.40 ^ 16384; > return (int64_t) (<unnamed-signed:15>) (SR.41 + 49152); > > } > > I don't understand why I get all these instructions. I know that > because it's signed, it is more complicated but I would prefer to get > an unsigned extract and the a shift left/shift right. Thus 3 > instructions. > > Right now, I get so many more instructions that represent what I > showed from the final cleanup. > > Any reason for all these instructions or ideas on how to get to my 3 > instructions ? > > Thank you for your help and time, > Jean Christophe Beyler >