Generate performance warnings in HLSL translation

Generate performance warnings for some code that undergoes heavy
emulation when translated to HLSL:
1. Dynamic indexing of vectors and matrices.
2. Non-empty fall-through cases in switch/case.

The warnings are generated only when code is translated to HLSL.
Generating them in the parsing stage would add too much maintenance
burden.

Improves switch statement fall-through handling in cases where an
empty fall-through case follows a non-empty one so that extra
performance warnings are not generated.

BUG=angleproject:1116

Change-Id: I7c85d78fe7c4f8e6042bda72ceaaf6e37dadfe6c
Reviewed-on: https://chromium-review.googlesource.com/732986
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/compiler/translator/RemoveDynamicIndexing.cpp
index 5344a27..7766c1a 100644
--- a/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ b/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -9,6 +9,7 @@
 
 #include "compiler/translator/RemoveDynamicIndexing.h"
 
+#include "compiler/translator/Diagnostics.h"
 #include "compiler/translator/InfoSink.h"
 #include "compiler/translator/IntermNodePatternMatcher.h"
 #include "compiler/translator/IntermNode_util.h"
@@ -281,7 +282,9 @@
 class RemoveDynamicIndexingTraverser : public TLValueTrackingTraverser
 {
   public:
-    RemoveDynamicIndexingTraverser(TSymbolTable *symbolTable, int shaderVersion);
+    RemoveDynamicIndexingTraverser(TSymbolTable *symbolTable,
+                                   int shaderVersion,
+                                   PerformanceDiagnostics *perfDiagnostics);
 
     bool visitBinary(Visit visit, TIntermBinary *node) override;
 
@@ -305,13 +308,18 @@
     //   V[j++][i]++.
     // where V is an array of vectors, j++ will only be evaluated once.
     bool mRemoveIndexSideEffectsInSubtree;
+
+    PerformanceDiagnostics *mPerfDiagnostics;
 };
 
-RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser(TSymbolTable *symbolTable,
-                                                               int shaderVersion)
+RemoveDynamicIndexingTraverser::RemoveDynamicIndexingTraverser(
+    TSymbolTable *symbolTable,
+    int shaderVersion,
+    PerformanceDiagnostics *perfDiagnostics)
     : TLValueTrackingTraverser(true, false, false, symbolTable, shaderVersion),
       mUsedTreeInsertion(false),
-      mRemoveIndexSideEffectsInSubtree(false)
+      mRemoveIndexSideEffectsInSubtree(false),
+      mPerfDiagnostics(perfDiagnostics)
 {
 }
 
@@ -398,6 +406,10 @@
         }
         else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node))
         {
+            mPerfDiagnostics->warning(node->getLine(),
+                                      "Performance: dynamic indexing of vectors and "
+                                      "matrices is emulated and can be slow.",
+                                      "[]");
             bool write = isLValueRequiredHere();
 
 #if defined(ANGLE_ENABLE_ASSERTS)
@@ -515,9 +527,12 @@
 
 }  // namespace
 
-void RemoveDynamicIndexing(TIntermNode *root, TSymbolTable *symbolTable, int shaderVersion)
+void RemoveDynamicIndexing(TIntermNode *root,
+                           TSymbolTable *symbolTable,
+                           int shaderVersion,
+                           PerformanceDiagnostics *perfDiagnostics)
 {
-    RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion);
+    RemoveDynamicIndexingTraverser traverser(symbolTable, shaderVersion, perfDiagnostics);
     do
     {
         traverser.nextIteration();