Newer (relatively speaking) x86-64 instruction sets support many three-operand instructions, which are actually easier to use for compilers than instructions with overwritten source operands or hard register constraints. Pattern matching for instructions that do not have a direct C representation (such as NAND) is also pretty standard in compilers. Auto-vectorization is more tricky (especially when you want code to actually run faster …), but some of the new ISAs are impactful without it. And of course there are expanders for fixed-size memcpy and memset that can use wider vector instructions quite easily. Those operations are quite common.