This is the mail archive of the gcc@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: Bitfields problem


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.beyler@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
>


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