One of my favourite examples is volatile. Volatile is more crazy in C++ but it's pretty crazy even in C. In both cases the standard basically shrugs, "Hope you know what you're doing because we sure don't" and offers no real insight into what this feature promises to do for you. But there is no other mechanism provided for MMIO.
Think of Rust's std::ptr::read_volatile (and write_volatile). These intrinsics do the thing you actually wanted (reading, or writing, a fixed size blob of "memory" that presumably wasn't really just RAM) and thus are important for writing device drivers and so on with MMIO.
[ You may be thinking, "But I need the correct size of blob read or written or my driver won't work", Rust has generics, so these functions are generic over the integer type you're reading/ writing, if you read a u64 that's a 64-bit read, if you write four u8s that 4 x 8-bit writes and so on ]
But C's volatile is a type qualifier instead. Why? Would it mean anything to, for example, integer divide an MMIO fetch by fifteen and write it back? a/= 15; No. So then why make it a type qualifier? When volatile was added to C they'd only just invented simple optimisations like re-ordering so they had no idea this was a bad idea, and it seemed simpler than adding an intrinsic (though not by much) but today we know better.