Unfortunatelly, this approach confuses gcc a lot. Attached testcase
will illustrate the problem on i686 (substitute SI with DI and DI with
TI on 64bit and change shift values for the same result):
Compared two approaches head-to-head on i686 target; gcc -O2
-fomit-frame-pointer generates:
test_c:
subl $28, %esp #,
xorl %edx, %edx #
movl 40(%esp), %eax # c, tmp66
movl 44(%esp), %ecx # d, d
movl %esi, 20(%esp) #,
movl %ebx, 16(%esp) #,
movl %eax, %edx # tmp66,
movl $0, %eax #, tmp66
movl %eax, %esi #, tmp74
movl 32(%esp), %eax # a, tmp70
movl %edx, %ebx # tmp75, __c
orl %ecx, %esi # d, tmp74
xorl %edx, %edx #
movl %esi, %ecx # tmp74, __c
movl 36(%esp), %esi # b, b
movl %edi, 24(%esp) #,
movl 24(%esp), %edi #,
movl %eax, %edx # tmp70,
movl $0, %eax #, tmp70
orl %esi, %eax # b, tmp72
movl 20(%esp), %esi #,
addl %eax, %ecx # tmp72, __c
adcl %edx, %ebx #, __c
movl %ecx, 8(%esp) # __c, y
movl %ebx, %ecx # __c, __c
xorl %ebx, %ebx # __c
movl 16(%esp), %ebx #,
movl %ecx, 12(%esp) # __c, x
addl $28, %esp #,
ret
Looking into this mess, I think that gcc has still a long way to go
w.r.t to DImode values on 32bit targets (and TImode values on 64bit
targets) and the only solution for the near future is using asm
here...