Unfold short-circuiting operators in loop conditions correctly

Sometimes short-circuiting operators need to be unfolded to if
statements. If the unfolded operator is inside a loop condition or
expression, it needs to be evaluated repeatedly inside the loop. Add
logic to UnfoldShortCircuitToIf that can move or copy the unfolded part
of loop conditions or expressions to inside the loop.

The exact changes that need to be done depend on the type of the loop.
For loops may require also moving the initializer to outside the loop.

The unfolded expression inside a loop condition or expression is moved
or copied to inside the loop on the first traversal of the loop node,
and unfolding to if is deferred until a second traversal. This keeps the
code relatively simple.

BUG=angleproject:1167
TEST=WebGL 2 conformance tests,
     dEQP-GLES2.functional.shaders.*select_iteration_count*

Change-Id: Ieffc0ea858186054378d387dca9aa64a5fa95137
Reviewed-on: https://chromium-review.googlesource.com/310230
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Tested-by: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 11caf23..0f7cc74 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -261,7 +261,7 @@
     REPLACE_IF_IS(mInit, TIntermNode, original, replacement);
     REPLACE_IF_IS(mCond, TIntermTyped, original, replacement);
     REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement);
-    REPLACE_IF_IS(mBody, TIntermNode, original, replacement);
+    REPLACE_IF_IS(mBody, TIntermAggregate, original, replacement);
     return false;
 }