Variable integer encoding
I actually take issue with functions written like this in general. It screams "I am smarter than a compiler", and flies in the face of most of what C++ is about at a philosophical level. 

It's not portable, it's not future-proof, it's severely hamstringing the compiler, so optimizations implemented in future versions of the compiler will likely not be able to be applied.

All this to say: for me, there needs to be a crazy strong rationale to motivate the existence of something written like this in a non-toy codebase. 

The biggest culprit of this in your code is the "writing more data than the size returned" part of it. The chances of this eventually stomping out-of-bounds memory is simply not worth the marginal performance difference. Considering the places in code where such encodings tend to be used, I find it highly unlikely that it has any measurable performance impact in anything that benchmarks this in context with some other code around it.

So, now that that's out of the way, here's my feedback of the function as written:

Don't use builtins where you don't have to.

I get using __builtin_clzll, but there is no valid reason to use __builtin_memcpy over std::memcpy.

Don't use magic values where unnecessary

That 64 coould easily be 8 * sizeof(value). Same goes for the 9, it could be sizeof(value) + 1. 

I know you only care about X86_64, and unsigned long long int is always 8 bytes on that platform, but if being safe does not cost you anything (which is the case here), then there is no excuse not to be.

Alternatively, if you really want 64 bits exactly, just use std::uint64_t instead.

Separation of concerns

The main issue I see with your function is that it conflates the encoding and the storage. You would be better off separating them, and letting the compiler reconciliate.

In the following, encode_and_store() compiles to effectively the same thing as your enc(). On top of that, since enc() is now a pure function, and does not involve any side effect anymore, the compiler is a lot more free to mix and merge it with the calling context, so odds are it'll end up being faster in actual use.

std::tuple&lt;unsigned long long int, int&gt; enc(unsigned long long int value) {
    int nUsedBits = 64 - __builtin_clzll(value|1);
    int nBytesNeeded = (nUsedBits+6)/7;

    if (nBytesNeeded&lt;9) {
        value = ((value&lt;&lt;1)|1)&lt;&lt;(nBytesNeeded-1);
    }
    return std::make_tuple(value, nBytesNeeded);
}

int enc_and_store(unsigned char *result, unsigned long long int value) {
   auto [data, bytes] = enc(value);
   if(bytes &gt;= 9) {
       *result++ = 0;
   }

   __builtin_memcpy(result, &amp;data, 8);
   return bytes;
}