Three methods of controlling bloat have been suggested. Firstly, and most widely used (e.g. in these experiments), is to place a universal upper bound either on tree depth  or program length. ([23,24] discuss unexpected problems with this approach).
The second (also commonly used) is to incorporate program size directly into the fitness measure (often called parsimony pressure) [16,25,26].  gives an analysis of the effect of parsimony pressure which varies linearly with program length. Multi-objective fitness measures where one objective is compact or fast programs have also been used .
The third method is to tailor the genetic operations. [28, page 469,] uses several mutation operators but adjusts their frequencies so a ``decrease in complexity is slightly more probable than an increase''.  suggests targeting genetic operations at redundant code. This is seldom used, perhaps due to the complexity of identifying redundant code.  showed bloat continuing despite their targeted genetic operations. Possibly this was because of the difficulty of reliably detecting introns. There was a route whereby the GP could evolve junk code which masqueraded as being useful and thereby protected itself from removal. While  propose a method where the likelihood of potentially disruptive genetic operations increases with parent size.