In the section 6.4 Constant Buffers of the book Practical Rendering & Computation with Direct3D 11 (pages 325, 326) it is mentioned:
By default, the HLSL compiler will attempt to align constants such that they don't span multiple float4 registers. [...] The packing for an HLSL constant buffer can also be manually specified through the packoffset keyword.
I assume a similar rule will apply to the OpenGL equivalent, Uniform Buffer Objects, since they map to the same hardware feature.
What about vanilla uniforms though? What are the rules that apply when declaring uniforms?
uniform vec2 xy; // Can we expect the compiler to pack xy
uniform vec2 zw; // into a same four component register?
uniform vec2 rg;
uniform float foo; // Will this prevent from packing rg and ba?
uniform vec2 ba; // If so, will foo eat up a full four components register?
If the compiler can do such optimizations, how good are they? Can we explicitly tell the compiler to pack or not, and when should we?