It really depends on the individual compiler. The GPU vendor is responsible for the compiler as part of their driver, so it's really a total crapshoot as to how things get optimized, and you would need vendor-specific tools (if available) to get the compiled shader and disassemble it.
If the GLSL is compiled to SPIR-V (i.e. for Vulkan) then you can at least look at the SPIR-V and see what optimizations were done at that level. If the loop gets unrolled by the SPIR-V compiler, it's unlikely that it would be re-rolled by the driver compiler. However, ultimately when it's submitted to the driver it will still go through another compile stage which may transform the code further, so whatever you see in the SPIR-V isn't necessarily definitive.
In general, you're right that the compiler has to assume that uniform values are arbitrary. So if, for instance, you loop from 0 up to some 32-bit int uniform value, then it won't be able to unroll the loop as it could have in principle billions of iterations.
Sometimes, if you put a compiler-visible upper bound on the loop count then the compiler will be able to unroll it:
uniform int iterCount;
int count = min(iterCount, 4);
for (int i = 0; i < count; ++i)
Here, it's possible for the compiler to prove that the count can't be more than 4, so it would be safe to unroll the loop 4x, with conditionals to jump over parts of it based on the actual value of
iterCount. But again, whether the compiler actually does that in any given instance is going to be down to the individual compiler's analysis and heuristics. Generally if the loop body is long, or the iteration count is high, it will be less profitable to unroll it.
By the way, in your example the value of
maxIter is always either 2 or 3, and so the loop count is either 5 or 7, and the compiler should be able to see that, so it would be a reasonable expectation that it could unroll that loop if it decides it's a good idea.
Also, if you have access to GL_EXT_control_flow_attributes then you can mark up loops with the
[[unroll]] annotation to explicitly request the compiler to unroll it—although the compiler may still refuse to honor that if it doesn't have a compiler-visible upper bound.