After going through the logic again:

iter #  i       byte    structure

1               1       0               00000001
2               2       0               00000010
3               3       0               00000100
4               4       0               00001000
5               5       0               00010000
6               6       0               00100000
7               7       0               01000000
8               8       0               10000000
9               1       1               00000001 00000000
10              2       1               00000010 00000000
11              3       1               00000100 00000000
12              4       1               00001000 00000000
13              5       1               00010000 00000000
14              6       1               00100000 00000000
15              7       1               01000000 00000000
16              8       1               10000000 00000000
17              1       2               00000001 00000000 00000000

Byte should be initialized to 1.

template <class T>
unsigned compute_byte_size()
{
    T max = T (one);
    T current = T(one);
    unsigned byte = 1;
    for (int i = 1; T (current * 2) > max; current *=2, max *= 2, i++) {
        if (i > 8) { byte++; i=1; }
    }
    return byte;
}

> -----Original Message-----
> From: Martin Sebor [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, March 05, 2008 5:19 PM
> To: [email protected]
> Subject: Re: [PATCH] STDCXX-423
> 
> Scott Zhong wrote:
> >
> >> -----Original Message-----
> >> From: Martin Sebor [mailto:[EMAIL PROTECTED]
> >> Sent: Wednesday, February 20, 2008 12:26 PM
> >> To: [email protected]
> >> Subject: Re: [PATCH] STDCXX-423
> >>
> >> Scott Zhong wrote:
> >> [...]
> >>>>> As I write this, I realize that the my function,
> >>> compute_byte_size(),
> >>>>> can be optimized to shift one bit to the next byte boundary.
> >>>> I don't think we need to (or should) worry about optimizing
config
> >>>> tests. What we might want to do is use the template parameter in
> >>>> the signature of the function for non-conforming compilers that
> >>>> have trouble with these types of things.
> >>> Sorry I meant to say that its more of a code fix than
optimization.
> >>> Sizeof() returns the number of bytes so the function should check
> > each
> >>> byte instead of each bit.
> >> But not all bits of every byte need to contribute to the value
> >> representation of the object. IIUC, there can be 4 byte ints
> >> (i.e., sizeof(int) == 4) with 29 bits for the value, 1 bit for
> >> the sign, and 2 bits of padding.
> >>
> >
> > I had overlooked that fact, thank you for reminding me.
> >
> >>>>> template <class T>
> >>>>> unsigned compute_byte_size()
> >>>>> {
> >>>>>     T max = T (one);
> >>>>>     unsigned byte = 0;
> >>>>>     for (; T (max * 128) > max; max *= 128) {
> >>>> FWIW, for signed T the expression T(max * 128) > max has
undefined
> >>>> behavior in the presence of overflow. We've seen at least two (if
> >>>> not three) compilers exploit this presumably in some aggressive
> >>>> optimizations (see, for example, STDCXX-482). Since most (all?)
> >>>> hardware simply wraps around in the presence of overflow we just
> >>>> need to prevent the compiler optimization here.
> >>> Would the volatile keyword in front of "max" be sufficient here?
> >> It might help, but I'm not sure it's guaranteed to. All it usually
> >> does is make the compiler generate code that reloads the value of
> >> the object from memory into a register on each access. The stage
> >> I'm concerned with takes place before code generation based on what
> >> the compiler can prove about the program. For all signed x, the
> >> compiler is free to assume that in (x * N) > x, the subexpression
> >> (x * N) doesn't overflow and thus (x * N) is always guaranteed to
> >> be greater than x (for N > 0). To prevent it from making such an
> >> assumption we need to rewrite the expression like so: (x * N) > y
> >> while initializing x and y to the same value in such a way that
> >> the compiler cannot prove that (x == y) holds.
> >>
> >
> > Would this suffice?
> 
> This doesn't seem correct, not just because of the typo but because
> it returns 3 for T = int (assuming one == 1). Even if it was correct
> I'm not sure a smart optimizer couldn't make some assumptions about
> the dependency between current and max (they are both modified using
> exactly the same expression) that would cause the code to misbehave.
> 
> Martin
> 
> >
> > template <class T>
> > unsigned compute_byte_size()
> > {
> >     T max = T (one);
> >     T current = T (one);
> >     unsigned byte = 0;
> >     for (int I = 1; T (current * 2) > max; current *= 2, max *= 2,
i++)
> > {
> >         if (i > 8 ) {byte++; i = 1; }
> >     }
> >     return byte;
> > }
> >
> >
> >> Martin
> >

Reply via email to