For completeness, you aught to include the LDDR and INDR versions (as well as the OTIR and OTDR output incrementing and output decrementing instructions).
The memory block moves had an obviuos need for the complementary DR and IR versions to prevent self corruption in cases where the source and target regions of memory overlapped.
A less obvious use for these instructions (LDIR and LDDR) was to code a very fast method of setting a block of ram to a preset byte value (eg zero a 1KB block by loading a zero into the start location of the source block (HL) and setting the DE register to HL + 1 and the BC to
03FFh before executing the LDIR instruction).This takes just a smidgen over 10.5ms to clear a 1Kb block @2MHz clock speed. You could also (mis)use the LDDR to achieve the same result in the reverse direction (your choice! you just simply set the DE starting value to one less than the HL value in this case).
I never found any use for the INIR/INDR and OTIR/OTDR instructions when I was programming I/O operations on the Transam Tuscan S100 bus system I was coding on thirty odd years ago. The UARTs used for the tape and the rs232 ports were single byte buffered IM6402IPL chips which, afaiaa, predated even the 8250.
In any case, I had to process each and every byte to calculate the checksum value on each 2KB block of data going to or coming from the tape so I only ever used the IN A,(N) and OUT A,(N) instructions.
I only had a vague notion of the existence of the INIR/INDR and OTIR/OTDR instructions and had to consult my Zaks book to check before jumping in with my tuppence worth. :-)