Considering that the compiler that you are using could be already configured to optimize program memory usage ( usually to detriment of speed ), even on this case it is always possible to reduce the code size by better structuring the program, and it is achievable only depending on the inventiveness of the programmer to have creative insights, and also to not oppose to make deep changes in a working code, for example by reusing parts with similar functions. By the way, due to the PIC16 family does not have a large stack, compilers had as default to assemble functions inline, which consumes more "ROM", and it would be not unreasonable to consider that the same treaty would be extended to the 18F family, therefore the first thing, you could check out what the default in the compiler you are using.