Compilers are good. Really good. The only time you need to code in assembly is for really tight control loops. Sometimes the assumptions compilers make are wrong.
There is an issue for this specific case that the free version of the Microchip compiler generates very inefficient code.
The full version is quite useable on tiny parts though.
There can occasionally be cases where the desired functionality is a good fit for the instruction set but a poor fit for standard C syntax. e.g. bit rotates, nibble swaps, rotate and use the resulting carry bit.
However in some cases, once you're familiar with how the compiler generates code you can coerce it into doing what you want. e.g. on the PIC you can do a char rotate or add and then use the carry result by accessing the physical carry bit in the status register.
It is important to know enough assembly to be able to look at compiler output and determine if it is doing something poorly or just plain wrong.