-O3 is for optimizations that are mostly not risky.
-O2 is for optimizations that don't involve a speed/size tradeoff
-O1 is for optimizations that don't slow your compiler down too much
Obviously these are fuzzy categories, but -O4 is where "undefined behavior" optimizations belong. Alternately, each individual optimization has its own flag, and can be turned on individually.