> On Feb 26, 2019, at 7:58 AM, Mouse <[email protected]> wrote:
> 
>>>>    int err = 0;
>>>>    long hisflags = ufetch_64(flag1p, &err) | ufetch_64(flag2p, &err);
> 
>>>>    if (err) return EFAULT;
> 
>>>>    do_something(hisflags);
> 
>>> I like this, because it swaps the cost of the value that is always
>>> needed (which was expensive) versus the one that isn't expected
>>> often (the error case, was cheap).
> 
>> Huh?  The code always has to access err to work correctly.  You don't
>> save anything.
> 
> Let's look at the no-error (presumably common) case:

So, let’s look at the EVEN MORE COMMON case of only a single ufetch call at any 
particular call site:

        if ((error = ufetch_64(flag1p, &val1))) return error;
        do_something(val1);

ufetch_64 does a memory load from flag1p
ufetch_64 does a memory store to &val1
Memory load from &val1 to pass argument to do_something()

Versus:

        error = 0;
        val1 = ufetch_64(flag1p, &error);
        if (error) return error;
        do_something(val1);

Memory store to initialize error
ufetch_64 does a memory load from flag1p
Memory load from &error to check error condition

It’s 2 loads and a store in either case, and the second pattern is contrary to 
just about everything else in the kernel.

Nevermind that it’s patently absurd to be micro-optimizing this particular 
thing because it completely ignores all of the other stuff that these routines 
do behind the curtain that absolutely dwarfs what we’re talking about here.

-- thorpej

Reply via email to