Joe Buck wrote:
> > > inline size_t __compute_size(size_t num, size_t size) { > > > size_t product = num * size; > > > return product >= num ? product : ~size_t(0); > > > }
2007/4/9, Ross Smith <[EMAIL PROTECTED]> wrote:
On Monday, 9 April 2007 10:23, Florian Weimer wrote: > * Ross Ridge: > > Florian Weimer writes: > >>I don't think this check is correct. Consider num = 0x33333334 and > >>size = 6. It seems that the check is difficult to perform > >> efficiently unless the architecture provides unsigned > >> multiplication with overflow detection, or an instruction to > >> implement __builtin_clz. > > > > This should work instead: > > > > inline size_t __compute_size(size_t num, size_t size) { > > if (num > ~size_t(0) / size) > > return ~size_t(0); > > return num * size; > > } > > Yeah, but that division is fairly expensive if it can't be performed > at compile time. OTOH, if __compute_size is inlined in all places, > code size does increase somewhat. You could avoid the division in nearly all cases by checking for reasonably-sized arguments first: inline size_t __compute_size(size_t num, size_t size) { static const int max_bits = sizeof(size_t) * CHAR_BITS; int low_num, low_size; low_num = num < ((size_t)1 << (max_bits * 5 / 8)); low_size = size < ((size_t)1 << (max_bits * 3 / 8)); if (__builtin_expect(low_num && low_size, 1) || num <= ~(size_t)0 / size) return num * size; else return ~size_t(0); }
This code is bigger than Joe Buck's. ----------------------------------------- Joe Buck's code: 10 instructions Ross Ridge's code: 16 instructions Ross Smith's code: 16 instructions ----------------------------------------- Joe Buck's code: 10 instructions __compute_size: pushl %ebp movl %esp, %ebp movl 8(%ebp), %eax movl %eax, %edx imull 12(%ebp), %edx cmpl %eax, %edx orl $-1, %edx popl %ebp movl %edx, %eax ret Ross Ridge's code: 16 instructions __compute_size: pushl %ebp orl $-1, %eax movl %esp, %ebp xorl %edx, %edx movl 12(%ebp), %ecx pushl %ebx movl 8(%ebp), %ebx divl %ecx orl $-1, %edx cmpl %eax, %ebx movl %ebx, %edx imull %ecx, %edx popl %ebx movl %edx, %eax popl %ebp ret Ross Smith's code: 16 instructions __compute_size: pushl %ebp orl $-1, %eax movl %esp, %ebp xorl %edx, %edx movl 12(%ebp), %ecx pushl %ebx movl 8(%ebp), %ebx divl %ecx orl $-1, %edx cmpl %eax, %ebx movl %ebx, %edx imull %ecx, %edx popl %ebx movl %edx, %eax popl %ebp ret
compute_size_april2007.tar.gz
Description: GNU Zip compressed data