Increase memory of an ATmega32
Global variables/types


Changing the type of global variables (e.g. use uint8_t or a similar 1 byte instead of long), or use bits to store boolean arrays.
Remove static variables and replace them by dynamic (local) variables if possible. Passing them as arguments might be used to keep the scope longer.


Data/precalculated tables


In case you now keep (fixed) data structures in your code (e.g. for pre calculated tables), than put these in external Flash. Executable code is hard to put in external Flash, but tables/data is not. Of course this comes with a performance loss. Another way is to calculate it on the fly (no calculated table needed at all).
Instead of using pre calculated data tables at all, calculate them; this might cause a performance loss.
In case you are using a lot of stored texts or data, 'compress' them if possible. The decompression code will cost some Flash, but if you have a lot of text, it might be worthwhile.


Executable code


Using for loops instead of calling functions one by one.
Check for repeated code and create functions of them, use parameters to differ between small changes; this will cause a (small) performance loss. 
Prevent 'inline' or long #define statements/code, these are substituted 
(copied) wherever used.


Logging/tracing

logging strings can consume many bytes (e.g. for one log string like: "The current temperature is: " cost 29 bytes). Having many log strings can add up a lot. To prevent this you can:


Use shorter strings ("CurTemp: " is only 9 bytes).
Print an integer (cost 1 or 2 bytes, depending on the int size).
Send this integer to another microcontroller which converts it to human readable text. It cost a bit of overhead/peripheral overhead.
When debugging, put all logging in #ifdefs, and save Flash by reducing functionality you don't need for testing. When not debugging, all logging statements will not cost any bytes.


Libraries


Finding alternative libraries which are implemented differently but with the functionality you need.


Compiler options


Check compiler options to see if the code can be compiled in a different way; mostly it will be a trade off against performance.


What you should NOT do


Make your code a few bytes smaller by using obscure code implementation. This will bite you later when you maintain your application.
Removing unused functions does not help (the compiler is smart enough to do this for you).