Migrate inliner-related tests to a separate unit-test file.

All tests are now GLSL-based instead of .fp based, for ease of
readability. DEF_TESTs which called test() more than once have been
split up into a separate individual DEF_TEST for each test() call, to
simplify fixups going forward.

Change-Id: I9202e95e9cafff3efc0c32aa3f3ca2eea04719fe
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/314886
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/gn/tests.gni b/gn/tests.gni
index 5ac9e8f..749bc7c 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -262,6 +262,7 @@
   "$_tests/SkSLErrorTest.cpp",
   "$_tests/SkSLFPTest.cpp",
   "$_tests/SkSLGLSLTest.cpp",
+  "$_tests/SkSLInlinerTest.cpp",
   "$_tests/SkSLInterpreterTest.cpp",
   "$_tests/SkSLMemoryLayoutTest.cpp",
   "$_tests/SkSLMetalTest.cpp",
diff --git a/tests/SkSLFPTest.cpp b/tests/SkSLFPTest.cpp
index 9f49561..521023a 100644
--- a/tests/SkSLFPTest.cpp
+++ b/tests/SkSLFPTest.cpp
@@ -1087,878 +1087,6 @@
 )__Cpp__"});
 }
 
-DEF_TEST(SkSLFPTernaryExpressionsShouldNotInlineResults, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half count = 0;
-             bool test(half4 v) {
-                 return v.x <= 0.5;
-             }
-             half4 trueSide(half4 v) {
-                 count += 1;
-                 return half4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));
-             }
-             half4 falseSide(half4 v) {
-                 count += 1;
-                 return half4(cos(v.y), cos(v.z), cos(v.w), cos(v.z));
-             }
-             void main() {
-                 sk_OutColor = test(color) ? trueSide(color) : falseSide(color);
-                 sk_OutColor *= count;
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(SkString trueSide_name;
-        const GrShaderVar trueSide_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
-        fragBuilder->emitFunction(kHalf4_GrSLType, "trueSide", 1, trueSide_args,
-R"SkSL(count += 1.0;
-return half4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));
-)SkSL", &trueSide_name);
-        SkString falseSide_name;
-        const GrShaderVar falseSide_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
-        fragBuilder->emitFunction(kHalf4_GrSLType, "falseSide", 1, falseSide_args,
-R"SkSL(count += 1.0;
-return half4(cos(v.y), cos(v.z), cos(v.w), cos(v.z));
-)SkSL", &falseSide_name);
-        fragBuilder->codeAppendf(
-R"SkSL(half count = %f;
-bool _0_test;
-{
-    _0_test = %s.x <= 0.5;
-}
-
-%s = _0_test ? %s(%s) : %s(%s);
-
-%s *= count;
-)SkSL"
-, count, args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor, trueSide_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar), falseSide_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPShortCircuitEvaluationsCannotInlineRightHandSide, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             bool testA(half4 v) {
-                 return v.x <= 0.5;
-             }
-             bool testB(half4 v) {
-                 return v.x > 0.5;
-             }
-             void main() {
-                 sk_OutColor = half4(0);
-                 if (testA(color) && testB(color)) {
-                    sk_OutColor = half4(0.5);
-                 }
-                 if (testB(color) || testA(color)) {
-                    sk_OutColor = half4(1.0);
-                 }
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(        SkString testA_name;
-        const GrShaderVar testA_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
-        fragBuilder->emitFunction(kBool_GrSLType, "testA", 1, testA_args,
-R"SkSL(return v.x <= 0.5;
-)SkSL", &testA_name);
-        SkString testB_name;
-        const GrShaderVar testB_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
-        fragBuilder->emitFunction(kBool_GrSLType, "testB", 1, testB_args,
-R"SkSL(return v.x > 0.5;
-)SkSL", &testB_name);
-        fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-bool _0_testA;
-{
-    _0_testA = %s.x <= 0.5;
-}
-
-if (_0_testA && %s(%s)) {
-    %s = half4(0.5);
-}
-
-bool _1_testB;
-{
-    _1_testB = %s.x > 0.5;
-}
-
-if (_1_testB || %s(%s)) {
-    %s = half4(1.0);
-}
-
-)SkSL"
-, args.fOutputColor, args.fUniformHandler->getUniformCStr(colorVar), testB_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor, args.fUniformHandler->getUniformCStr(colorVar), testA_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPWhileTestCannotBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             bool shouldLoop(half4 v) {
-                 return v.x < 0.5;
-             }
-             void main() {
-                 sk_OutColor = half4(0);
-                 while (shouldLoop(sk_OutColor)) {
-                     sk_OutColor += half4(0.125);
-                 }
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(SkString shouldLoop_name;
-        const GrShaderVar shouldLoop_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
-        fragBuilder->emitFunction(kBool_GrSLType, "shouldLoop", 1, shouldLoop_args,
-R"SkSL(return v.x < 0.5;
-)SkSL", &shouldLoop_name);
-        fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-while (%s(%s)) {
-    %s += half4(0.125);
-}
-)SkSL"
-, args.fOutputColor, shouldLoop_name.c_str(), args.fOutputColor, args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedWhileBodyMustBeInAScope, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             half4 adjust(half4 v) {
-                 return v + half4(0.125);
-             }
-             void main() {
-                 sk_OutColor = half4(0);
-                 while (sk_OutColor.x < 0.5)
-                     sk_OutColor = adjust(sk_OutColor);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->emitFunction(kHalf4_GrSLType, "adjust", 1, adjust_args,
-R"SkSL(return v + half4(0.125);
-)SkSL", &adjust_name);
-        fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-while (%s.x < 0.5) {
-    half4 _0_adjust;
-    {
-        _0_adjust = %s + half4(0.125);
-    }
-
-    %s = _0_adjust;
-}
-)SkSL"
-, args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPDoWhileTestCannotBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             bool shouldLoop(half4 v) {
-                 return v.x < 0.5;
-             }
-             void main() {
-                 sk_OutColor = half4(0);
-                 do {
-                     sk_OutColor += half4(0.125);
-                 } while (shouldLoop(sk_OutColor));
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(SkString shouldLoop_name;
-        const GrShaderVar shouldLoop_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
-        fragBuilder->emitFunction(kBool_GrSLType, "shouldLoop", 1, shouldLoop_args,
-R"SkSL(return v.x < 0.5;
-)SkSL", &shouldLoop_name);
-        fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-do {
-    %s += half4(0.125);
-} while (%s(%s));
-)SkSL"
-, args.fOutputColor, args.fOutputColor, shouldLoop_name.c_str(), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedDoWhileBodyMustBeInAScope, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             half4 adjust(half4 v) {
-                 return v + half4(0.125);
-             }
-             void main() {
-                 sk_OutColor = half4(0);
-                 do
-                     sk_OutColor = adjust(sk_OutColor);
-                 while (sk_OutColor.x < 0.5);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->emitFunction(kHalf4_GrSLType, "adjust", 1, adjust_args,
-R"SkSL(return v + half4(0.125);
-)SkSL", &adjust_name);
-        fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-do {
-    half4 _0_adjust;
-    {
-        _0_adjust = %s + half4(0.125);
-    }
-
-    %s = _0_adjust;
-} while (%s.x < 0.5);
-)SkSL"
-, args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPOnlyForInitializerExpressionsCanBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             half4 initLoopVar() {
-                 return half4(0.0625);
-             }
-             bool shouldLoop(half4 v) {
-                 return v.x < 0.5;
-             }
-             half4 grow(half4 v) {
-                 return v + half4(0.125);
-             }
-             void main() {
-                 for (sk_OutColor = initLoopVar();
-                      shouldLoop(sk_OutColor);
-                      sk_OutColor = grow(sk_OutColor)) {
-                 }
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(SkString initLoopVar_name;
-        const GrShaderVar initLoopVar_args[] = { };
-        fragBuilder->emitFunction(kHalf4_GrSLType, "initLoopVar", 0, initLoopVar_args,
-R"SkSL(return half4(0.0625);
-)SkSL", &initLoopVar_name);
-        SkString shouldLoop_name;
-        const GrShaderVar shouldLoop_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
-        fragBuilder->emitFunction(kBool_GrSLType, "shouldLoop", 1, shouldLoop_args,
-R"SkSL(return v.x < 0.5;
-)SkSL", &shouldLoop_name);
-        SkString grow_name;
-        const GrShaderVar grow_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
-        fragBuilder->emitFunction(kHalf4_GrSLType, "grow", 1, grow_args,
-R"SkSL(return v + half4(0.125);
-)SkSL", &grow_name);
-        fragBuilder->codeAppendf(
-R"SkSL(for (%s = half4(0.0625);
-%s(%s); %s = %s(%s)) {
-}
-)SkSL"
-, args.fOutputColor, shouldLoop_name.c_str(), args.fOutputColor, args.fOutputColor, grow_name.c_str(), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedForBodyMustBeInAScope, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             half4 adjust(half4 v) {
-                 return v + half4(0.125);
-             }
-             void main() {
-                 sk_OutColor = half4(0);
-                 for (int x=0; x<4; ++x)
-                     sk_OutColor = adjust(sk_OutColor);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-for (int x = 0;x < 4; ++x) {
-    half4 _0_adjust;
-    {
-        _0_adjust = %s + half4(0.125);
-    }
-
-    %s = _0_adjust;
-}
-)SkSL"
-, args.fOutputColor, args.fOutputColor, args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPIfTestsCanBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             bool ifTest(half4 v) {
-                 return color.x >= 0.5;
-             }
-             void main() {
-                 if (ifTest(color))
-                     sk_OutColor = half4(1.0);
-                 else
-                     sk_OutColor = half4(0.5);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(bool _0_ifTest;
-{
-    _0_ifTest = %s.x >= 0.5;
-}
-
-if (_0_ifTest) %s = half4(1.0); else %s = half4(0.5);
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedIfBodyMustBeInAScope, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 ifBody() {
-                 return color + half4(0.125);
-             }
-             void main() {
-                 half4 c = color;
-                 if (c.x >= 0.5)
-                     c = ifBody();
-                 sk_OutColor = c;
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 c = %s;
-if (c.x >= 0.5) {
-    half4 _0_ifBody;
-    {
-        _0_ifBody = %s + half4(0.125);
-    }
-
-    c = _0_ifBody;
-}
-%s = c;
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedElseBodyMustBeInAScope, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 elseBody() {
-                 return color + half4(0.125);
-             }
-             void main() {
-                 half4 c = color;
-                 if (c.x >= 0.5)
-                     ;
-                 else
-                     c = elseBody();
-                 sk_OutColor = c;
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 c = %s;
-if (c.x >= 0.5) {
-} else {
-    half4 _0_elseBody;
-    {
-        _0_elseBody = %s + half4(0.125);
-    }
-
-    c = _0_elseBody;
-}
-%s = c;
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPSwitchWithReturnInsideCannotBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 switchy(half4 c) {
-                 switch (int(c.x)) {
-                     case 0: return c.yyyy;
-                 }
-                 return c.zzzz;
-             }
-             void main() {
-                 sk_OutColor = switchy(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->emitFunction(kHalf4_GrSLType, "switchy", 1, switchy_args,
-R"SkSL(switch (int(c.x)) {
-    case 0:
-        return c.yyyy;
-}
-return c.zzzz;
-)SkSL", &switchy_name);
-        fragBuilder->codeAppendf(
-R"SkSL(%s = %s(%s);
-)SkSL"
-, args.fOutputColor, switchy_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPSwitchWithoutReturnInsideCanBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 switchy(half4 c) {
-                 half4 result;
-                 switch (int(c.x)) {
-                     case 0: result = c.yyyy;
-                 }
-                 result = c.zzzz;
-                 return result;
-             }
-             void main() {
-                 sk_OutColor = switchy(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_switchy;
-{
-    half4 result;
-    switch (int(%s.x)) {
-        case 0:
-            result = %s.yyyy;
-    }
-    result = %s.zzzz;
-    _0_switchy = result;
-}
-
-%s = _0_switchy;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPForLoopWithReturnInsideCannotBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 loopy(half4 c) {
-                 for (int x=0; x<5; ++x) {
-                     if (x == int(c.w)) return c.yyyy;
-                 }
-                 return c.zzzz;
-             }
-             void main() {
-                 sk_OutColor = loopy(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->emitFunction(kHalf4_GrSLType, "loopy", 1, loopy_args,
-R"SkSL(for (int x = 0;x < 5; ++x) {
-    if (x == int(c.w)) return c.yyyy;
-}
-return c.zzzz;
-)SkSL", &loopy_name);
-        fragBuilder->codeAppendf(
-R"SkSL(%s = %s(%s);
-)SkSL"
-, args.fOutputColor, loopy_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPSwitchWithCastCanBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 switchy(half4 c) {
-                 half4 result;
-                 switch (int(c.x)) {
-                     case 1: result = c.yyyy; break;
-                     default: result = c.zzzz; break;
-                 }
-                 return result;
-             }
-             void main() {
-                 sk_OutColor = switchy(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_switchy;
-{
-    half4 result;
-    switch (int(%s.x)) {
-        case 1:
-            result = %s.yyyy;
-            break;
-        default:
-            result = %s.zzzz;
-            break;
-    }
-    _0_switchy = result;
-}
-
-%s = _0_switchy;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPForLoopWithoutReturnInsideCanBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 loopy(half4 c) {
-                 half4 pix;
-                 for (int x=0; x<5; ++x) {
-                     if (x == int(c.w)) pix = c.yyyy;
-                 }
-                 pix = c.zzzz;
-                 return pix;
-             }
-             void main() {
-                 sk_OutColor = loopy(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_loopy;
-{
-    half4 pix;
-    for (int x = 0;x < 5; ++x) {
-        if (x == int(%s.w)) pix = %s.yyyy;
-    }
-    pix = %s.zzzz;
-    _0_loopy = pix;
-}
-
-%s = _0_loopy;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinerManglesOverlappingNames, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half add(half a, half b) {
-                 half c = a + b;
-                 return c;
-             }
-             half mul(half a, half b) {
-                 return a * b;
-             }
-             half fma(half a, half b, half c) {
-                 return add(mul(a, b), c);
-             }
-             half4 main() {
-                 half a = fma(color.x, color.y, color.z);
-                 half b = fma(color.y, color.z, color.w);
-                 half c = fma(color.z, color.w, color.x);
-                 return half4(a, b, mul(c, c), mul(a, mul(b, c)));
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half _2_fma;
-half _3_a = %s.x;
-half _4_b = %s.y;
-half _5_c = %s.z;
-{
-    half _0_mul;
-    {
-        _0_mul = _3_a * _4_b;
-    }
-
-    half _1_add;
-    {
-        half c = _0_mul + _5_c;
-        _1_add = c;
-    }
-
-    _2_fma = _1_add;
-
-}
-
-half a = _2_fma;
-
-half _6_fma;
-half _7_a = %s.y;
-half _8_b = %s.z;
-half _9_c = %s.w;
-{
-    half _0_mul;
-    {
-        _0_mul = _7_a * _8_b;
-    }
-
-    half _1_add;
-    {
-        half c = _0_mul + _9_c;
-        _1_add = c;
-    }
-
-    _6_fma = _1_add;
-
-}
-
-half b = _6_fma;
-
-half _10_fma;
-half _11_a = %s.z;
-half _12_b = %s.w;
-half _13_c = %s.x;
-{
-    half _0_mul;
-    {
-        _0_mul = _11_a * _12_b;
-    }
-
-    half _1_add;
-    {
-        half c = _0_mul + _13_c;
-        _1_add = c;
-    }
-
-    _10_fma = _1_add;
-
-}
-
-half c = _10_fma;
-
-half _14_mul;
-{
-    _14_mul = c * c;
-}
-
-half _15_mul;
-{
-    _15_mul = b * c;
-}
-
-half _16_mul;
-{
-    _16_mul = a * _15_mul;
-}
-
-return half4(a, b, _14_mul, _16_mul);
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPIfStatementWithReturnInsideCanBeInlined, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 branchy(half4 c) {
-                 if (c.z == c.w) return c.yyyy; else return c.zzzz;
-             }
-             void main() {
-                 sk_OutColor = branchy(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_branchy;
-{
-    if (%s.z == %s.w) _0_branchy = %s.yyyy; else _0_branchy = %s.zzzz;
-}
-
-%s = _0_branchy;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPUnnecessaryBlocksDoNotAffectEarlyReturnDetection, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             half4 blocky(half4 c) {
-                 {
-                     return c;
-                 }
-             }
-             void main() {
-                 sk_OutColor = blocky(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_blocky;
-{
-    {
-        _0_blocky = %s;
-    }
-}
-
-%s = _0_blocky;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedEarlyReturnsAreWrappedInDoWhileBlock, r) {
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             inline half4 returny(half4 c) {
-                 if (c.x > c.y) return c.xxxx;
-                 if (c.y > c.z) return c.yyyy;
-                 return c.zzzz;
-             }
-             void main() {
-                 sk_OutColor = returny(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_returny;
-do {
-    if (%s.x > %s.y) {
-        _0_returny = %s.xxxx;
-        break;
-    }
-    if (%s.y > %s.z) {
-        _0_returny = %s.yyyy;
-        break;
-    }
-    {
-        _0_returny = %s.zzzz;
-        break;
-    }
-} while (false);
-
-%s = _0_returny;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPEarlyReturnDetectionSupportsIfElse, r) {
-    // An if-else statement at the end of a function, with a return as the last statement on all
-    // paths, are not actually "early" returns. The inliner is able to recognize this pattern.
-    test(r,
-         *SkSL::ShaderCapsFactory::Default(),
-         R"__SkSL__(
-             uniform half4 color;
-             inline half4 branchy(half4 c) {
-                 c *= 0.5;
-                 if (c.x > 0)
-                     return c.xxxx;
-                 else if (c.y > 0)
-                     return c.yyyy;
-                 else if (c.z > 0)
-                     return c.zzzz;
-                 else
-                     return c.wwww;
-             }
-             inline half4 branchyAndBlocky(half4 c) {{{
-                 if (c.x > 0) {
-                     half4 d = c * 0.5;
-                     return d.xxxx;
-                 } else {{{
-                     if (c.x < 0) {
-                         return c.wwww;
-                     } else {
-                         return c.yyyy;
-                     }
-                 }}}
-             }}}
-             void main() {
-                 sk_OutColor = branchy(color) * branchyAndBlocky(color);
-             }
-         )__SkSL__",
-         /*expectedH=*/{},
-         /*expectedCPP=*/{
-         R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_branchy;
-half4 _1_c = %s;
-{
-    _1_c *= 0.5;
-    if (_1_c.x > 0.0) _0_branchy = _1_c.xxxx; else if (_1_c.y > 0.0) _0_branchy = _1_c.yyyy; else if (_1_c.z > 0.0) _0_branchy = _1_c.zzzz; else _0_branchy = _1_c.wwww;
-}
-
-half4 _2_branchyAndBlocky;
-{
-    {
-        {
-            if (%s.x > 0.0) {
-                half4 d = %s * 0.5;
-                _2_branchyAndBlocky = d.xxxx;
-            } else {
-                {
-                    {
-                        if (%s.x < 0.0) {
-                            _2_branchyAndBlocky = %s.wwww;
-                        } else {
-                            _2_branchyAndBlocky = %s.yyyy;
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-%s = _0_branchy * _2_branchyAndBlocky;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
 DEF_TEST(SkSLFPGrSLTypesAreSupported, r) {
     // We thwart the optimizer by wrapping our return statement in a loop, which prevents inlining.
     test(r,
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 62b63a4..16724fb 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -125,70 +125,6 @@
 )__GLSL__");
 }
 
-DEF_TEST(SkSLFunctionInlineThreshold, r) {
-    test(r,
-         "void tooBig(inout int x) {"
-         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
-         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
-         "}"
-         "void main() { int x = 0; tooBig(x); }",
-         *SkSL::ShaderCapsFactory::Default(),
-         "#version 400\n"
-         "void tooBig(inout int x) {\n"
-         "    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n"
-         "    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n"
-         "    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n"
-         "    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n"
-         "    ++x;\n    ++x;\n"
-         "}\n"
-         "void main() {\n"
-         "    int x = 0;\n"
-         "    tooBig(x);\n"
-         "}\n"
-         );
-    test(r,
-         "inline void tooBig(inout int x) {"
-         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
-         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
-         "}"
-         "void main() { int y = 0; tooBig(y); }",
-         *SkSL::ShaderCapsFactory::Default(),
-         "#version 400\n"
-         "void main() {\n"
-         "    int y = 0;\n"
-         "    {\n"
-         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
-         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
-         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
-         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
-         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
-         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
-         "    }\n"
-         "\n"
-         "}\n"
-         );
-    test(r,
-         "inline void cantActuallyInline(inout int x) {"
-         "    for (;;) {"
-         "        ++x;"
-         "        if (x > 10) return;"
-         "    }"
-         "}"
-         "void main() { int x = 0; cantActuallyInline(x); }",
-         *SkSL::ShaderCapsFactory::Default(),
-         "#version 400\n"
-         "void cantActuallyInline(inout int x) {\n"
-         "    for (; ; ) {\n"
-         "        ++x;\n"
-         "        if (x > 10) return;\n"
-         "    }\n"
-         "}\n"
-         "void main() {\n"
-         "    int x = 0;\n"
-         "    cantActuallyInline(x);\n"
-         "}\n");
-}
-
 DEF_TEST(SkSLOperators, r) {
     test(r,
          "void main() {"
@@ -239,136 +175,6 @@
          "}\n");
 }
 
-DEF_TEST(SkSLFunctionInlineArguments, r) {
-    test(r,
-         "half basic(half x) {"
-         "    return x * 2;"
-         "}"
-         "void main() {"
-         "    sk_FragColor.x = basic(1);"
-         "    half y = 2;"
-         "    sk_FragColor.y = basic(y);"
-         "}",
-         *SkSL::ShaderCapsFactory::Default(),
-         "#version 400\n"
-         "out vec4 sk_FragColor;\n"
-         "void main() {\n"
-         "    sk_FragColor.x = 2.0;\n"
-         "\n"
-         "    sk_FragColor.y = 4.0;\n"
-         "\n"
-         "}\n");
-    test(r,
-         "half parameterWrite(half x) {"
-         "    x *= 2;"
-         "    return x;"
-         "}"
-         "void main() {"
-         "    sk_FragColor.x = parameterWrite(1);"
-         "}",
-         *SkSL::ShaderCapsFactory::Default(),
-R"__GLSL__(#version 400
-out vec4 sk_FragColor;
-void main() {
-    float _0_parameterWrite;
-    float _1_x = 1.0;
-    {
-        _1_x *= 2.0;
-        _0_parameterWrite = _1_x;
-    }
-
-    sk_FragColor.x = _0_parameterWrite;
-
-}
-)__GLSL__");
-    test(r,
-         "void outParameter(inout half x) {"
-         "    x *= 2;"
-         "}"
-         "void main() {"
-         "    half x = 1;"
-         "    outParameter(x);"
-         "    sk_FragColor.x = x;"
-         "}",
-         *SkSL::ShaderCapsFactory::Default(),
-         "#version 400\n"
-         "out vec4 sk_FragColor;\n"
-         "void main() {\n"
-         "    float x = 1.0;\n"
-         "    {\n"
-         "        x *= 2.0;\n"
-         "    }\n"
-         "\n"
-         "    sk_FragColor.x = x;\n"
-         "}\n");
-    test(r,
-         "void foo(out half x) {"
-         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
-         "    --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x;"
-         "    x = 42;"
-         "}"
-         "half bar(half y) {"
-         "    foo(y);"
-         "    return y;"
-         "}"
-         "void main() {"
-         "    half _1_y = 123;"  // make sure the inliner doesn't try to reuse this name
-         "    half z = 0;"
-         "    bar(z);"
-         "    sk_FragColor.x = z;"
-         "}",
-         *SkSL::ShaderCapsFactory::Default(),
-R"__GLSL__(#version 400
-out vec4 sk_FragColor;
-void foo(out float x) {
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    ++x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    --x;
-    x = 42.0;
-}
-void main() {
-    float _2_y = 0.0;
-    {
-        foo(_2_y);
-    }
-
-
-    sk_FragColor.x = 0.0;
-}
-)__GLSL__");
-}
-
 DEF_TEST(SkSLMatrices, r) {
     test(r,
          "void main() {"
diff --git a/tests/SkSLInlinerTest.cpp b/tests/SkSLInlinerTest.cpp
new file mode 100644
index 0000000..4bb7be0
--- /dev/null
+++ b/tests/SkSLInlinerTest.cpp
@@ -0,0 +1,1100 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/sksl/SkSLCompiler.h"
+
+#include "tests/Test.h"
+
+// Note that the optimizer will aggressively kill dead code and substitute constants in place of
+// variables, so we have to jump through a few hoops to ensure that the code in these tests has the
+// necessary side-effects to remain live. In some cases we rely on the optimizer not (yet) being
+// smart enough to optimize around certain constructs; as the optimizer gets smarter it will
+// undoubtedly end up breaking some of these tests. That is a good thing, as long as the new code is
+// equivalent!
+
+static void test(skiatest::Reporter* r, const SkSL::Program::Settings& settings,
+                 const char* src, const char* expectedGLSL, SkSL::Program::Inputs* inputs,
+                 SkSL::Program::Kind kind = SkSL::Program::kFragment_Kind) {
+    SkSL::Compiler compiler;
+    SkSL::String output;
+    std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, SkSL::String(src),
+                                                                     settings);
+    if (!program) {
+        SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
+    }
+    REPORTER_ASSERT(r, program);
+    if (program) {
+        *inputs = program->fInputs;
+        REPORTER_ASSERT(r, compiler.toGLSL(*program, &output));
+        if (program) {
+            SkSL::String skExpected(expectedGLSL);
+            if (output != skExpected) {
+                SkDebugf("GLSL MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'",
+                         src, expectedGLSL, output.c_str());
+            }
+            REPORTER_ASSERT(r, output == skExpected);
+        }
+    }
+}
+
+static void test(skiatest::Reporter* r, const GrShaderCaps& caps,
+                 const char* src, const char* expectedGLSL,
+                 SkSL::Program::Kind kind = SkSL::Program::kFragment_Kind) {
+    SkSL::Program::Settings settings;
+    settings.fCaps = &caps;
+    SkSL::Program::Inputs inputs;
+    test(r, settings, src, expectedGLSL, &inputs, kind);
+}
+
+DEF_TEST(SkSLFunctionInlineThreshold, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         "void tooBig(inout int x) {"
+         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
+         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
+         "}"
+         "void main() { int x = 0; tooBig(x); }",
+         "#version 400\n"
+         "void tooBig(inout int x) {\n"
+         "    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n"
+         "    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n"
+         "    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n"
+         "    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n    ++x;\n"
+         "    ++x;\n    ++x;\n"
+         "}\n"
+         "void main() {\n"
+         "    int x = 0;\n"
+         "    tooBig(x);\n"
+         "}\n"
+         );
+}
+
+DEF_TEST(SkSLFunctionInlineKeywordOverridesThreshold, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         "inline void tooBig(inout int x) {"
+         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
+         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
+         "}"
+         "void main() { int y = 0; tooBig(y); }",
+         "#version 400\n"
+         "void main() {\n"
+         "    int y = 0;\n"
+         "    {\n"
+         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
+         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
+         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
+         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
+         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
+         "        ++y;\n        ++y;\n        ++y;\n        ++y;\n"
+         "    }\n"
+         "\n"
+         "}\n"
+         );
+}
+
+DEF_TEST(SkSLFunctionUnableToInlineReturnsInsideLoop, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         "inline void cantActuallyInline(inout int x) {"
+         "    for (;;) {"
+         "        ++x;"
+         "        if (x > 10) return;"
+         "    }"
+         "}"
+         "void main() { int x = 0; cantActuallyInline(x); }",
+         "#version 400\n"
+         "void cantActuallyInline(inout int x) {\n"
+         "    for (; ; ) {\n"
+         "        ++x;\n"
+         "        if (x > 10) return;\n"
+         "    }\n"
+         "}\n"
+         "void main() {\n"
+         "    int x = 0;\n"
+         "    cantActuallyInline(x);\n"
+         "}\n");
+}
+
+DEF_TEST(SkSLFunctionInlineWithUnmodifiedArgument, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         "half basic(half x) {"
+         "    return x * 2;"
+         "}"
+         "void main() {"
+         "    sk_FragColor.x = basic(1);"
+         "    half y = 2;"
+         "    sk_FragColor.y = basic(y);"
+         "}",
+         "#version 400\n"
+         "out vec4 sk_FragColor;\n"
+         "void main() {\n"
+         "    sk_FragColor.x = 2.0;\n"
+         "\n"
+         "    sk_FragColor.y = 4.0;\n"
+         "\n"
+         "}\n");
+}
+
+DEF_TEST(SkSLFunctionInlineWithModifiedArgument, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         "half parameterWrite(half x) {"
+         "    x *= 2;"
+         "    return x;"
+         "}"
+         "void main() {"
+         "    sk_FragColor.x = parameterWrite(1);"
+         "}",
+R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+    float _0_parameterWrite;
+    float _1_x = 1.0;
+    {
+        _1_x *= 2.0;
+        _0_parameterWrite = _1_x;
+    }
+
+    sk_FragColor.x = _0_parameterWrite;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFunctionInlineWithInoutArgument, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         "void outParameter(inout half x) {"
+         "    x *= 2;"
+         "}"
+         "void main() {"
+         "    half x = 1;"
+         "    outParameter(x);"
+         "    sk_FragColor.x = x;"
+         "}",
+         "#version 400\n"
+         "out vec4 sk_FragColor;\n"
+         "void main() {\n"
+         "    float x = 1.0;\n"
+         "    {\n"
+         "        x *= 2.0;\n"
+         "    }\n"
+         "\n"
+         "    sk_FragColor.x = x;\n"
+         "}\n");
+}
+
+DEF_TEST(SkSLFunctionInlineWithNestedCall, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         "void foo(out half x) {"
+         "    ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x; ++x;"
+         "    --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x; --x;"
+         "    x = 42;"
+         "}"
+         "half bar(half y) {"
+         "    foo(y);"
+         "    return y;"
+         "}"
+         "void main() {"
+         "    half _1_y = 123;"  // make sure the inliner doesn't try to reuse this name
+         "    half z = 0;"
+         "    bar(z);"
+         "    sk_FragColor.x = z;"
+         "}",
+R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void foo(out float x) {
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    ++x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    --x;
+    x = 42.0;
+}
+void main() {
+    float _2_y = 0.0;
+    {
+        foo(_2_y);
+    }
+
+
+    sk_FragColor.x = 0.0;
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPTernaryExpressionsShouldNotInlineResults, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half count = 0;
+             bool test(half4 v) {
+                 return v.x <= 0.5;
+             }
+             half4 trueSide(half4 v) {
+                 count += 1;
+                 return half4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));
+             }
+             half4 falseSide(half4 v) {
+                 count += 1;
+                 return half4(cos(v.y), cos(v.z), cos(v.w), cos(v.z));
+             }
+             void main() {
+                 sk_FragColor = test(color) ? trueSide(color) : falseSide(color);
+                 sk_FragColor *= count;
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+float count = 0.0;
+vec4 trueSide(vec4 v) {
+    count += 1.0;
+    return vec4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));
+}
+vec4 falseSide(vec4 v) {
+    count += 1.0;
+    return vec4(cos(v.y), cos(v.z), cos(v.w), cos(v.z));
+}
+void main() {
+    bool _0_test;
+    {
+        _0_test = color.x <= 0.5;
+    }
+
+    sk_FragColor = _0_test ? trueSide(color) : falseSide(color);
+
+    sk_FragColor *= count;
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPShortCircuitEvaluationsCannotInlineRightHandSide, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             bool testA(half4 v) {
+                 return v.x <= 0.5;
+             }
+             bool testB(half4 v) {
+                 return v.x > 0.5;
+             }
+             void main() {
+                 sk_FragColor = half4(0);
+                 if (testA(color) && testB(color)) {
+                    sk_FragColor = half4(0.5);
+                 }
+                 if (testB(color) || testA(color)) {
+                    sk_FragColor = half4(1.0);
+                 }
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+bool testA(vec4 v) {
+    return v.x <= 0.5;
+}
+bool testB(vec4 v) {
+    return v.x > 0.5;
+}
+void main() {
+    sk_FragColor = vec4(0.0);
+    bool _0_testA;
+    {
+        _0_testA = color.x <= 0.5;
+    }
+
+    if (_0_testA && testB(color)) {
+        sk_FragColor = vec4(0.5);
+    }
+
+    bool _1_testB;
+    {
+        _1_testB = color.x > 0.5;
+    }
+
+    if (_1_testB || testA(color)) {
+        sk_FragColor = vec4(1.0);
+    }
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPWhileTestCannotBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             bool shouldLoop(half4 v) {
+                 return v.x < 0.5;
+             }
+             void main() {
+                 sk_FragColor = half4(0);
+                 while (shouldLoop(sk_FragColor)) {
+                     sk_FragColor += half4(0.125);
+                 }
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+bool shouldLoop(vec4 v) {
+    return v.x < 0.5;
+}
+void main() {
+    sk_FragColor = vec4(0.0);
+    while (shouldLoop(sk_FragColor)) {
+        sk_FragColor += vec4(0.125);
+    }
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedWhileBodyMustBeInAScope, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             half4 adjust(half4 v) {
+                 return v + half4(0.125);
+             }
+             void main() {
+                 sk_FragColor = half4(0);
+                 while (sk_FragColor.x < 0.5)
+                     sk_FragColor = adjust(sk_FragColor);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+    sk_FragColor = vec4(0.0);
+    while (sk_FragColor.x < 0.5) {
+        vec4 _0_adjust;
+        {
+            _0_adjust = sk_FragColor + vec4(0.125);
+        }
+
+        sk_FragColor = _0_adjust;
+    }
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPDoWhileTestCannotBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             bool shouldLoop(half4 v) {
+                 return v.x < 0.5;
+             }
+             void main() {
+                 sk_FragColor = half4(0);
+                 do {
+                     sk_FragColor += half4(0.125);
+                 } while (shouldLoop(sk_FragColor));
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+bool shouldLoop(vec4 v) {
+    return v.x < 0.5;
+}
+void main() {
+    sk_FragColor = vec4(0.0);
+    do {
+        sk_FragColor += vec4(0.125);
+    } while (shouldLoop(sk_FragColor));
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedDoWhileBodyMustBeInAScope, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             half4 adjust(half4 v) {
+                 return v + half4(0.125);
+             }
+             void main() {
+                 sk_FragColor = half4(0);
+                 do
+                     sk_FragColor = adjust(sk_FragColor);
+                 while (sk_FragColor.x < 0.5);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+    sk_FragColor = vec4(0.0);
+    do {
+        vec4 _0_adjust;
+        {
+            _0_adjust = sk_FragColor + vec4(0.125);
+        }
+
+        sk_FragColor = _0_adjust;
+    } while (sk_FragColor.x < 0.5);
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPOnlyForInitializerExpressionsCanBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             half4 initLoopVar() {
+                 return half4(0.0625);
+             }
+             bool shouldLoop(half4 v) {
+                 return v.x < 0.5;
+             }
+             half4 grow(half4 v) {
+                 return v + half4(0.125);
+             }
+             void main() {
+                 for (sk_FragColor = initLoopVar();
+                      shouldLoop(sk_FragColor);
+                      sk_FragColor = grow(sk_FragColor)) {
+                 }
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+bool shouldLoop(vec4 v) {
+    return v.x < 0.5;
+}
+vec4 grow(vec4 v) {
+    return v + vec4(0.125);
+}
+void main() {
+    for (sk_FragColor = vec4(0.0625);
+    shouldLoop(sk_FragColor); sk_FragColor = grow(sk_FragColor)) {
+    }
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedForBodyMustBeInAScope, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             half4 adjust(half4 v) {
+                 return v + half4(0.125);
+             }
+             void main() {
+                 sk_FragColor = half4(0);
+                 for (int x=0; x<4; ++x)
+                     sk_FragColor = adjust(sk_FragColor);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+    sk_FragColor = vec4(0.0);
+    for (int x = 0;x < 4; ++x) {
+        vec4 _0_adjust;
+        {
+            _0_adjust = sk_FragColor + vec4(0.125);
+        }
+
+        sk_FragColor = _0_adjust;
+    }
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPIfTestsCanBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             bool ifTest(half4 v) {
+                 return color.x >= 0.5;
+             }
+             void main() {
+                 if (ifTest(color))
+                     sk_FragColor = half4(1.0);
+                 else
+                     sk_FragColor = half4(0.5);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    bool _0_ifTest;
+    {
+        _0_ifTest = color.x >= 0.5;
+    }
+
+    if (_0_ifTest) sk_FragColor = vec4(1.0); else sk_FragColor = vec4(0.5);
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedIfBodyMustBeInAScope, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 ifBody() {
+                 return color + half4(0.125);
+             }
+             void main() {
+                 half4 c = color;
+                 if (c.x >= 0.5)
+                     c = ifBody();
+                 sk_FragColor = c;
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 c = color;
+    if (c.x >= 0.5) {
+        vec4 _0_ifBody;
+        {
+            _0_ifBody = color + vec4(0.125);
+        }
+
+        c = _0_ifBody;
+    }
+    sk_FragColor = c;
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedElseBodyMustBeInAScope, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 elseBody() {
+                 return color + half4(0.125);
+             }
+             void main() {
+                 half4 c = color;
+                 if (c.x >= 0.5)
+                     ;
+                 else
+                     c = elseBody();
+                 sk_FragColor = c;
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 c = color;
+    if (c.x >= 0.5) {
+    } else {
+        vec4 _0_elseBody;
+        {
+            _0_elseBody = color + vec4(0.125);
+        }
+
+        c = _0_elseBody;
+    }
+    sk_FragColor = c;
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPSwitchWithReturnInsideCannotBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 switchy(half4 c) {
+                 switch (int(c.x)) {
+                     case 0: return c.yyyy;
+                 }
+                 return c.zzzz;
+             }
+             void main() {
+                 sk_FragColor = switchy(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+vec4 switchy(vec4 c) {
+    switch (int(c.x)) {
+        case 0:
+            return c.yyyy;
+    }
+    return c.zzzz;
+}
+void main() {
+    sk_FragColor = switchy(color);
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPSwitchWithoutReturnInsideCanBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 switchy(half4 c) {
+                 half4 result;
+                 switch (int(c.x)) {
+                     case 0: result = c.yyyy;
+                 }
+                 result = c.zzzz;
+                 return result;
+             }
+             void main() {
+                 sk_FragColor = switchy(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 _0_switchy;
+    {
+        vec4 result;
+        switch (int(color.x)) {
+            case 0:
+                result = color.yyyy;
+        }
+        result = color.zzzz;
+        _0_switchy = result;
+    }
+
+    sk_FragColor = _0_switchy;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPForLoopWithReturnInsideCannotBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 loopy(half4 c) {
+                 for (int x=0; x<5; ++x) {
+                     if (x == int(c.w)) return c.yyyy;
+                 }
+                 return c.zzzz;
+             }
+             void main() {
+                 sk_FragColor = loopy(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+vec4 loopy(vec4 c) {
+    for (int x = 0;x < 5; ++x) {
+        if (x == int(c.w)) return c.yyyy;
+    }
+    return c.zzzz;
+}
+void main() {
+    sk_FragColor = loopy(color);
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPSwitchWithCastCanBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 switchy(half4 c) {
+                 half4 result;
+                 switch (int(c.x)) {
+                     case 1: result = c.yyyy; break;
+                     default: result = c.zzzz; break;
+                 }
+                 return result;
+             }
+             void main() {
+                 sk_FragColor = switchy(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 _0_switchy;
+    {
+        vec4 result;
+        switch (int(color.x)) {
+            case 1:
+                result = color.yyyy;
+                break;
+            default:
+                result = color.zzzz;
+                break;
+        }
+        _0_switchy = result;
+    }
+
+    sk_FragColor = _0_switchy;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPForLoopWithoutReturnInsideCanBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 loopy(half4 c) {
+                 half4 pix;
+                 for (int x=0; x<5; ++x) {
+                     if (x == int(c.w)) pix = c.yyyy;
+                 }
+                 pix = c.zzzz;
+                 return pix;
+             }
+             void main() {
+                 sk_FragColor = loopy(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 _0_loopy;
+    {
+        vec4 pix;
+        for (int x = 0;x < 5; ++x) {
+            if (x == int(color.w)) pix = color.yyyy;
+        }
+        pix = color.zzzz;
+        _0_loopy = pix;
+    }
+
+    sk_FragColor = _0_loopy;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinerManglesOverlappingNames, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half add(half a, half b) {
+                 half c = a + b;
+                 return c;
+             }
+             half mul(half a, half b) {
+                 return a * b;
+             }
+             half fma(half a, half b, half c) {
+                 return add(mul(a, b), c);
+             }
+             half4 main() {
+                 half a = fma(color.x, color.y, color.z);
+                 half b = fma(color.y, color.z, color.w);
+                 half c = fma(color.z, color.w, color.x);
+                 return half4(a, b, mul(c, c), mul(a, mul(b, c)));
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+uniform vec4 color;
+vec4 main() {
+    float _2_fma;
+    float _3_a = color.x;
+    float _4_b = color.y;
+    float _5_c = color.z;
+    {
+        float _0_mul;
+        {
+            _0_mul = _3_a * _4_b;
+        }
+
+        float _1_add;
+        {
+            float c = _0_mul + _5_c;
+            _1_add = c;
+        }
+
+        _2_fma = _1_add;
+
+    }
+
+    float a = _2_fma;
+
+    float _6_fma;
+    float _7_a = color.y;
+    float _8_b = color.z;
+    float _9_c = color.w;
+    {
+        float _0_mul;
+        {
+            _0_mul = _7_a * _8_b;
+        }
+
+        float _1_add;
+        {
+            float c = _0_mul + _9_c;
+            _1_add = c;
+        }
+
+        _6_fma = _1_add;
+
+    }
+
+    float b = _6_fma;
+
+    float _10_fma;
+    float _11_a = color.z;
+    float _12_b = color.w;
+    float _13_c = color.x;
+    {
+        float _0_mul;
+        {
+            _0_mul = _11_a * _12_b;
+        }
+
+        float _1_add;
+        {
+            float c = _0_mul + _13_c;
+            _1_add = c;
+        }
+
+        _10_fma = _1_add;
+
+    }
+
+    float c = _10_fma;
+
+    float _14_mul;
+    {
+        _14_mul = c * c;
+    }
+
+    float _15_mul;
+    {
+        _15_mul = b * c;
+    }
+
+    float _16_mul;
+    {
+        _16_mul = a * _15_mul;
+    }
+
+    return vec4(a, b, _14_mul, _16_mul);
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPIfStatementWithReturnInsideCanBeInlined, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 branchy(half4 c) {
+                 if (c.z == c.w) return c.yyyy; else return c.zzzz;
+             }
+             void main() {
+                 sk_FragColor = branchy(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 _0_branchy;
+    {
+        if (color.z == color.w) _0_branchy = color.yyyy; else _0_branchy = color.zzzz;
+    }
+
+    sk_FragColor = _0_branchy;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPUnnecessaryBlocksDoNotAffectEarlyReturnDetection, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             half4 blocky(half4 c) {
+                 {
+                     return c;
+                 }
+             }
+             void main() {
+                 sk_FragColor = blocky(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 _0_blocky;
+    {
+        {
+            _0_blocky = color;
+        }
+    }
+
+    sk_FragColor = _0_blocky;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedEarlyReturnsAreWrappedInDoWhileBlock, r) {
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             inline half4 returny(half4 c) {
+                 if (c.x > c.y) return c.xxxx;
+                 if (c.y > c.z) return c.yyyy;
+                 return c.zzzz;
+             }
+             void main() {
+                 sk_FragColor = returny(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 _0_returny;
+    do {
+        if (color.x > color.y) {
+            _0_returny = color.xxxx;
+            break;
+        }
+        if (color.y > color.z) {
+            _0_returny = color.yyyy;
+            break;
+        }
+        {
+            _0_returny = color.zzzz;
+            break;
+        }
+    } while (false);
+
+    sk_FragColor = _0_returny;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPEarlyReturnDetectionSupportsIfElse, r) {
+    // An if-else statement at the end of a function, with a return as the last statement on all
+    // paths, are not actually "early" returns. The inliner is able to recognize this pattern.
+    test(r,
+         *SkSL::ShaderCapsFactory::Default(),
+         /*src=*/R"__SkSL__(
+             uniform half4 color;
+             inline half4 branchy(half4 c) {
+                 c *= 0.5;
+                 if (c.x > 0)
+                     return c.xxxx;
+                 else if (c.y > 0)
+                     return c.yyyy;
+                 else if (c.z > 0)
+                     return c.zzzz;
+                 else
+                     return c.wwww;
+             }
+             inline half4 branchyAndBlocky(half4 c) {{{
+                 if (c.x > 0) {
+                     half4 d = c * 0.5;
+                     return d.xxxx;
+                 } else {{{
+                     if (c.x < 0) {
+                         return c.wwww;
+                     } else {
+                         return c.yyyy;
+                     }
+                 }}}
+             }}}
+             void main() {
+                 sk_FragColor = branchy(color) * branchyAndBlocky(color);
+             }
+         )__SkSL__",
+         /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+    vec4 _0_branchy;
+    vec4 _1_c = color;
+    {
+        _1_c *= 0.5;
+        if (_1_c.x > 0.0) _0_branchy = _1_c.xxxx; else if (_1_c.y > 0.0) _0_branchy = _1_c.yyyy; else if (_1_c.z > 0.0) _0_branchy = _1_c.zzzz; else _0_branchy = _1_c.wwww;
+    }
+
+    vec4 _2_branchyAndBlocky;
+    {
+        {
+            {
+                if (color.x > 0.0) {
+                    vec4 d = color * 0.5;
+                    _2_branchyAndBlocky = d.xxxx;
+                } else {
+                    {
+                        {
+                            if (color.x < 0.0) {
+                                _2_branchyAndBlocky = color.wwww;
+                            } else {
+                                _2_branchyAndBlocky = color.yyyy;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    sk_FragColor = _0_branchy * _2_branchyAndBlocky;
+
+}
+)__GLSL__");
+}