Demonstrate a bug with inlined static switches.

When we detect a static switch, the optimizer finds the matching switch-
case and eliminates all the other switch-cases. It handles case
fall-through by scanning forward and looking for an unconditional break.

However, the inliner has an interesting quirk--it can replace `return`
statements inside of a switch with `continue` statements, since the body
of the inlined function has been wrapped with a for-loop to allow for
early exits. The optimizer does not recognize these continue statements
as exits from the switch (although they certainly qualify), so it
treats continues as fallen-through and keeps emitting switch-cases.

The dead-code elimination pass was actually doing us a favor here and
eliminating the excess code later. A flag was added to disable DCE in
order to reveal the problem in a test.

Change-Id: I8ff19fde5e32d0ab73d7c5411da40cb953a446f5
Bug: skia:11352
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372956
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLProgramSettings.h b/src/sksl/SkSLProgramSettings.h
index bc13775..219624a 100644
--- a/src/sksl/SkSLProgramSettings.h
+++ b/src/sksl/SkSLProgramSettings.h
@@ -51,14 +51,17 @@
     // At present, zero is always used by our backends.
     int fDefaultUniformSet = 0;
     int fDefaultUniformBinding = 0;
-    // If true, remove any uncalled functions other than main(). Note that a function which
-    // starts out being used may end up being uncalled after optimization.
-    bool fRemoveDeadFunctions = true;
-    // Sets an upper limit on the acceptable amount of code growth from inlining.
-    // A value of zero will disable the inliner entirely.
-    int fInlineThreshold = SkSL::kDefaultInlineThreshold;
-    // true to enable optimization passes
+    // Enables the SkSL optimizer.
     bool fOptimize = true;
+    // (Requires fOptimize = true) Remove any uncalled functions other than main(). Note that a
+    // function which starts out being used may end up being uncalled after optimization.
+    bool fRemoveDeadFunctions = true;
+    // (Requires fOptimize = true) Uses the control-flow graph to detect and eliminate code within
+    // a function that has become unreachable due to optimization.
+    bool fDeadCodeElimination = true;
+    // (Requires fOptimize = true) When greater than zero, enables the inliner. The threshold value
+    // sets an upper limit on the acceptable amount of code growth from inlining.
+    int fInlineThreshold = SkSL::kDefaultInlineThreshold;
     // If true, implicit conversions to lower precision numeric types are allowed
     // (eg, float to half)
     bool fAllowNarrowingConversions = false;