-O3 turns on almost all optimizations, save some that cause a size/speed tradeoff or can break standards, like the following:

-funroll-loops

This does much like it says... it "unrolls" fixed-length loops to eliminate some counters and JMP instructions. It results in a small speed boost at the cost of larger binaries. There's also -funroll-all-loops, but don't use it because it tries to unroll variable-length loops and this will actually slow things down.

-ffast-math

Disables some safeguards like checking for negative numbers being sqrt()'ed in order to increase execution speed. This can break programs that aren't too careful about such things and rely on the compiler to include such checks.

-fstrict-aliasing

This makes assumptions about which data types can be aliased to which to speed up code, but some things can break. The programmer is expected to know what they're doing.
eg:
An integer/double union variable can be accessed as either type despite which one it's currently holding, and will still give you a valid number. You can even do this through a pointer.
However with strict-aliasing on, you lose the ability to do this with pointers because an int* can't be aliased to a double* or vise-versa. Any programs making use of such a construct will probably segfault or worse when they attempt to do this while -fstrict-aliasing optimized.