The benefit of IOCP and Overlapped I/O on Windows isn't the design. The benefit is that it comes complete out of the box, whereas on Linux and *BSD you either need to roll your own or supplement inconsistent kernel interfaces that people tend to avoid. But both IOCP and Overlapped I/O are higher-level APIs than traditional Unix readiness notification. The problem on Windows is that there's nothing like epoll or kqueue, which is critically important when you're trying to write library code that works with different event models. (Even on Windows Overlapped I/O isn't always ideal, especially in libraries trying to avoid callbacks or support multi-threading strategies different than those dictated by Overlapped I/O). Windows does implement something equivalent to traditional Unix readiness notification internally--it's how IOCP and Overlapped I/O are implemented--but its unpublished and exceptionally opaque. See https://github.com/piscisaureus/wepoll
And then you have a language with GC and you want a async IO, and your runtime becomes so messy with IOCP support, so you just use poll on windows, as many languages do. kqueue is fine, but messy and incomprehensible, and I don't see how is it fundamentally better than epoll with ET.
I can, I think, partially address this, though unfortunately in the negative.
My understanding of IOCP is that the model requires the following: if you want to, say, receive data on a socket, you supply the IOCP w/ a buffer/length. After some data has been received, the buffer and the amount received are returned to you.
The problem with this model is that the buffer is effectively locked up in kernel space until the I/O is complete. Compared to readiness-notifications (select() and derivatives, such as poll/epoll/kqueue), which can share the same receive buffer among all receiving sockets. (They might need to buffer things like partially received commands, but you can perhaps use a much smaller buffer there, and/or only allocate it in the event you require it.)
It has been a long time since I've done Windows programming, so please correct me if I've gotten the above wrong. But that's a fundamental difference and advantage that epoll/kqueue have over IOCP.
Now, I do think the IOCP model is very much conceptually simpler, and I would guess that it is easier to write correct IOCP code than epoll code, but at the expense of memory in some situations. But IOCP doesn't (I don't think) cover as many situations as epoll/kqueue.