writer/hlsl: Emit for-loops where possible.

Use the new transforms to try and simplify loops into for-loops.
Emit loops when the initialiser, condition and continuing are simple enough to do so.

Bug: tint:952
Change-Id: I5b3c225b245ffa72996abf6a70f52a9cd25b748e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56772
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/transform/hlsl.cc b/src/transform/hlsl.cc
index 0cea62f..8889fed 100644
--- a/src/transform/hlsl.cc
+++ b/src/transform/hlsl.cc
@@ -21,7 +21,9 @@
 #include "src/transform/canonicalize_entry_point_io.h"
 #include "src/transform/decompose_memory_access.h"
 #include "src/transform/external_texture_transform.h"
+#include "src/transform/fold_trivial_single_use_lets.h"
 #include "src/transform/inline_pointer_lets.h"
+#include "src/transform/loop_to_for_loop.h"
 #include "src/transform/manager.h"
 #include "src/transform/pad_array_elements.h"
 #include "src/transform/promote_initializers_to_const_var.h"
@@ -40,6 +42,12 @@
 Output Hlsl::Run(const Program* in, const DataMap&) {
   Manager manager;
   DataMap data;
+
+  // Attempt to convert `loop`s into for-loops. This is to try and massage the
+  // output into something that will not cause FXC to choke or misbehave.
+  manager.Add<FoldTrivialSingleUseLets>();
+  manager.Add<LoopToForLoop>();
+
   // ZeroInitWorkgroupMemory must come before CanonicalizeEntryPointIO as
   // ZeroInitWorkgroupMemory may inject new builtin parameters.
   manager.Add<ZeroInitWorkgroupMemory>();
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index b6158ab..550b675 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -2549,6 +2549,111 @@
   return true;
 }
 
+bool GeneratorImpl::EmitForLoop(ast::ForLoopStatement* stmt) {
+  TextBuffer init_buf;
+  if (auto* init = stmt->initializer()) {
+    TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
+    if (!EmitStatement(init)) {
+      return false;
+    }
+  }
+  bool multi_stmt_init = init_buf.lines.size() > 1;
+  // For-loop has multi-statement initializer.
+  // This cannot be emitted with a regular for loop, so instead nest the loop in
+  // a new block scope prefixed with these initializer statements.
+  if (multi_stmt_init) {
+    line() << "{";
+    increment_indent();
+    current_buffer_->Append(init_buf);
+    init_buf.lines.clear();  // Don't emit the initializer again in the 'for'
+  }
+
+  TextBuffer cond_pre;
+  std::stringstream cond_buf;
+  if (auto* cond = stmt->condition()) {
+    TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre);
+    if (!EmitExpression(cond_buf, cond)) {
+      return false;
+    }
+  }
+
+  TextBuffer cont_buf;
+  if (auto* cont = stmt->continuing()) {
+    TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
+    if (!EmitStatement(cont)) {
+      return false;
+    }
+  }
+
+  if (cond_pre.lines.size() > 0 || cont_buf.lines.size() > 1) {
+    // For-loop has multi-statement conditional and / or continuing.
+    // This cannot be emitted with a regular for loop, so instead generate a
+    // `while(true)` loop.
+    auto emit_continuing = [&]() {
+      current_buffer_->Append(cont_buf);
+      return true;
+    };
+
+    TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
+    line() << "while (true) {";
+    {
+      ScopedIndent si(this);
+
+      if (stmt->condition()) {
+        current_buffer_->Append(cond_pre);
+        line() << "if (!(" << cond_buf.str() << ")) { break; }";
+      }
+
+      if (!EmitStatements(stmt->body()->statements())) {
+        return false;
+      }
+
+      if (!emit_continuing()) {
+        return false;
+      }
+    }
+    line() << "}";
+  } else {
+    // For-loop can be generated.
+    {
+      auto out = line();
+      out << "for";
+      {
+        ScopedParen sp(out);
+
+        if (!init_buf.lines.empty()) {
+          out << init_buf.lines[0].content << " ";
+        } else {
+          out << "; ";
+        }
+
+        out << cond_buf.str() << "; ";
+
+        if (!cont_buf.lines.empty()) {
+          out << TrimSuffix(cont_buf.lines[0].content, ";");
+        }
+      }
+      out << " {";
+    }
+    {
+      auto emit_continuing = [] { return true; };
+      TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
+      if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+        return false;
+      }
+    }
+
+    line() << "}";
+  }
+
+  if (multi_stmt_init) {
+    decrement_indent();
+    line() << "}";
+  }
+
+  return true;
+}
+
 bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
                                        ast::MemberAccessorExpression* expr) {
   if (!EmitExpression(out, expr->structure())) {
@@ -2617,6 +2722,9 @@
   if (auto* l = stmt->As<ast::LoopStatement>()) {
     return EmitLoop(l);
   }
+  if (auto* l = stmt->As<ast::ForLoopStatement>()) {
+    return EmitForLoop(l);
+  }
   if (auto* r = stmt->As<ast::ReturnStatement>()) {
     return EmitReturn(r);
   }
diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h
index 61d09da..8da3178 100644
--- a/src/writer/hlsl/generator_impl.h
+++ b/src/writer/hlsl/generator_impl.h
@@ -25,6 +25,7 @@
 #include "src/ast/break_statement.h"
 #include "src/ast/continue_statement.h"
 #include "src/ast/discard_statement.h"
+#include "src/ast/for_loop_statement.h"
 #include "src/ast/if_statement.h"
 #include "src/ast/loop_statement.h"
 #include "src/ast/return_statement.h"
@@ -271,6 +272,10 @@
   /// @param stmt the statement to emit
   /// @returns true if the statement was emitted
   bool EmitLoop(ast::LoopStatement* stmt);
+  /// Handles a for loop statement
+  /// @param stmt the statement to emit
+  /// @returns true if the statement was emitted
+  bool EmitForLoop(ast::ForLoopStatement* stmt);
   /// Handles generating an identifier expression
   /// @param out the output of the expression stream
   /// @param expr the identifier expression
diff --git a/src/writer/hlsl/generator_impl_loop_test.cc b/src/writer/hlsl/generator_impl_loop_test.cc
index a775429..0811a6e 100644
--- a/src/writer/hlsl/generator_impl_loop_test.cc
+++ b/src/writer/hlsl/generator_impl_loop_test.cc
@@ -148,6 +148,227 @@
 )");
 }
 
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoop) {
+  // for(; ; ) {
+  //   return;
+  // }
+
+  auto* f = For(nullptr, nullptr, nullptr, Block(Return()));
+  WrapInFunction(f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  for(; ; ) {
+    return;
+  }
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithSimpleInit) {
+  // for(var i : i32; ; ) {
+  //   return;
+  // }
+
+  auto* f = For(Decl(Var("i", ty.i32())), nullptr, nullptr, Block(Return()));
+  WrapInFunction(f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  for(int i = 0; ; ) {
+    return;
+  }
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithMultiStmtInit) {
+  // for(var b = true && false; ; ) {
+  //   return;
+  // }
+  auto* multi_stmt = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
+                                                   Expr(true), Expr(false));
+  auto* f = For(Decl(Var("b", nullptr, multi_stmt)), nullptr, nullptr,
+                Block(Return()));
+  WrapInFunction(f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  {
+    bool tint_tmp = true;
+    if (tint_tmp) {
+      tint_tmp = false;
+    }
+    bool b = (tint_tmp);
+    for(; ; ) {
+      return;
+    }
+  }
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithSimpleCond) {
+  // for(; true; ) {
+  //   return;
+  // }
+
+  auto* f = For(nullptr, true, nullptr, Block(Return()));
+  WrapInFunction(f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  for(; true; ) {
+    return;
+  }
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithMultiStmtCond) {
+  // for(; true && false; ) {
+  //   return;
+  // }
+
+  auto* multi_stmt = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
+                                                   Expr(true), Expr(false));
+  auto* f = For(nullptr, multi_stmt, nullptr, Block(Return()));
+  WrapInFunction(f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  while (true) {
+    bool tint_tmp = true;
+    if (tint_tmp) {
+      tint_tmp = false;
+    }
+    if (!((tint_tmp))) { break; }
+    return;
+  }
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithSimpleCont) {
+  // for(; ; i = i + 1) {
+  //   return;
+  // }
+
+  auto* v = Decl(Var("i", ty.i32()));
+  auto* f = For(nullptr, nullptr, Assign("i", Add("i", 1)), Block(Return()));
+  WrapInFunction(v, f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  for(; ; i = (i + 1)) {
+    return;
+  }
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithMultiStmtCont) {
+  // for(; ; i = true && false) {
+  //   return;
+  // }
+
+  auto* multi_stmt = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
+                                                   Expr(true), Expr(false));
+  auto* v = Decl(Var("i", ty.bool_()));
+  auto* f = For(nullptr, nullptr, Assign("i", multi_stmt), Block(Return()));
+  WrapInFunction(v, f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  while (true) {
+    return;
+    bool tint_tmp = true;
+    if (tint_tmp) {
+      tint_tmp = false;
+    }
+    i = (tint_tmp);
+  }
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithSimpleInitCondCont) {
+  // for(var i : i32; true; i = i + 1) {
+  //   return;
+  // }
+
+  auto* f = For(Decl(Var("i", ty.i32())), true, Assign("i", Add("i", 1)),
+                Block(Return()));
+  WrapInFunction(f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  for(int i = 0; true; i = (i + 1)) {
+    return;
+  }
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithMultiStmtInitCondCont) {
+  // for(var i = true && false; true && false; i = true && false) {
+  //   return;
+  // }
+  auto* multi_stmt_a = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
+                                                     Expr(true), Expr(false));
+  auto* multi_stmt_b = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
+                                                     Expr(true), Expr(false));
+  auto* multi_stmt_c = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
+                                                     Expr(true), Expr(false));
+
+  auto* f = For(Decl(Var("i", nullptr, multi_stmt_a)), multi_stmt_b,
+                Assign("i", multi_stmt_c), Block(Return()));
+  WrapInFunction(f);
+
+  GeneratorImpl& gen = Build();
+
+  gen.increment_indent();
+
+  ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
+  EXPECT_EQ(gen.result(), R"(  {
+    bool tint_tmp = true;
+    if (tint_tmp) {
+      tint_tmp = false;
+    }
+    bool i = (tint_tmp);
+    while (true) {
+      bool tint_tmp_1 = true;
+      if (tint_tmp_1) {
+        tint_tmp_1 = false;
+      }
+      if (!((tint_tmp_1))) { break; }
+      return;
+      bool tint_tmp_2 = true;
+      if (tint_tmp_2) {
+        tint_tmp_2 = false;
+      }
+      i = (tint_tmp_2);
+    }
+  }
+)");
+}
+
 }  // namespace
 }  // namespace hlsl
 }  // namespace writer
diff --git a/test/bug/tint/413.spvasm.expected.hlsl b/test/bug/tint/413.spvasm.expected.hlsl
index d285a8d..8b5111a 100644
--- a/test/bug/tint/413.spvasm.expected.hlsl
+++ b/test/bug/tint/413.spvasm.expected.hlsl
@@ -7,8 +7,7 @@
   srcValue = x_18;
   const uint x_22 = srcValue.x;
   srcValue.x = (x_22 + asuint(1));
-  const uint4 x_27 = srcValue;
-  Dst[int2(0, 0)] = x_27;
+  Dst[int2(0, 0)] = srcValue;
   return;
 }
 
diff --git a/test/bug/tint/453.wgsl.expected.hlsl b/test/bug/tint/453.wgsl.expected.hlsl
index fde2021..3dcf77f 100644
--- a/test/bug/tint/453.wgsl.expected.hlsl
+++ b/test/bug/tint/453.wgsl.expected.hlsl
@@ -8,7 +8,6 @@
   srcValue = x_22;
   const uint x_24 = srcValue.x;
   const uint x_25 = (x_24 + 1u);
-  const uint4 x_27 = srcValue;
-  Dst[int2(0, 0)] = x_27.xxxx;
+  Dst[int2(0, 0)] = srcValue.xxxx;
   return;
 }
diff --git a/test/bug/tint/534.wgsl.expected.hlsl b/test/bug/tint/534.wgsl.expected.hlsl
index 54c56dd..2c9ea16 100644
--- a/test/bug/tint/534.wgsl.expected.hlsl
+++ b/test/bug/tint/534.wgsl.expected.hlsl
@@ -43,18 +43,14 @@
     uint i = 0u;
     while (true) {
       const uint scalar_offset_1 = (12u) / 4;
-      if (!((i < uniforms[scalar_offset_1 / 4][scalar_offset_1 % 4]))) {
-        break;
-      }
+      if (!(!(!((i < uniforms[scalar_offset_1 / 4][scalar_offset_1 % 4]))))) { break; }
       Set_uint4(srcColorBits, i, ConvertToFp16FloatValue(srcColor[i]));
       bool tint_tmp_1 = success;
       if (tint_tmp_1) {
         tint_tmp_1 = (srcColorBits[i] == dstColorBits[i]);
       }
       success = (tint_tmp_1);
-      {
-        i = (i + 1u);
-      }
+      i = (i + 1u);
     }
   }
   uint outputIndex = ((GlobalInvocationID.y * uint(size.x)) + GlobalInvocationID.x);
diff --git a/test/bug/tint/744.wgsl.expected.hlsl b/test/bug/tint/744.wgsl.expected.hlsl
index d986a62..0314864 100644
--- a/test/bug/tint/744.wgsl.expected.hlsl
+++ b/test/bug/tint/744.wgsl.expected.hlsl
@@ -20,16 +20,10 @@
   uint result = 0u;
   {
     uint i = 0u;
-    while (true) {
-      if (!((i < dimInner))) {
-        break;
-      }
+    for(; !(!((i < dimInner))); i = (i + 1u)) {
       const uint a = (i + (resultCell.x * dimInner));
       const uint b = (resultCell.y + (i * dimOutter));
       result = (result + (firstMatrix.Load((4u * a)) * secondMatrix.Load((4u * b))));
-      {
-        i = (i + 1u);
-      }
     }
   }
   const uint index = (resultCell.y + (resultCell.x * dimOutter));
diff --git a/test/bug/tint/749.spvasm.expected.hlsl b/test/bug/tint/749.spvasm.expected.hlsl
index fe1e826..af27660 100644
--- a/test/bug/tint/749.spvasm.expected.hlsl
+++ b/test/bug/tint/749.spvasm.expected.hlsl
@@ -255,8 +255,7 @@
       const int x_983 = i_1;
       i_1 = 0;
       i_1 = x_983;
-      const int x_72 = j_1;
-      param_1 = x_72;
+      param_1 = j_1;
       const int x_984 = param_3;
       param_3 = 0;
       param_3 = x_984;
@@ -556,8 +555,7 @@
     const int x_1049 = top;
     top = 0;
     top = x_1049;
-    const int x_118 = l_1;
-    param_4 = x_118;
+    param_4 = l_1;
     const int x_1050 = stack.arr[x_110_save];
     stack.arr[x_110_save] = 0;
     stack.arr[x_110_save] = x_1050;
diff --git a/test/bug/tint/757.wgsl.expected.hlsl b/test/bug/tint/757.wgsl.expected.hlsl
index 67bbffb..72ed5bd 100644
--- a/test/bug/tint/757.wgsl.expected.hlsl
+++ b/test/bug/tint/757.wgsl.expected.hlsl
@@ -17,14 +17,8 @@
   float4 texel = myTexture.Load(int4(GlobalInvocationID.xy, 0, 0));
   {
     uint i = 0u;
-    while (true) {
-      if (!((i < 1u))) {
-        break;
-      }
+    for(; !(!((i < 1u))); i = (i + 1u)) {
       result.Store((4u * (flatIndex + i)), asuint(texel.r));
-      {
-        i = (i + 1u);
-      }
     }
   }
   return;
diff --git a/test/bug/tint/914.wgsl.expected.hlsl b/test/bug/tint/914.wgsl.expected.hlsl
index 4059091..7aef00e 100644
--- a/test/bug/tint/914.wgsl.expected.hlsl
+++ b/test/bug/tint/914.wgsl.expected.hlsl
@@ -100,14 +100,8 @@
   tint_array_wrapper_3 BCached = (tint_array_wrapper_3)0;
   {
     uint index = 0u;
-    while (true) {
-      if (!((index < (RowPerThread * ColPerThread)))) {
-        break;
-      }
+    for(; !(!((index < (RowPerThread * ColPerThread)))); index = (index + 1u)) {
       acc.arr[index] = 0.0f;
-      {
-        index = (index + 1u);
-      }
     }
   }
   const uint ColPerThreadA = (TileInner / 16u);
@@ -116,137 +110,71 @@
   const uint tileRowB = (local_id.y * RowPerThreadB);
   {
     uint t = 0u;
-    while (true) {
-      if (!((t < numTiles))) {
-        break;
-      }
+    for(; !(!((t < numTiles))); t = (t + 1u)) {
       {
         uint innerRow = 0u;
-        while (true) {
-          if (!((innerRow < RowPerThread))) {
-            break;
-          }
+        for(; !(!((innerRow < RowPerThread))); innerRow = (innerRow + 1u)) {
           {
             uint innerCol = 0u;
-            while (true) {
-              if (!((innerCol < ColPerThreadA))) {
-                break;
-              }
+            for(; !(!((innerCol < ColPerThreadA))); innerCol = (innerCol + 1u)) {
               const uint inputRow = (tileRow + innerRow);
               const uint inputCol = (tileColA + innerCol);
               mm_Asub.arr[inputRow].arr[inputCol] = mm_readA((globalRow + innerRow), ((t * TileInner) + inputCol));
-              {
-                innerCol = (innerCol + 1u);
-              }
             }
           }
-          {
-            innerRow = (innerRow + 1u);
-          }
         }
       }
       {
         uint innerRow = 0u;
-        while (true) {
-          if (!((innerRow < RowPerThreadB))) {
-            break;
-          }
+        for(; !(!((innerRow < RowPerThreadB))); innerRow = (innerRow + 1u)) {
           {
             uint innerCol = 0u;
-            while (true) {
-              if (!((innerCol < ColPerThread))) {
-                break;
-              }
+            for(; !(!((innerCol < ColPerThread))); innerCol = (innerCol + 1u)) {
               const uint inputRow = (tileRowB + innerRow);
               const uint inputCol = (tileCol + innerCol);
               mm_Bsub.arr[innerCol].arr[inputCol] = mm_readB(((t * TileInner) + inputRow), (globalCol + innerCol));
-              {
-                innerCol = (innerCol + 1u);
-              }
             }
           }
-          {
-            innerRow = (innerRow + 1u);
-          }
         }
       }
       GroupMemoryBarrierWithGroupSync();
       {
         uint k = 0u;
-        while (true) {
-          if (!((k < TileInner))) {
-            break;
-          }
+        for(; !(!((k < TileInner))); k = (k + 1u)) {
           {
             uint inner = 0u;
-            while (true) {
-              if (!((inner < ColPerThread))) {
-                break;
-              }
+            for(; !(!((inner < ColPerThread))); inner = (inner + 1u)) {
               BCached.arr[inner] = mm_Bsub.arr[k].arr[(tileCol + inner)];
-              {
-                inner = (inner + 1u);
-              }
             }
           }
           {
             uint innerRow = 0u;
-            while (true) {
-              if (!((innerRow < RowPerThread))) {
-                break;
-              }
+            for(; !(!((innerRow < RowPerThread))); innerRow = (innerRow + 1u)) {
               ACached = mm_Asub.arr[(tileRow + innerRow)].arr[k];
               {
                 uint innerCol = 0u;
-                while (true) {
-                  if (!((innerCol < ColPerThread))) {
-                    break;
-                  }
+                for(; !(!((innerCol < ColPerThread))); innerCol = (innerCol + 1u)) {
                   const uint index = ((innerRow * ColPerThread) + innerCol);
                   acc.arr[index] = (acc.arr[index] + (ACached * BCached.arr[innerCol]));
-                  {
-                    innerCol = (innerCol + 1u);
-                  }
                 }
               }
-              {
-                innerRow = (innerRow + 1u);
-              }
             }
           }
-          {
-            k = (k + 1u);
-          }
         }
       }
       GroupMemoryBarrierWithGroupSync();
-      {
-        t = (t + 1u);
-      }
     }
   }
   {
     uint innerRow = 0u;
-    while (true) {
-      if (!((innerRow < RowPerThread))) {
-        break;
-      }
+    for(; !(!((innerRow < RowPerThread))); innerRow = (innerRow + 1u)) {
       {
         uint innerCol = 0u;
-        while (true) {
-          if (!((innerCol < ColPerThread))) {
-            break;
-          }
+        for(; !(!((innerCol < ColPerThread))); innerCol = (innerCol + 1u)) {
           const uint index = ((innerRow * ColPerThread) + innerCol);
           mm_write((globalRow + innerRow), (globalCol + innerCol), acc.arr[index]);
-          {
-            innerCol = (innerCol + 1u);
-          }
         }
       }
-      {
-        innerRow = (innerRow + 1u);
-      }
     }
   }
   return;
diff --git a/test/bug/tint/922.wgsl.expected.hlsl b/test/bug/tint/922.wgsl.expected.hlsl
index cb96b2b..964eb97 100644
--- a/test/bug/tint/922.wgsl.expected.hlsl
+++ b/test/bug/tint/922.wgsl.expected.hlsl
@@ -65,37 +65,25 @@
 float3 Mat4x3GetCol0_(Mat4x3_ m) {
   Mat4x3_ m1 = (Mat4x3_)0;
   m1 = m;
-  const Mat4x3_ _e2 = m1;
-  const Mat4x3_ _e5 = m1;
-  const Mat4x3_ _e8 = m1;
-  return float3(_e2.mx.x, _e5.my.x, _e8.mz.x);
+  return float3(m1.mx.x, m1.my.x, m1.mz.x);
 }
 
 float3 Mat4x3GetCol1_(Mat4x3_ m2) {
   Mat4x3_ m3 = (Mat4x3_)0;
   m3 = m2;
-  const Mat4x3_ _e2 = m3;
-  const Mat4x3_ _e5 = m3;
-  const Mat4x3_ _e8 = m3;
-  return float3(_e2.mx.y, _e5.my.y, _e8.mz.y);
+  return float3(m3.mx.y, m3.my.y, m3.mz.y);
 }
 
 float3 Mat4x3GetCol2_(Mat4x3_ m4) {
   Mat4x3_ m5 = (Mat4x3_)0;
   m5 = m4;
-  const Mat4x3_ _e2 = m5;
-  const Mat4x3_ _e5 = m5;
-  const Mat4x3_ _e8 = m5;
-  return float3(_e2.mx.z, _e5.my.z, _e8.mz.z);
+  return float3(m5.mx.z, m5.my.z, m5.mz.z);
 }
 
 float3 Mat4x3GetCol3_(Mat4x3_ m6) {
   Mat4x3_ m7 = (Mat4x3_)0;
   m7 = m6;
-  const Mat4x3_ _e2 = m7;
-  const Mat4x3_ _e5 = m7;
-  const Mat4x3_ _e8 = m7;
-  return float3(_e2.mx.w, _e5.my.w, _e8.mz.w);
+  return float3(m7.mx.w, m7.my.w, m7.mz.w);
 }
 
 float4 Mul(Mat4x4_ m8, float4 v) {
@@ -103,15 +91,7 @@
   float4 v1 = float4(0.0f, 0.0f, 0.0f, 0.0f);
   m9 = m8;
   v1 = v;
-  const Mat4x4_ _e4 = m9;
-  const float4 _e6 = v1;
-  const Mat4x4_ _e8 = m9;
-  const float4 _e10 = v1;
-  const Mat4x4_ _e12 = m9;
-  const float4 _e14 = v1;
-  const Mat4x4_ _e16 = m9;
-  const float4 _e18 = v1;
-  return float4(dot(_e4.mx, _e6), dot(_e8.my, _e10), dot(_e12.mz, _e14), dot(_e16.mw, _e18));
+  return float4(dot(m9.mx, v1), dot(m9.my, v1), dot(m9.mz, v1), dot(m9.mw, v1));
 }
 
 float3 Mul1(Mat4x3_ m10, float4 v2) {
@@ -119,13 +99,7 @@
   float4 v3 = float4(0.0f, 0.0f, 0.0f, 0.0f);
   m11 = m10;
   v3 = v2;
-  const Mat4x3_ _e4 = m11;
-  const float4 _e6 = v3;
-  const Mat4x3_ _e8 = m11;
-  const float4 _e10 = v3;
-  const Mat4x3_ _e12 = m11;
-  const float4 _e14 = v3;
-  return float3(dot(_e4.mx, _e6), dot(_e8.my, _e10), dot(_e12.mz, _e14));
+  return float3(dot(m11.mx, v3), dot(m11.my, v3), dot(m11.mz, v3));
 }
 
 float2 Mul2(Mat4x2_ m12, float4 v4) {
@@ -133,11 +107,7 @@
   float4 v5 = float4(0.0f, 0.0f, 0.0f, 0.0f);
   m13 = m12;
   v5 = v4;
-  const Mat4x2_ _e4 = m13;
-  const float4 _e6 = v5;
-  const Mat4x2_ _e8 = m13;
-  const float4 _e10 = v5;
-  return float2(dot(_e4.mx, _e6), dot(_e8.my, _e10));
+  return float2(dot(m13.mx, v5), dot(m13.my, v5));
 }
 
 float4 Mul3(float3 v6, Mat4x3_ m14) {
@@ -145,35 +115,25 @@
   Mat4x3_ m15 = (Mat4x3_)0;
   v7 = v6;
   m15 = m14;
-  const Mat4x3_ _e5 = m15;
-  const float3 _e6 = Mat4x3GetCol0_(_e5);
+  const float3 _e6 = Mat4x3GetCol0_(m15);
   const float3 _e7 = v7;
-  const Mat4x3_ _e10 = m15;
-  const float3 _e11 = Mat4x3GetCol1_(_e10);
+  const float3 _e11 = Mat4x3GetCol1_(m15);
   const float3 _e12 = v7;
-  const Mat4x3_ _e15 = m15;
-  const float3 _e16 = Mat4x3GetCol2_(_e15);
+  const float3 _e16 = Mat4x3GetCol2_(m15);
   const float3 _e17 = v7;
-  const Mat4x3_ _e20 = m15;
-  const float3 _e21 = Mat4x3GetCol3_(_e20);
-  const float3 _e22 = v7;
-  return float4(dot(_e6, _e7), dot(_e11, _e12), dot(_e16, _e17), dot(_e21, _e22));
+  const float3 _e21 = Mat4x3GetCol3_(m15);
+  return float4(dot(_e6, _e7), dot(_e11, _e12), dot(_e16, _e17), dot(_e21, v7));
 }
 
 Mat4x4_ _Mat4x4_(float n) {
   float n1 = 0.0f;
   Mat4x4_ o = (Mat4x4_)0;
   n1 = n;
-  const float _e4 = n1;
-  o.mx = float4(_e4, 0.0f, 0.0f, 0.0f);
-  const float _e11 = n1;
-  o.my = float4(0.0f, _e11, 0.0f, 0.0f);
-  const float _e18 = n1;
-  o.mz = float4(0.0f, 0.0f, _e18, 0.0f);
-  const float _e25 = n1;
-  o.mw = float4(0.0f, 0.0f, 0.0f, _e25);
-  const Mat4x4_ _e27 = o;
-  return _e27;
+  o.mx = float4(n1, 0.0f, 0.0f, 0.0f);
+  o.my = float4(0.0f, n1, 0.0f, 0.0f);
+  o.mz = float4(0.0f, 0.0f, n1, 0.0f);
+  o.mw = float4(0.0f, 0.0f, 0.0f, n1);
+  return o;
 }
 
 Mat4x4_ _Mat4x4_1(Mat4x3_ m16) {
@@ -182,14 +142,10 @@
   m17 = m16;
   const Mat4x4_ _e4 = _Mat4x4_(1.0f);
   o1 = _e4;
-  const Mat4x3_ _e7 = m17;
-  o1.mx = _e7.mx;
-  const Mat4x3_ _e10 = m17;
-  o1.my = _e10.my;
-  const Mat4x3_ _e13 = m17;
-  o1.mz = _e13.mz;
-  const Mat4x4_ _e15 = o1;
-  return _e15;
+  o1.mx = m17.mx;
+  o1.my = m17.my;
+  o1.mz = m17.mz;
+  return o1;
 }
 
 Mat4x4_ _Mat4x4_2(Mat4x2_ m18) {
@@ -198,75 +154,55 @@
   m19 = m18;
   const Mat4x4_ _e4 = _Mat4x4_(1.0f);
   o2 = _e4;
-  const Mat4x2_ _e7 = m19;
-  o2.mx = _e7.mx;
-  const Mat4x2_ _e10 = m19;
-  o2.my = _e10.my;
-  const Mat4x4_ _e12 = o2;
-  return _e12;
+  o2.mx = m19.mx;
+  o2.my = m19.my;
+  return o2;
 }
 
 Mat4x3_ _Mat4x3_(float n2) {
   float n3 = 0.0f;
   Mat4x3_ o3 = (Mat4x3_)0;
   n3 = n2;
-  const float _e4 = n3;
-  o3.mx = float4(_e4, 0.0f, 0.0f, 0.0f);
-  const float _e11 = n3;
-  o3.my = float4(0.0f, _e11, 0.0f, 0.0f);
-  const float _e18 = n3;
-  o3.mz = float4(0.0f, 0.0f, _e18, 0.0f);
-  const Mat4x3_ _e21 = o3;
-  return _e21;
+  o3.mx = float4(n3, 0.0f, 0.0f, 0.0f);
+  o3.my = float4(0.0f, n3, 0.0f, 0.0f);
+  o3.mz = float4(0.0f, 0.0f, n3, 0.0f);
+  return o3;
 }
 
 Mat4x3_ _Mat4x3_1(Mat4x4_ m20) {
   Mat4x4_ m21 = (Mat4x4_)0;
   Mat4x3_ o4 = (Mat4x3_)0;
   m21 = m20;
-  const Mat4x4_ _e4 = m21;
-  o4.mx = _e4.mx;
-  const Mat4x4_ _e7 = m21;
-  o4.my = _e7.my;
-  const Mat4x4_ _e10 = m21;
-  o4.mz = _e10.mz;
-  const Mat4x3_ _e12 = o4;
-  return _e12;
+  o4.mx = m21.mx;
+  o4.my = m21.my;
+  o4.mz = m21.mz;
+  return o4;
 }
 
 void main1() {
   Mat4x3_ t_PosMtx = (Mat4x3_)0;
   float2 t_TexSpaceCoord = float2(0.0f, 0.0f);
-  const float _e15 = a_PosMtxIdx1;
-  const Mat4x3_ _e18 = tint_symbol_5(global2, (48u * uint(int(_e15))));
+  const Mat4x3_ _e18 = tint_symbol_5(global2, (48u * uint(int(a_PosMtxIdx1))));
   t_PosMtx = _e18;
-  const Mat4x3_ _e23 = t_PosMtx;
-  const Mat4x4_ _e24 = _Mat4x4_1(_e23);
+  const Mat4x4_ _e24 = _Mat4x4_1(t_PosMtx);
   const float3 _e25 = a_Position1;
-  const Mat4x3_ _e29 = t_PosMtx;
-  const Mat4x4_ _e30 = _Mat4x4_1(_e29);
-  const float3 _e31 = a_Position1;
-  const float4 _e34 = Mul(_e30, float4(_e31, 1.0f));
+  const Mat4x4_ _e30 = _Mat4x4_1(t_PosMtx);
+  const float4 _e34 = Mul(_e30, float4(a_Position1, 1.0f));
   const Mat4x4_ _e35 = tint_symbol_7(global, 0u);
-  const Mat4x3_ _e37 = t_PosMtx;
-  const Mat4x4_ _e38 = _Mat4x4_1(_e37);
+  const Mat4x4_ _e38 = _Mat4x4_1(t_PosMtx);
   const float3 _e39 = a_Position1;
-  const Mat4x3_ _e43 = t_PosMtx;
-  const Mat4x4_ _e44 = _Mat4x4_1(_e43);
-  const float3 _e45 = a_Position1;
-  const float4 _e48 = Mul(_e44, float4(_e45, 1.0f));
+  const Mat4x4_ _e44 = _Mat4x4_1(t_PosMtx);
+  const float4 _e48 = Mul(_e44, float4(a_Position1, 1.0f));
   const float4 _e49 = Mul(_e35, _e48);
   gl_Position = _e49;
-  const float4 _e50 = a_Color1;
-  v_Color = _e50;
+  v_Color = a_Color1;
   const uint scalar_offset_9 = (32u) / 4;
   const float4 _e52 = asfloat(global1[scalar_offset_9 / 4]);
   if ((_e52.x == 2.0f)) {
     {
       const float3 _e59 = a_Normal1;
       const Mat4x2_ _e64 = tint_symbol_9(global1, (32u * uint(0)));
-      const float3 _e65 = a_Normal1;
-      const float2 _e68 = Mul2(_e64, float4(_e65, 1.0f));
+      const float2 _e68 = Mul2(_e64, float4(a_Normal1, 1.0f));
       v_TexCoord = _e68.xy;
       return;
     }
@@ -274,8 +210,7 @@
     {
       const float2 _e73 = a_UV1;
       const Mat4x2_ _e79 = tint_symbol_9(global1, (32u * uint(0)));
-      const float2 _e80 = a_UV1;
-      const float2 _e84 = Mul2(_e79, float4(_e80, 1.0f, 1.0f));
+      const float2 _e84 = Mul2(_e79, float4(a_UV1, 1.0f, 1.0f));
       v_TexCoord = _e84.xy;
       return;
     }
@@ -307,10 +242,7 @@
   a_Normal1 = a_Normal;
   a_PosMtxIdx1 = a_PosMtxIdx;
   main1();
-  const float4 _e11 = v_Color;
-  const float2 _e13 = v_TexCoord;
-  const float4 _e15 = gl_Position;
-  const VertexOutput tint_symbol_3 = {_e11, _e13, _e15};
+  const VertexOutput tint_symbol_3 = {v_Color, v_TexCoord, gl_Position};
   const tint_symbol_2 tint_symbol_13 = {tint_symbol_3.v_Color, tint_symbol_3.v_TexCoord, tint_symbol_3.member};
   return tint_symbol_13;
 }
diff --git a/test/bug/tint/943.spvasm.expected.hlsl b/test/bug/tint/943.spvasm.expected.hlsl
index 8751dc5..0bf03e3 100644
--- a/test/bug/tint/943.spvasm.expected.hlsl
+++ b/test/bug/tint/943.spvasm.expected.hlsl
@@ -41,8 +41,7 @@
     x_87 = all((x_84 < x_85));
     x_88_phi = x_87;
   }
-  const bool x_88 = x_88_phi;
-  return x_88;
+  return x_88_phi;
 }
 
 float mm_readA_i1_i1_(inout int row, inout int col) {
@@ -73,8 +72,7 @@
   } else {
     x_430 = 0.0f;
   }
-  const float x_450 = x_430;
-  return x_450;
+  return x_430;
 }
 
 float mm_readB_i1_i1_(inout int row_1, inout int col_1) {
@@ -105,8 +103,7 @@
   } else {
     x_468 = 0.0f;
   }
-  const float x_487 = x_468;
-  return x_487;
+  return x_468;
 }
 
 int getOutputFlatIndex_vi3_(inout int3 coords) {
@@ -136,8 +133,7 @@
   param = int3(x_115, x_116, x_117);
   const int x_120 = getOutputFlatIndex_vi3_(param);
   flatIndex_1 = x_120;
-  const int x_122 = flatIndex_1;
-  param_1 = x_122;
+  param_1 = flatIndex_1;
   const float x_124 = value_1;
   param_2 = x_124;
   setOutput_i1_f1_(param_1, param_2);
@@ -154,8 +150,7 @@
   const int x_492 = row_2;
   const int x_493 = col_2;
   outCoord = int3(x_491, x_492, x_493);
-  const int x_496 = batch;
-  param_14 = x_496;
+  param_14 = batch;
   const int x_498 = row_2;
   param_15 = x_498;
   const int x_500 = col_2;
@@ -216,30 +211,10 @@
   const int x_152 = dimInner;
   numTiles = (((x_152 - 1) / 64) + 1);
   innerRow = 0;
-  while (true) {
-    const int x_163 = innerRow;
-    if ((x_163 < 1)) {
-    } else {
-      break;
-    }
+  for(; (innerRow < 1); innerRow = (innerRow + 1)) {
     innerCol = 0;
-    while (true) {
-      const int x_171 = innerCol;
-      if ((x_171 < 1)) {
-      } else {
-        break;
-      }
-      const int x_177 = innerRow;
-      const int x_178 = innerCol;
-      acc.arr[x_177].arr[x_178] = 0.0f;
-      {
-        const int x_181 = innerCol;
-        innerCol = (x_181 + 1);
-      }
-    }
-    {
-      const int x_183 = innerRow;
-      innerRow = (x_183 + 1);
+    for(; (innerCol < 1); innerCol = (innerCol + 1)) {
+      acc.arr[innerRow].arr[innerCol] = 0.0f;
     }
   }
   const uint x_187 = gl_LocalInvocationID.x;
@@ -247,179 +222,72 @@
   const uint x_192 = gl_LocalInvocationID.y;
   tileRowB = (asint(x_192) * 1);
   t = 0;
-  while (true) {
-    const int x_201 = t;
-    const int x_202 = numTiles;
-    if ((x_201 < x_202)) {
-    } else {
-      break;
-    }
+  for(; (t < numTiles); t = (t + 1)) {
     innerRow_1 = 0;
-    while (true) {
-      const int x_210 = innerRow_1;
-      if ((x_210 < 1)) {
-      } else {
-        break;
-      }
+    for(; (innerRow_1 < 1); innerRow_1 = (innerRow_1 + 1)) {
       innerCol_1 = 0;
-      while (true) {
-        const int x_218 = innerCol_1;
-        if ((x_218 < 64)) {
-        } else {
-          break;
-        }
-        const int x_221 = tileRow;
-        const int x_222 = innerRow_1;
-        inputRow = (x_221 + x_222);
-        const int x_225 = tileColA;
-        const int x_226 = innerCol_1;
-        inputCol = (x_225 + x_226);
+      for(; (innerCol_1 < 64); innerCol_1 = (innerCol_1 + 1)) {
+        inputRow = (tileRow + innerRow_1);
+        inputCol = (tileColA + innerCol_1);
         const int x_233 = inputRow;
         const int x_234 = inputCol;
-        const int x_235 = globalRow;
-        const int x_236 = innerRow_1;
         const int x_238 = t;
         const int x_240 = inputCol;
-        param_3 = (x_235 + x_236);
+        param_3 = (globalRow + innerRow_1);
         param_4 = ((x_238 * 64) + x_240);
         const float x_244 = mm_readA_i1_i1_(param_3, param_4);
         mm_Asub.arr[x_233].arr[x_234] = x_244;
-        {
-          const int x_247 = innerCol_1;
-          innerCol_1 = (x_247 + 1);
-        }
-      }
-      {
-        const int x_249 = innerRow_1;
-        innerRow_1 = (x_249 + 1);
       }
     }
     innerRow_2 = 0;
-    while (true) {
-      const int x_257 = innerRow_2;
-      if ((x_257 < 1)) {
-      } else {
-        break;
-      }
+    for(; (innerRow_2 < 1); innerRow_2 = (innerRow_2 + 1)) {
       innerCol_2 = 0;
-      while (true) {
-        const int x_265 = innerCol_2;
-        if ((x_265 < 1)) {
-        } else {
-          break;
-        }
-        const int x_268 = tileRowB;
-        const int x_269 = innerRow_2;
-        inputRow_1 = (x_268 + x_269);
-        const int x_272 = tileCol;
-        const int x_273 = innerCol_2;
-        inputCol_1 = (x_272 + x_273);
+      for(; (innerCol_2 < 1); innerCol_2 = (innerCol_2 + 1)) {
+        inputRow_1 = (tileRowB + innerRow_2);
+        inputCol_1 = (tileCol + innerCol_2);
         const int x_278 = inputRow_1;
         const int x_279 = inputCol_1;
-        const int x_280 = t;
-        const int x_282 = inputRow_1;
         const int x_284 = globalCol;
         const int x_285 = innerCol_2;
-        param_5 = ((x_280 * 64) + x_282);
+        param_5 = ((t * 64) + inputRow_1);
         param_6 = (x_284 + x_285);
         const float x_289 = mm_readB_i1_i1_(param_5, param_6);
         mm_Bsub.arr[x_278].arr[x_279] = x_289;
-        {
-          const int x_291 = innerCol_2;
-          innerCol_2 = (x_291 + 1);
-        }
-      }
-      {
-        const int x_293 = innerRow_2;
-        innerRow_2 = (x_293 + 1);
       }
     }
     GroupMemoryBarrierWithGroupSync();
     k = 0;
-    while (true) {
-      const int x_302 = k;
-      if ((x_302 < 64)) {
-      } else {
-        break;
-      }
+    for(; (k < 64); k = (k + 1)) {
       inner = 0;
-      while (true) {
-        const int x_310 = inner;
-        if ((x_310 < 1)) {
-        } else {
-          break;
-        }
+      for(; (inner < 1); inner = (inner + 1)) {
         const int x_314 = inner;
-        const int x_315 = k;
-        const int x_316 = tileCol;
-        const int x_317 = inner;
-        const float x_320 = mm_Bsub.arr[x_315].arr[(x_316 + x_317)];
+        const float x_320 = mm_Bsub.arr[k].arr[(tileCol + inner)];
         BCached.arr[x_314] = x_320;
-        {
-          const int x_322 = inner;
-          inner = (x_322 + 1);
-        }
       }
       innerRow_3 = 0;
-      while (true) {
-        const int x_330 = innerRow_3;
-        if ((x_330 < 1)) {
-        } else {
-          break;
-        }
-        const int x_333 = tileRow;
-        const int x_334 = innerRow_3;
-        const int x_336 = k;
-        const float x_338 = mm_Asub.arr[(x_333 + x_334)].arr[x_336];
+      for(; (innerRow_3 < 1); innerRow_3 = (innerRow_3 + 1)) {
+        const float x_338 = mm_Asub.arr[(tileRow + innerRow_3)].arr[k];
         ACached = x_338;
         innerCol_3 = 0;
-        while (true) {
-          const int x_345 = innerCol_3;
-          if ((x_345 < 1)) {
-          } else {
-            break;
-          }
+        for(; (innerCol_3 < 1); innerCol_3 = (innerCol_3 + 1)) {
           const int x_347 = innerRow_3;
           const int x_348 = innerCol_3;
           const float x_349 = ACached;
-          const int x_350 = innerCol_3;
-          const float x_352 = BCached.arr[x_350];
+          const float x_352 = BCached.arr[innerCol_3];
           const float x_355 = acc.arr[x_347].arr[x_348];
           acc.arr[x_347].arr[x_348] = (x_355 + (x_349 * x_352));
-          {
-            const int x_358 = innerCol_3;
-            innerCol_3 = (x_358 + 1);
-          }
         }
-        {
-          const int x_360 = innerRow_3;
-          innerRow_3 = (x_360 + 1);
-        }
-      }
-      {
-        const int x_362 = k;
-        k = (x_362 + 1);
       }
     }
     GroupMemoryBarrierWithGroupSync();
-    {
-      const int x_364 = t;
-      t = (x_364 + 1);
-    }
   }
   innerRow_4 = 0;
-  while (true) {
-    const int x_372 = innerRow_4;
-    if ((x_372 < 1)) {
-    } else {
-      break;
-    }
+  for(; (innerRow_4 < 1); innerRow_4 = (innerRow_4 + 1)) {
     innerCol_4 = 0;
     while (true) {
       bool x_393 = false;
       bool x_394_phi = false;
-      const int x_380 = innerCol_4;
-      if ((x_380 < 1)) {
+      if ((innerCol_4 < 1)) {
       } else {
         break;
       }
@@ -435,29 +303,21 @@
         x_393 = ((x_389 + x_390) < x_392);
         x_394_phi = x_393;
       }
-      const bool x_394 = x_394_phi;
-      if (x_394) {
-        const int x_397 = globalRow;
-        const int x_398 = innerRow_4;
+      if (x_394_phi) {
         const int x_400 = globalCol;
         const int x_401 = innerCol_4;
         const int x_403 = innerRow_4;
         const int x_404 = innerCol_4;
-        param_7 = (x_397 + x_398);
+        param_7 = (globalRow + innerRow_4);
         param_8 = (x_400 + x_401);
         const float x_409 = acc.arr[x_403].arr[x_404];
         param_9 = x_409;
         mm_write_i1_i1_f1_(param_7, param_8, param_9);
       }
       {
-        const int x_411 = innerCol_4;
-        innerCol_4 = (x_411 + 1);
+        innerCol_4 = (innerCol_4 + 1);
       }
     }
-    {
-      const int x_413 = innerRow_4;
-      innerRow_4 = (x_413 + 1);
-    }
   }
   return;
 }
@@ -477,12 +337,9 @@
   dimBOuter_1 = x_75;
   const uint x_505 = gl_GlobalInvocationID.z;
   batch = asint(x_505);
-  const int x_508 = dimAOuter_1;
-  param_18 = x_508;
-  const int x_510 = dimInner_1;
-  param_19 = x_510;
-  const int x_512 = dimBOuter_1;
-  param_20 = x_512;
+  param_18 = dimAOuter_1;
+  param_19 = dimInner_1;
+  param_20 = dimBOuter_1;
   mm_matMul_i1_i1_i1_(param_18, param_19, param_20);
   return;
 }
diff --git a/test/bug/tint/948.wgsl.expected.hlsl b/test/bug/tint/948.wgsl.expected.hlsl
index f852d43..2454c3b 100644
--- a/test/bug/tint/948.wgsl.expected.hlsl
+++ b/test/bug/tint/948.wgsl.expected.hlsl
@@ -25,12 +25,9 @@
   const uint scalar_offset = (108u) / 4;
   const float x_25 = asfloat(x_20[scalar_offset / 4][scalar_offset % 4]);
   fX = (x_15 / x_25);
-  const float x_37 = fX;
-  const float4 x_40 = frameMapTexture.SampleBias(frameMapSampler, float2(x_37, 0.0f), 0.0f);
-  const float x_44 = fX;
-  const float4 x_47 = frameMapTexture.SampleBias(frameMapSampler, float2(x_44, 0.25f), 0.0f);
-  const float x_51 = fX;
-  const float4 x_54 = frameMapTexture.SampleBias(frameMapSampler, float2(x_51, 0.5f), 0.0f);
+  const float4 x_40 = frameMapTexture.SampleBias(frameMapSampler, float2(fX, 0.0f), 0.0f);
+  const float4 x_47 = frameMapTexture.SampleBias(frameMapSampler, float2(fX, 0.25f), 0.0f);
+  const float4 x_54 = frameMapTexture.SampleBias(frameMapSampler, float2(fX, 0.5f), 0.0f);
   return float4x4(float4(x_40.x, x_40.y, x_40.z, x_40.w), float4(x_47.x, x_47.y, x_47.z, x_47.w), float4(x_54.x, x_54.y, x_54.z, x_54.w), float4(float4(0.0f, 0.0f, 0.0f, 0.0f).x, float4(0.0f, 0.0f, 0.0f, 0.0f).y, float4(0.0f, 0.0f, 0.0f, 0.0f).z, float4(0.0f, 0.0f, 0.0f, 0.0f).w));
 }
 
@@ -54,12 +51,10 @@
   float alpha = 0.0f;
   float3 mixed = float3(0.0f, 0.0f, 0.0f);
   color = float4(0.0f, 0.0f, 0.0f, 0.0f);
-  const float2 x_86 = tUV;
-  tileUV = frac(x_86);
+  tileUV = frac(tUV);
   const float x_91 = tileUV.y;
   tileUV.y = (1.0f - x_91);
-  const float2 x_95 = tUV;
-  tileID = floor(x_95);
+  tileID = floor(tUV);
   const uint scalar_offset_1 = (96u) / 4;
   uint4 ubo_load = x_20[scalar_offset_1 / 4];
   const float2 x_101 = asfloat(((scalar_offset_1 & 2) ? ubo_load.zw : ubo_load.xy));
@@ -72,14 +67,8 @@
   const float2 x_111 = asfloat(((scalar_offset_3 & 2) ? ubo_load_1.zw : ubo_load_1.xy));
   stageUnits = (float2(1.0f, 1.0f) / x_111);
   i = 0;
-  while (true) {
-    const int x_122 = i;
-    if ((x_122 < 2)) {
-    } else {
-      break;
-    }
-    const int x_126 = i;
-    switch(x_126) {
+  for(; (i < 2); i = (i + 1)) {
+    switch(i) {
       case 1: {
         const float2 x_150 = tileID;
         const uint scalar_offset_4 = (88u) / 4;
@@ -114,15 +103,9 @@
       const float x_184 = animationData.z;
       mt = ((x_181 * x_184) % 1.0f);
       f = 0.0f;
-      while (true) {
-        const float x_193 = f;
-        if ((x_193 < 8.0f)) {
-        } else {
-          break;
-        }
+      for(; (f < 8.0f); f = (f + 1.0f)) {
         const float x_197 = animationData.y;
-        const float x_198 = mt;
-        if ((x_197 > x_198)) {
+        if ((x_197 > mt)) {
           const float x_203 = animationData.x;
           frameID_1 = x_203;
           break;
@@ -130,17 +113,11 @@
         const float x_208 = frameID_1;
         const uint scalar_offset_8 = (108u) / 4;
         const float x_211 = asfloat(x_20[scalar_offset_8 / 4][scalar_offset_8 % 4]);
-        const float x_214 = f;
-        const float4 x_217 = animationMapTexture.SampleBias(animationMapSampler, float2(((x_208 + 0.5f) / x_211), (0.125f * x_214)), 0.0f);
+        const float4 x_217 = animationMapTexture.SampleBias(animationMapSampler, float2(((x_208 + 0.5f) / x_211), (0.125f * f)), 0.0f);
         animationData = x_217;
-        {
-          const float x_218 = f;
-          f = (x_218 + 1.0f);
-        }
       }
     }
-    const float x_222 = frameID_1;
-    param = (x_222 + 0.5f);
+    param = (frameID_1 + 0.5f);
     const float4x4 x_225 = getFrameData_f1_(param);
     frameData = x_225;
     const float4 x_228 = frameData[0];
@@ -149,8 +126,7 @@
     const float2 x_231 = asfloat(((scalar_offset_9 & 2) ? ubo_load_4.zw : ubo_load_4.xy));
     frameSize = (float2(x_228.w, x_228.z) / x_231);
     const float4 x_235 = frameData[0];
-    const float2 x_237 = sheetUnits;
-    offset_1 = (float2(x_235.x, x_235.y) * x_237);
+    offset_1 = (float2(x_235.x, x_235.y) * sheetUnits);
     const float4 x_241 = frameData[2];
     const float4 x_244 = frameData[0];
     ratio = (float2(x_241.x, x_241.y) / float2(x_244.w, x_244.z));
@@ -159,18 +135,11 @@
       const float2 x_252 = tileUV;
       tileUV = float2(x_252.y, x_252.x);
     }
-    const int x_254 = i;
-    if ((x_254 == 0)) {
-      const float2 x_263 = tileUV;
-      const float2 x_264 = frameSize;
-      const float2 x_266 = offset_1;
-      const float4 x_268 = spriteSheetTexture.Sample(spriteSheetSampler, ((x_263 * x_264) + x_266));
+    if ((i == 0)) {
+      const float4 x_268 = spriteSheetTexture.Sample(spriteSheetSampler, ((tileUV * frameSize) + offset_1));
       color = x_268;
     } else {
-      const float2 x_274 = tileUV;
-      const float2 x_275 = frameSize;
-      const float2 x_277 = offset_1;
-      const float4 x_279 = spriteSheetTexture.Sample(spriteSheetSampler, ((x_274 * x_275) + x_277));
+      const float4 x_279 = spriteSheetTexture.Sample(spriteSheetSampler, ((tileUV * frameSize) + offset_1));
       nc = x_279;
       const float x_283 = color.w;
       const float x_285 = nc.w;
@@ -180,22 +149,15 @@
       const float x_295 = nc.w;
       mixed = lerp(float3(x_290.x, x_290.y, x_290.z), float3(x_292.x, x_292.y, x_292.z), float3(x_295, x_295, x_295));
       const float3 x_298 = mixed;
-      const float x_299 = alpha;
-      color = float4(x_298.x, x_298.y, x_298.z, x_299);
-    }
-    {
-      const int x_304 = i;
-      i = (x_304 + 1);
+      color = float4(x_298.x, x_298.y, x_298.z, alpha);
     }
   }
   const uint scalar_offset_10 = (112u) / 4;
   const float3 x_310 = asfloat(x_20[scalar_offset_10 / 4].xyz);
   const float4 x_311 = color;
   const float3 x_313 = (float3(x_311.x, x_311.y, x_311.z) * x_310);
-  const float4 x_314 = color;
-  color = float4(x_313.x, x_313.y, x_313.z, x_314.w);
-  const float4 x_318 = color;
-  glFragColor = x_318;
+  color = float4(x_313.x, x_313.y, x_313.z, color.w);
+  glFragColor = color;
   return;
 }
 
diff --git a/test/bug/tint/949.wgsl.expected.hacked.hlsl b/test/bug/tint/949.wgsl.expected.hacked.hlsl
new file mode 100644
index 0000000..8d446b9
--- /dev/null
+++ b/test/bug/tint/949.wgsl.expected.hacked.hlsl
@@ -0,0 +1,433 @@
+struct lightingInfo {
+  float3 diffuse;
+  float3 specular;
+};
+
+static float u_Float = 0.0f;
+static float3 u_Color = float3(0.0f, 0.0f, 0.0f);
+Texture2D<float4> TextureSamplerTexture : register(t1, space2);
+SamplerState TextureSamplerSampler : register(s0, space2);
+static float2 vMainuv = float2(0.0f, 0.0f);
+cbuffer cbuffer_x_269 : register(b6, space2) {
+  uint4 x_269[11];
+};
+static float4 v_output1 = float4(0.0f, 0.0f, 0.0f, 0.0f);
+static bool gl_FrontFacing = false;
+static float2 v_uv = float2(0.0f, 0.0f);
+static float4 v_output2 = float4(0.0f, 0.0f, 0.0f, 0.0f);
+Texture2D<float4> TextureSampler1Texture : register(t3, space2);
+SamplerState TextureSampler1Sampler : register(s2, space2);
+cbuffer cbuffer_light0 : register(b5, space0) {
+  uint4 light0[6];
+};
+static float4 glFragColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
+SamplerState bumpSamplerSampler : register(s4, space2);
+Texture2D<float4> bumpSamplerTexture : register(t5, space2);
+
+float3x3 cotangent_frame_vf3_vf3_vf2_vf2_(inout float3 normal_1, inout float3 p, inout float2 uv, inout float2 tangentSpaceParams) {
+  float3 dp1 = float3(0.0f, 0.0f, 0.0f);
+  float3 dp2 = float3(0.0f, 0.0f, 0.0f);
+  float2 duv1 = float2(0.0f, 0.0f);
+  float2 duv2 = float2(0.0f, 0.0f);
+  float3 dp2perp = float3(0.0f, 0.0f, 0.0f);
+  float3 dp1perp = float3(0.0f, 0.0f, 0.0f);
+  float3 tangent = float3(0.0f, 0.0f, 0.0f);
+  float3 bitangent = float3(0.0f, 0.0f, 0.0f);
+  float invmax = 0.0f;
+  const float3 x_133 = p;
+  dp1 = ddx(x_133);
+  const float3 x_136 = p;
+  dp2 = ddy(x_136);
+  const float2 x_139 = uv;
+  duv1 = ddx(x_139);
+  const float2 x_142 = uv;
+  duv2 = ddy(x_142);
+  const float3 x_145 = dp2;
+  const float3 x_146 = normal_1;
+  dp2perp = cross(x_145, x_146);
+  const float3 x_149 = normal_1;
+  const float3 x_150 = dp1;
+  dp1perp = cross(x_149, x_150);
+  const float3 x_153 = dp2perp;
+  const float x_155 = duv1.x;
+  const float3 x_157 = dp1perp;
+  const float x_159 = duv2.x;
+  tangent = ((x_153 * x_155) + (x_157 * x_159));
+  const float3 x_163 = dp2perp;
+  const float x_165 = duv1.y;
+  const float3 x_167 = dp1perp;
+  const float x_169 = duv2.y;
+  bitangent = ((x_163 * x_165) + (x_167 * x_169));
+  const float x_173 = tangentSpaceParams.x;
+  const float3 x_174 = tangent;
+  tangent = (x_174 * x_173);
+  const float x_177 = tangentSpaceParams.y;
+  const float3 x_178 = bitangent;
+  bitangent = (x_178 * x_177);
+  const float3 x_181 = tangent;
+  const float3 x_182 = tangent;
+  const float3 x_184 = bitangent;
+  const float3 x_185 = bitangent;
+  invmax = rsqrt(max(dot(x_181, x_182), dot(x_184, x_185)));
+  const float3 x_189 = tangent;
+  const float x_190 = invmax;
+  const float3 x_191 = (x_189 * x_190);
+  const float3 x_192 = bitangent;
+  const float x_193 = invmax;
+  const float3 x_194 = (x_192 * x_193);
+  const float3 x_195 = normal_1;
+  return float3x3(float3(x_191.x, x_191.y, x_191.z), float3(x_194.x, x_194.y, x_194.z), float3(x_195.x, x_195.y, x_195.z));
+}
+
+float3x3 transposeMat3_mf33_(inout float3x3 inMatrix) {
+  float3 i0 = float3(0.0f, 0.0f, 0.0f);
+  float3 i1 = float3(0.0f, 0.0f, 0.0f);
+  float3 i2 = float3(0.0f, 0.0f, 0.0f);
+  float3x3 outMatrix = float3x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+  const float3 x_60 = inMatrix[0];
+  i0 = x_60;
+  const float3 x_64 = inMatrix[1];
+  i1 = x_64;
+  const float3 x_68 = inMatrix[2];
+  i2 = x_68;
+  const float x_73 = i0.x;
+  const float x_75 = i1.x;
+  const float x_77 = i2.x;
+  const float3 x_78 = float3(x_73, x_75, x_77);
+  const float x_81 = i0.y;
+  const float x_83 = i1.y;
+  const float x_85 = i2.y;
+  const float3 x_86 = float3(x_81, x_83, x_85);
+  const float x_89 = i0.z;
+  const float x_91 = i1.z;
+  const float x_93 = i2.z;
+  const float3 x_94 = float3(x_89, x_91, x_93);
+  outMatrix = float3x3(float3(x_78.x, x_78.y, x_78.z), float3(x_86.x, x_86.y, x_86.z), float3(x_94.x, x_94.y, x_94.z));
+  const float3x3 x_110 = outMatrix;
+  return x_110;
+}
+
+float3 perturbNormalBase_mf33_vf3_f1_(inout float3x3 cotangentFrame, inout float3 normal, inout float scale) {
+  const float3x3 x_113 = cotangentFrame;
+  const float3 x_114 = normal;
+  return normalize(mul(x_114, x_113));
+}
+
+float3 perturbNormal_mf33_vf3_f1_(inout float3x3 cotangentFrame_1, inout float3 textureSample, inout float scale_1) {
+  float3x3 param = float3x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+  float3 param_1 = float3(0.0f, 0.0f, 0.0f);
+  float param_2 = 0.0f;
+  const float3 x_119 = textureSample;
+  const float3x3 x_125 = cotangentFrame_1;
+  param = x_125;
+  param_1 = ((x_119 * 2.0f) - float3(1.0f, 1.0f, 1.0f));
+  const float x_128 = scale_1;
+  param_2 = x_128;
+  const float3 x_129 = perturbNormalBase_mf33_vf3_f1_(param, param_1, param_2);
+  return x_129;
+}
+
+lightingInfo computeHemisphericLighting_vf3_vf3_vf4_vf3_vf3_vf3_f1_(inout float3 viewDirectionW, inout float3 vNormal, inout float4 lightData, inout float3 diffuseColor, inout float3 specularColor, inout float3 groundColor, inout float glossiness) {
+  float ndl = 0.0f;
+  lightingInfo result = {float3(0.0f, 0.0f, 0.0f), float3(0.0f, 0.0f, 0.0f)};
+  float3 angleW = float3(0.0f, 0.0f, 0.0f);
+  float specComp = 0.0f;
+  const float3 x_212 = vNormal;
+  const float4 x_213 = lightData;
+  ndl = ((dot(x_212, float3(x_213.x, x_213.y, x_213.z)) * 0.5f) + 0.5f);
+  const float3 x_220 = groundColor;
+  const float3 x_221 = diffuseColor;
+  const float x_222 = ndl;
+  result.diffuse = lerp(x_220, x_221, float3(x_222, x_222, x_222));
+  const float3 x_227 = viewDirectionW;
+  const float4 x_228 = lightData;
+  angleW = normalize((x_227 + float3(x_228.x, x_228.y, x_228.z)));
+  const float3 x_233 = vNormal;
+  const float3 x_234 = angleW;
+  specComp = max(0.0f, dot(x_233, x_234));
+  const float x_237 = specComp;
+  const float x_238 = glossiness;
+  specComp = pow(x_237, max(1.0f, x_238));
+  const float x_241 = specComp;
+  const float3 x_242 = specularColor;
+  result.specular = (x_242 * x_241);
+  const lightingInfo x_245 = result;
+  return x_245;
+}
+
+void main_1() {
+  float4 tempTextureRead = float4(0.0f, 0.0f, 0.0f, 0.0f);
+  float3 rgb = float3(0.0f, 0.0f, 0.0f);
+  float3 output5 = float3(0.0f, 0.0f, 0.0f);
+  float4 output4 = float4(0.0f, 0.0f, 0.0f, 0.0f);
+  float2 uvOffset = float2(0.0f, 0.0f);
+  float normalScale = 0.0f;
+  float2 TBNUV = float2(0.0f, 0.0f);
+  float2 x_299 = float2(0.0f, 0.0f);
+  float3x3 TBN = float3x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+  float3 param_3 = float3(0.0f, 0.0f, 0.0f);
+  float3 param_4 = float3(0.0f, 0.0f, 0.0f);
+  float2 param_5 = float2(0.0f, 0.0f);
+  float2 param_6 = float2(0.0f, 0.0f);
+  float3x3 invTBN = float3x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+  float3x3 param_7 = float3x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+  float parallaxLimit = 0.0f;
+  float2 vOffsetDir = float2(0.0f, 0.0f);
+  float2 vMaxOffset = float2(0.0f, 0.0f);
+  float numSamples = 0.0f;
+  float stepSize = 0.0f;
+  float currRayHeight = 0.0f;
+  float2 vCurrOffset = float2(0.0f, 0.0f);
+  float2 vLastOffset = float2(0.0f, 0.0f);
+  float lastSampledHeight = 0.0f;
+  float currSampledHeight = 0.0f;
+  float delta1 = 0.0f;
+  float delta2 = 0.0f;
+  float ratio = 0.0f;
+  float2 parallaxOcclusion_0 = float2(0.0f, 0.0f);
+  float3x3 param_8 = float3x3(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+  float3 param_9 = float3(0.0f, 0.0f, 0.0f);
+  float param_10 = 0.0f;
+  float2 output6 = float2(0.0f, 0.0f);
+  float4 tempTextureRead1 = float4(0.0f, 0.0f, 0.0f, 0.0f);
+  float3 rgb1 = float3(0.0f, 0.0f, 0.0f);
+  float3 viewDirectionW_1 = float3(0.0f, 0.0f, 0.0f);
+  float shadow = 0.0f;
+  float glossiness_1 = 0.0f;
+  float3 diffuseBase = float3(0.0f, 0.0f, 0.0f);
+  float3 specularBase = float3(0.0f, 0.0f, 0.0f);
+  float3 normalW = float3(0.0f, 0.0f, 0.0f);
+  lightingInfo info = {float3(0.0f, 0.0f, 0.0f), float3(0.0f, 0.0f, 0.0f)};
+  float3 param_11 = float3(0.0f, 0.0f, 0.0f);
+  float3 param_12 = float3(0.0f, 0.0f, 0.0f);
+  float4 param_13 = float4(0.0f, 0.0f, 0.0f, 0.0f);
+  float3 param_14 = float3(0.0f, 0.0f, 0.0f);
+  float3 param_15 = float3(0.0f, 0.0f, 0.0f);
+  float3 param_16 = float3(0.0f, 0.0f, 0.0f);
+  float param_17 = 0.0f;
+  float3 diffuseOutput = float3(0.0f, 0.0f, 0.0f);
+  float3 specularOutput = float3(0.0f, 0.0f, 0.0f);
+  float3 output3 = float3(0.0f, 0.0f, 0.0f);
+  u_Float = 100.0f;
+  u_Color = float3(0.5f, 0.5f, 0.5f);
+  const float2 x_261 = vMainuv;
+  const float4 x_262 = TextureSamplerTexture.Sample(TextureSamplerSampler, x_261);
+  tempTextureRead = x_262;
+  const float4 x_264 = tempTextureRead;
+  const int scalar_offset = (160u) / 4;
+  const float x_273 = asfloat(x_269[scalar_offset / 4][scalar_offset % 4]);
+  rgb = (float3(x_264.x, x_264.y, x_264.z) * x_273);
+  const int scalar_offset_1 = (144u) / 4;
+  const float3 x_279 = asfloat(x_269[scalar_offset_1 / 4].xyz);
+  const float4 x_282 = v_output1;
+  output5 = normalize((x_279 - float3(x_282.x, x_282.y, x_282.z)));
+  output4 = float4(0.0f, 0.0f, 0.0f, 0.0f);
+  uvOffset = float2(0.0f, 0.0f);
+  const int scalar_offset_2 = (128u) / 4;
+  const float x_292 = asfloat(x_269[scalar_offset_2 / 4][scalar_offset_2 % 4]);
+  normalScale = (1.0f / x_292);
+  const bool x_298 = gl_FrontFacing;
+  if (x_298) {
+    const float2 x_303 = v_uv;
+    x_299 = x_303;
+  } else {
+    const float2 x_305 = v_uv;
+    x_299 = -(x_305);
+  }
+  const float2 x_307 = x_299;
+  TBNUV = x_307;
+  const float4 x_310 = v_output2;
+  const float x_312 = normalScale;
+  param_3 = (float3(x_310.x, x_310.y, x_310.z) * x_312);
+  const float4 x_317 = v_output1;
+  param_4 = float3(x_317.x, x_317.y, x_317.z);
+  const float2 x_320 = TBNUV;
+  param_5 = x_320;
+  const int scalar_offset_3 = (168u) / 4;
+  uint4 ubo_load = x_269[scalar_offset_3 / 4];
+  const float2 x_324 = asfloat(((scalar_offset_3 & 2) ? ubo_load.zw : ubo_load.xy));
+  param_6 = x_324;
+  const float3x3 x_325 = cotangent_frame_vf3_vf3_vf2_vf2_(param_3, param_4, param_5, param_6);
+  TBN = x_325;
+  const float3x3 x_328 = TBN;
+  param_7 = x_328;
+  const float3x3 x_329 = transposeMat3_mf33_(param_7);
+  invTBN = x_329;
+  const float3x3 x_331 = invTBN;
+  const float3 x_332 = output5;
+  const float3 x_334 = mul(-(x_332), x_331);
+  const float3x3 x_337 = invTBN;
+  const float3 x_338 = output5;
+  parallaxLimit = (length(float2(x_334.x, x_334.y)) / mul(-(x_338), x_337).z);
+  const int scalar_offset_4 = (156u) / 4;
+  const float x_345 = asfloat(x_269[scalar_offset_4 / 4][scalar_offset_4 % 4]);
+  const float x_346 = parallaxLimit;
+  parallaxLimit = (x_346 * x_345);
+  const float3x3 x_349 = invTBN;
+  const float3 x_350 = output5;
+  const float3 x_352 = mul(-(x_350), x_349);
+  vOffsetDir = normalize(float2(x_352.x, x_352.y));
+  const float2 x_356 = vOffsetDir;
+  const float x_357 = parallaxLimit;
+  vMaxOffset = (x_356 * x_357);
+  const float3x3 x_361 = invTBN;
+  const float3 x_362 = output5;
+  const float3x3 x_365 = invTBN;
+  const float4 x_366 = v_output2;
+  numSamples = (15.0f + (dot(mul(-(x_362), x_361), mul(float3(x_366.x, x_366.y, x_366.z), x_365)) * -11.0f));
+  const float x_374 = numSamples;
+  stepSize = (1.0f / x_374);
+  currRayHeight = 1.0f;
+  vCurrOffset = float2(0.0f, 0.0f);
+  vLastOffset = float2(0.0f, 0.0f);
+  lastSampledHeight = 1.0f;
+  currSampledHeight = 1.0f;
+int i = 0;
+  while (i < 15) {
+    i++;
+    const float2 x_394 = v_uv;
+    const float2 x_395 = vCurrOffset;
+    const float4 x_397 = TextureSamplerTexture.Sample(TextureSamplerSampler, (x_394 + x_395));
+    currSampledHeight = x_397.w;
+    const float x_400 = currSampledHeight;
+    const float x_401 = currRayHeight;
+    if ((x_400 > x_401)) {
+      const float x_406 = currSampledHeight;
+      const float x_407 = currRayHeight;
+      delta1 = (x_406 - x_407);
+      const float x_410 = currRayHeight;
+      const float x_411 = stepSize;
+      const float x_413 = lastSampledHeight;
+      delta2 = ((x_410 + x_411) - x_413);
+      const float x_416 = delta1;
+      const float x_417 = delta1;
+      const float x_418 = delta2;
+      ratio = (x_416 / (x_417 + x_418));
+      const float x_421 = ratio;
+      const float2 x_422 = vLastOffset;
+      const float x_424 = ratio;
+      const float2 x_426 = vCurrOffset;
+      vCurrOffset = ((x_422 * x_421) + (x_426 * (1.0f - x_424)));
+      break;
+    } else {
+      const float x_431 = stepSize;
+      const float x_432 = currRayHeight;
+      currRayHeight = (x_432 - x_431);
+      const float2 x_434 = vCurrOffset;
+      vLastOffset = x_434;
+      const float x_435 = stepSize;
+      const float2 x_436 = vMaxOffset;
+      const float2 x_438 = vCurrOffset;
+      vCurrOffset = (x_438 + (x_436 * x_435));
+      const float x_440 = currSampledHeight;
+      lastSampledHeight = x_440;
+    }
+  }
+  const float2 x_444 = vCurrOffset;
+  parallaxOcclusion_0 = x_444;
+  const float2 x_445 = parallaxOcclusion_0;
+  uvOffset = x_445;
+  const float2 x_449 = v_uv;
+  const float2 x_450 = uvOffset;
+  const float4 x_452 = TextureSamplerTexture.Sample(TextureSamplerSampler, (x_449 + x_450));
+  const int scalar_offset_5 = (128u) / 4;
+  const float x_454 = asfloat(x_269[scalar_offset_5 / 4][scalar_offset_5 % 4]);
+  const float3x3 x_457 = TBN;
+  param_8 = x_457;
+  param_9 = float3(x_452.x, x_452.y, x_452.z);
+  param_10 = (1.0f / x_454);
+  const float3 x_461 = perturbNormal_mf33_vf3_f1_(param_8, param_9, param_10);
+  const float4 x_462 = output4;
+  output4 = float4(x_461.x, x_461.y, x_461.z, x_462.w);
+  const float2 x_465 = v_uv;
+  const float2 x_466 = uvOffset;
+  output6 = (x_465 + x_466);
+  const float2 x_474 = output6;
+  const float4 x_475 = TextureSampler1Texture.Sample(TextureSampler1Sampler, x_474);
+  tempTextureRead1 = x_475;
+  const float4 x_477 = tempTextureRead1;
+  rgb1 = float3(x_477.x, x_477.y, x_477.z);
+  const int scalar_offset_6 = (144u) / 4;
+  const float3 x_481 = asfloat(x_269[scalar_offset_6 / 4].xyz);
+  const float4 x_482 = v_output1;
+  viewDirectionW_1 = normalize((x_481 - float3(x_482.x, x_482.y, x_482.z)));
+  shadow = 1.0f;
+  const float x_488 = u_Float;
+  glossiness_1 = (1.0f * x_488);
+  diffuseBase = float3(0.0f, 0.0f, 0.0f);
+  specularBase = float3(0.0f, 0.0f, 0.0f);
+  const float4 x_494 = output4;
+  normalW = float3(x_494.x, x_494.y, x_494.z);
+  const float3 x_501 = viewDirectionW_1;
+  param_11 = x_501;
+  const float3 x_503 = normalW;
+  param_12 = x_503;
+  const int scalar_offset_7 = (0u) / 4;
+  const float4 x_507 = asfloat(light0[scalar_offset_7 / 4]);
+  param_13 = x_507;
+  const int scalar_offset_8 = (16u) / 4;
+  const float4 x_510 = asfloat(light0[scalar_offset_8 / 4]);
+  param_14 = float3(x_510.x, x_510.y, x_510.z);
+  const int scalar_offset_9 = (32u) / 4;
+  const float4 x_514 = asfloat(light0[scalar_offset_9 / 4]);
+  param_15 = float3(x_514.x, x_514.y, x_514.z);
+  const int scalar_offset_10 = (48u) / 4;
+  const float3 x_518 = asfloat(light0[scalar_offset_10 / 4].xyz);
+  param_16 = x_518;
+  const float x_520 = glossiness_1;
+  param_17 = x_520;
+  const lightingInfo x_521 = computeHemisphericLighting_vf3_vf3_vf4_vf3_vf3_vf3_f1_(param_11, param_12, param_13, param_14, param_15, param_16, param_17);
+  info = x_521;
+  shadow = 1.0f;
+  const float3 x_523 = info.diffuse;
+  const float x_524 = shadow;
+  const float3 x_526 = diffuseBase;
+  diffuseBase = (x_526 + (x_523 * x_524));
+  const float3 x_529 = info.specular;
+  const float x_530 = shadow;
+  const float3 x_532 = specularBase;
+  specularBase = (x_532 + (x_529 * x_530));
+  const float3 x_535 = diffuseBase;
+  const float3 x_536 = rgb1;
+  diffuseOutput = (x_535 * x_536);
+  const float3 x_539 = specularBase;
+  const float3 x_540 = u_Color;
+  specularOutput = (x_539 * x_540);
+  const float3 x_543 = diffuseOutput;
+  const float3 x_544 = specularOutput;
+  output3 = (x_543 + x_544);
+  const float3 x_548 = output3;
+  glFragColor = float4(x_548.x, x_548.y, x_548.z, 1.0f);
+  return;
+}
+
+struct main_out {
+  float4 glFragColor_1;
+};
+struct tint_symbol_1 {
+  float4 v_output1_param : TEXCOORD0;
+  float2 vMainuv_param : TEXCOORD1;
+  float4 v_output2_param : TEXCOORD2;
+  float2 v_uv_param : TEXCOORD3;
+  bool gl_FrontFacing_param : SV_IsFrontFace;
+};
+struct tint_symbol_2 {
+  float4 glFragColor_1 : SV_Target0;
+};
+
+tint_symbol_2 main(tint_symbol_1 tint_symbol) {
+  const float2 vMainuv_param = tint_symbol.vMainuv_param;
+  const float4 v_output1_param = tint_symbol.v_output1_param;
+  const bool gl_FrontFacing_param = tint_symbol.gl_FrontFacing_param;
+  const float2 v_uv_param = tint_symbol.v_uv_param;
+  const float4 v_output2_param = tint_symbol.v_output2_param;
+  vMainuv = vMainuv_param;
+  v_output1 = v_output1_param;
+  gl_FrontFacing = gl_FrontFacing_param;
+  v_uv = v_uv_param;
+  v_output2 = v_output2_param;
+  main_1();
+  const main_out tint_symbol_3 = {glFragColor};
+  const tint_symbol_2 tint_symbol_9 = {tint_symbol_3.glFragColor_1};
+  return tint_symbol_9;
+}
diff --git a/test/bug/tint/949.wgsl.expected.hlsl b/test/bug/tint/949.wgsl.expected.hlsl
index d4aee55..926e020 100644
--- a/test/bug/tint/949.wgsl.expected.hlsl
+++ b/test/bug/tint/949.wgsl.expected.hlsl
@@ -46,8 +46,7 @@
   const float3 x_146 = normal_1;
   dp2perp = cross(x_145, x_146);
   const float3 x_149 = normal_1;
-  const float3 x_150 = dp1;
-  dp1perp = cross(x_149, x_150);
+  dp1perp = cross(x_149, dp1);
   const float3 x_153 = dp2perp;
   const float x_155 = duv1.x;
   const float3 x_157 = dp1perp;
@@ -59,22 +58,12 @@
   const float x_169 = duv2.y;
   bitangent = ((x_163 * x_165) + (x_167 * x_169));
   const float x_173 = tangentSpaceParams.x;
-  const float3 x_174 = tangent;
-  tangent = (x_174 * x_173);
+  tangent = (tangent * x_173);
   const float x_177 = tangentSpaceParams.y;
-  const float3 x_178 = bitangent;
-  bitangent = (x_178 * x_177);
-  const float3 x_181 = tangent;
-  const float3 x_182 = tangent;
-  const float3 x_184 = bitangent;
-  const float3 x_185 = bitangent;
-  invmax = rsqrt(max(dot(x_181, x_182), dot(x_184, x_185)));
-  const float3 x_189 = tangent;
-  const float x_190 = invmax;
-  const float3 x_191 = (x_189 * x_190);
-  const float3 x_192 = bitangent;
-  const float x_193 = invmax;
-  const float3 x_194 = (x_192 * x_193);
+  bitangent = (bitangent * x_177);
+  invmax = rsqrt(max(dot(tangent, tangent), dot(bitangent, bitangent)));
+  const float3 x_191 = (tangent * invmax);
+  const float3 x_194 = (bitangent * invmax);
   const float3 x_195 = normal_1;
   return float3x3(float3(x_191.x, x_191.y, x_191.z), float3(x_194.x, x_194.y, x_194.z), float3(x_195.x, x_195.y, x_195.z));
 }
@@ -103,8 +92,7 @@
   const float x_93 = i2.z;
   const float3 x_94 = float3(x_89, x_91, x_93);
   outMatrix = float3x3(float3(x_78.x, x_78.y, x_78.z), float3(x_86.x, x_86.y, x_86.z), float3(x_94.x, x_94.y, x_94.z));
-  const float3x3 x_110 = outMatrix;
-  return x_110;
+  return outMatrix;
 }
 
 float3 perturbNormalBase_mf33_vf3_f1_(inout float3x3 cotangentFrame, inout float3 normal, inout float scale) {
@@ -143,16 +131,14 @@
   const float4 x_228 = lightData;
   angleW = normalize((x_227 + float3(x_228.x, x_228.y, x_228.z)));
   const float3 x_233 = vNormal;
-  const float3 x_234 = angleW;
-  specComp = max(0.0f, dot(x_233, x_234));
+  specComp = max(0.0f, dot(x_233, angleW));
   const float x_237 = specComp;
   const float x_238 = glossiness;
   specComp = pow(x_237, max(1.0f, x_238));
   const float x_241 = specComp;
   const float3 x_242 = specularColor;
   result.specular = (x_242 * x_241);
-  const lightingInfo x_245 = result;
-  return x_245;
+  return result;
 }
 
 void main_1() {
@@ -211,8 +197,7 @@
   float3 output3 = float3(0.0f, 0.0f, 0.0f);
   u_Float = 100.0f;
   u_Color = float3(0.5f, 0.5f, 0.5f);
-  const float2 x_261 = vMainuv;
-  const float4 x_262 = TextureSamplerTexture.Sample(TextureSamplerSampler, x_261);
+  const float4 x_262 = TextureSamplerTexture.Sample(TextureSamplerSampler, vMainuv);
   tempTextureRead = x_262;
   const float4 x_264 = tempTextureRead;
   const uint scalar_offset = (160u) / 4;
@@ -227,132 +212,71 @@
   const uint scalar_offset_2 = (128u) / 4;
   const float x_292 = asfloat(x_269[scalar_offset_2 / 4][scalar_offset_2 % 4]);
   normalScale = (1.0f / x_292);
-  const bool x_298 = gl_FrontFacing;
-  if (x_298) {
-    const float2 x_303 = v_uv;
-    x_299 = x_303;
+  if (gl_FrontFacing) {
+    x_299 = v_uv;
   } else {
-    const float2 x_305 = v_uv;
-    x_299 = -(x_305);
+    x_299 = -(v_uv);
   }
-  const float2 x_307 = x_299;
-  TBNUV = x_307;
+  TBNUV = x_299;
   const float4 x_310 = v_output2;
-  const float x_312 = normalScale;
-  param_3 = (float3(x_310.x, x_310.y, x_310.z) * x_312);
+  param_3 = (float3(x_310.x, x_310.y, x_310.z) * normalScale);
   const float4 x_317 = v_output1;
   param_4 = float3(x_317.x, x_317.y, x_317.z);
-  const float2 x_320 = TBNUV;
-  param_5 = x_320;
+  param_5 = TBNUV;
   const uint scalar_offset_3 = (168u) / 4;
   uint4 ubo_load = x_269[scalar_offset_3 / 4];
   const float2 x_324 = asfloat(((scalar_offset_3 & 2) ? ubo_load.zw : ubo_load.xy));
   param_6 = x_324;
   const float3x3 x_325 = cotangent_frame_vf3_vf3_vf2_vf2_(param_3, param_4, param_5, param_6);
   TBN = x_325;
-  const float3x3 x_328 = TBN;
-  param_7 = x_328;
+  param_7 = TBN;
   const float3x3 x_329 = transposeMat3_mf33_(param_7);
   invTBN = x_329;
-  const float3x3 x_331 = invTBN;
-  const float3 x_332 = output5;
-  const float3 x_334 = mul(-(x_332), x_331);
-  const float3x3 x_337 = invTBN;
-  const float3 x_338 = output5;
-  parallaxLimit = (length(float2(x_334.x, x_334.y)) / mul(-(x_338), x_337).z);
+  const float3 x_334 = mul(-(output5), invTBN);
+  parallaxLimit = (length(float2(x_334.x, x_334.y)) / mul(-(output5), invTBN).z);
   const uint scalar_offset_4 = (156u) / 4;
   const float x_345 = asfloat(x_269[scalar_offset_4 / 4][scalar_offset_4 % 4]);
-  const float x_346 = parallaxLimit;
-  parallaxLimit = (x_346 * x_345);
-  const float3x3 x_349 = invTBN;
-  const float3 x_350 = output5;
-  const float3 x_352 = mul(-(x_350), x_349);
+  parallaxLimit = (parallaxLimit * x_345);
+  const float3 x_352 = mul(-(output5), invTBN);
   vOffsetDir = normalize(float2(x_352.x, x_352.y));
-  const float2 x_356 = vOffsetDir;
-  const float x_357 = parallaxLimit;
-  vMaxOffset = (x_356 * x_357);
-  const float3x3 x_361 = invTBN;
-  const float3 x_362 = output5;
-  const float3x3 x_365 = invTBN;
+  vMaxOffset = (vOffsetDir * parallaxLimit);
   const float4 x_366 = v_output2;
-  numSamples = (15.0f + (dot(mul(-(x_362), x_361), mul(float3(x_366.x, x_366.y, x_366.z), x_365)) * -11.0f));
-  const float x_374 = numSamples;
-  stepSize = (1.0f / x_374);
+  numSamples = (15.0f + (dot(mul(-(output5), invTBN), mul(float3(x_366.x, x_366.y, x_366.z), invTBN)) * -11.0f));
+  stepSize = (1.0f / numSamples);
   currRayHeight = 1.0f;
   vCurrOffset = float2(0.0f, 0.0f);
   vLastOffset = float2(0.0f, 0.0f);
   lastSampledHeight = 1.0f;
   currSampledHeight = 1.0f;
   i = 0;
-  while (true) {
-    const int x_388 = i;
-    if ((x_388 < 15)) {
-    } else {
-      break;
-    }
-    const float2 x_394 = v_uv;
-    const float2 x_395 = vCurrOffset;
-    const float4 x_397 = TextureSamplerTexture.Sample(TextureSamplerSampler, (x_394 + x_395));
+  for(; (i < 15); i = (i + 1)) {
+    const float4 x_397 = TextureSamplerTexture.Sample(TextureSamplerSampler, (v_uv + vCurrOffset));
     currSampledHeight = x_397.w;
-    const float x_400 = currSampledHeight;
-    const float x_401 = currRayHeight;
-    if ((x_400 > x_401)) {
-      const float x_406 = currSampledHeight;
-      const float x_407 = currRayHeight;
-      delta1 = (x_406 - x_407);
-      const float x_410 = currRayHeight;
-      const float x_411 = stepSize;
-      const float x_413 = lastSampledHeight;
-      delta2 = ((x_410 + x_411) - x_413);
-      const float x_416 = delta1;
-      const float x_417 = delta1;
-      const float x_418 = delta2;
-      ratio = (x_416 / (x_417 + x_418));
-      const float x_421 = ratio;
-      const float2 x_422 = vLastOffset;
-      const float x_424 = ratio;
-      const float2 x_426 = vCurrOffset;
-      vCurrOffset = ((x_422 * x_421) + (x_426 * (1.0f - x_424)));
+    if ((currSampledHeight > currRayHeight)) {
+      delta1 = (currSampledHeight - currRayHeight);
+      delta2 = ((currRayHeight + stepSize) - lastSampledHeight);
+      ratio = (delta1 / (delta1 + delta2));
+      vCurrOffset = ((vLastOffset * ratio) + (vCurrOffset * (1.0f - ratio)));
       break;
     } else {
-      const float x_431 = stepSize;
-      const float x_432 = currRayHeight;
-      currRayHeight = (x_432 - x_431);
-      const float2 x_434 = vCurrOffset;
-      vLastOffset = x_434;
-      const float x_435 = stepSize;
-      const float2 x_436 = vMaxOffset;
-      const float2 x_438 = vCurrOffset;
-      vCurrOffset = (x_438 + (x_436 * x_435));
-      const float x_440 = currSampledHeight;
-      lastSampledHeight = x_440;
-    }
-    {
-      const int x_441 = i;
-      i = (x_441 + 1);
+      currRayHeight = (currRayHeight - stepSize);
+      vLastOffset = vCurrOffset;
+      vCurrOffset = (vCurrOffset + (vMaxOffset * stepSize));
+      lastSampledHeight = currSampledHeight;
     }
   }
-  const float2 x_444 = vCurrOffset;
-  parallaxOcclusion_0 = x_444;
-  const float2 x_445 = parallaxOcclusion_0;
-  uvOffset = x_445;
-  const float2 x_449 = v_uv;
-  const float2 x_450 = uvOffset;
-  const float4 x_452 = TextureSamplerTexture.Sample(TextureSamplerSampler, (x_449 + x_450));
+  parallaxOcclusion_0 = vCurrOffset;
+  uvOffset = parallaxOcclusion_0;
+  const float4 x_452 = TextureSamplerTexture.Sample(TextureSamplerSampler, (v_uv + uvOffset));
   const uint scalar_offset_5 = (128u) / 4;
   const float x_454 = asfloat(x_269[scalar_offset_5 / 4][scalar_offset_5 % 4]);
-  const float3x3 x_457 = TBN;
-  param_8 = x_457;
+  param_8 = TBN;
   param_9 = float3(x_452.x, x_452.y, x_452.z);
   param_10 = (1.0f / x_454);
   const float3 x_461 = perturbNormal_mf33_vf3_f1_(param_8, param_9, param_10);
-  const float4 x_462 = output4;
-  output4 = float4(x_461.x, x_461.y, x_461.z, x_462.w);
-  const float2 x_465 = v_uv;
-  const float2 x_466 = uvOffset;
-  output6 = (x_465 + x_466);
-  const float2 x_474 = output6;
-  const float4 x_475 = TextureSampler1Texture.Sample(TextureSampler1Sampler, x_474);
+  output4 = float4(x_461.x, x_461.y, x_461.z, output4.w);
+  output6 = (v_uv + uvOffset);
+  const float4 x_475 = TextureSampler1Texture.Sample(TextureSampler1Sampler, output6);
   tempTextureRead1 = x_475;
   const float4 x_477 = tempTextureRead1;
   rgb1 = float3(x_477.x, x_477.y, x_477.z);
@@ -361,16 +285,13 @@
   const float4 x_482 = v_output1;
   viewDirectionW_1 = normalize((x_481 - float3(x_482.x, x_482.y, x_482.z)));
   shadow = 1.0f;
-  const float x_488 = u_Float;
-  glossiness_1 = (1.0f * x_488);
+  glossiness_1 = (1.0f * u_Float);
   diffuseBase = float3(0.0f, 0.0f, 0.0f);
   specularBase = float3(0.0f, 0.0f, 0.0f);
   const float4 x_494 = output4;
   normalW = float3(x_494.x, x_494.y, x_494.z);
-  const float3 x_501 = viewDirectionW_1;
-  param_11 = x_501;
-  const float3 x_503 = normalW;
-  param_12 = x_503;
+  param_11 = viewDirectionW_1;
+  param_12 = normalW;
   const uint scalar_offset_7 = (0u) / 4;
   const float4 x_507 = asfloat(light0[scalar_offset_7 / 4]);
   param_13 = x_507;
@@ -383,28 +304,17 @@
   const uint scalar_offset_10 = (48u) / 4;
   const float3 x_518 = asfloat(light0[scalar_offset_10 / 4].xyz);
   param_16 = x_518;
-  const float x_520 = glossiness_1;
-  param_17 = x_520;
+  param_17 = glossiness_1;
   const lightingInfo x_521 = computeHemisphericLighting_vf3_vf3_vf4_vf3_vf3_vf3_f1_(param_11, param_12, param_13, param_14, param_15, param_16, param_17);
   info = x_521;
   shadow = 1.0f;
   const float3 x_523 = info.diffuse;
-  const float x_524 = shadow;
-  const float3 x_526 = diffuseBase;
-  diffuseBase = (x_526 + (x_523 * x_524));
+  diffuseBase = (diffuseBase + (x_523 * shadow));
   const float3 x_529 = info.specular;
-  const float x_530 = shadow;
-  const float3 x_532 = specularBase;
-  specularBase = (x_532 + (x_529 * x_530));
-  const float3 x_535 = diffuseBase;
-  const float3 x_536 = rgb1;
-  diffuseOutput = (x_535 * x_536);
-  const float3 x_539 = specularBase;
-  const float3 x_540 = u_Color;
-  specularOutput = (x_539 * x_540);
-  const float3 x_543 = diffuseOutput;
-  const float3 x_544 = specularOutput;
-  output3 = (x_543 + x_544);
+  specularBase = (specularBase + (x_529 * shadow));
+  diffuseOutput = (diffuseBase * rgb1);
+  specularOutput = (specularBase * u_Color);
+  output3 = (diffuseOutput + specularOutput);
   const float3 x_548 = output3;
   glFragColor = float4(x_548.x, x_548.y, x_548.z, 1.0f);
   return;
diff --git a/test/bug/tint/949.wgsl.expected.spirvcross.hlsl b/test/bug/tint/949.wgsl.expected.spirvcross.hlsl
new file mode 100644
index 0000000..1d61098
--- /dev/null
+++ b/test/bug/tint/949.wgsl.expected.spirvcross.hlsl
@@ -0,0 +1,211 @@
+/* Dumped generated HLSL */
+struct lightingInfo
+{
+    float3 diffuse;
+    float3 specular;
+};
+
+cbuffer LeftOver : register(b0, space2)
+{
+    row_major float4x4 _269_u_World : packoffset(c0);
+    row_major float4x4 _269_u_ViewProjection : packoffset(c4);
+    float _269_u_bumpStrength : packoffset(c8);
+    float3 _269_u_cameraPosition : packoffset(c9);
+    float _269_u_parallaxScale : packoffset(c9.w);
+    float _269_textureInfoName : packoffset(c10);
+    float2 _269_tangentSpaceParameter0 : packoffset(c10.z);
+};
+
+cbuffer Light0 : register(b0, space0)
+{
+    float4 light0_vLightData : packoffset(c0);
+    float4 light0_vLightDiffuse : packoffset(c1);
+    float4 light0_vLightSpecular : packoffset(c2);
+    float3 light0_vLightGround : packoffset(c3);
+    float4 light0_shadowsInfo : packoffset(c4);
+    float2 light0_depthValues : packoffset(c5);
+};
+
+Texture2D<float4> TextureSamplerTexture : register(t3, space2);
+SamplerState TextureSamplerSampler : register(s2, space2);
+Texture2D<float4> TextureSampler1Texture : register(t1, space2);
+SamplerState TextureSampler1Sampler : register(s0, space2);
+SamplerState bumpSamplerSampler : register(s1, space2);
+Texture2D<float4> bumpSamplerTexture : register(t2, space2);
+
+static bool gl_FrontFacing;
+static float2 vMainuv;
+static float4 v_output1;
+static float2 v_uv;
+static float4 v_output2;
+static float4 glFragColor;
+
+struct SPIRV_Cross_Input
+{
+    float4 v_output1 : TEXCOORD0;
+    float2 vMainuv : TEXCOORD1;
+    float4 v_output2 : TEXCOORD2;
+    float2 v_uv : TEXCOORD3;
+    bool gl_FrontFacing : SV_IsFrontFace;
+};
+
+struct SPIRV_Cross_Output
+{
+    float4 glFragColor : SV_Target0;
+};
+
+static float u_Float = 0.0f;
+static float3 u_Color = 0.0f.xxx;
+
+float3x3 cotangent_frame(float3 normal, float3 p, float2 uv, float2 tangentSpaceParams)
+{
+    float3 dp1 = ddx(p);
+    float3 dp2 = ddy(p);
+    float2 duv1 = ddx(uv);
+    float2 duv2 = ddy(uv);
+    float3 dp2perp = cross(dp2, normal);
+    float3 dp1perp = cross(normal, dp1);
+    float3 tangent = (dp2perp * duv1.x) + (dp1perp * duv2.x);
+    float3 bitangent = (dp2perp * duv1.y) + (dp1perp * duv2.y);
+    tangent *= tangentSpaceParams.x;
+    bitangent *= tangentSpaceParams.y;
+    float invmax = rsqrt(max(dot(tangent, tangent), dot(bitangent, bitangent)));
+    return float3x3(float3(tangent * invmax), float3(bitangent * invmax), float3(normal));
+}
+
+float3x3 transposeMat3(float3x3 inMatrix)
+{
+    float3 i0 = inMatrix[0];
+    float3 i1 = inMatrix[1];
+    float3 i2 = inMatrix[2];
+    float3x3 outMatrix = float3x3(float3(float3(i0.x, i1.x, i2.x)), float3(float3(i0.y, i1.y, i2.y)), float3(float3(i0.z, i1.z, i2.z)));
+    return outMatrix;
+}
+
+float3 perturbNormalBase(float3x3 cotangentFrame, float3 normal, float scale)
+{
+    return normalize(mul(normal, cotangentFrame));
+}
+
+float3 perturbNormal(float3x3 cotangentFrame, float3 textureSample, float scale)
+{
+    float3x3 param = cotangentFrame;
+    float3 param_1 = (textureSample * 2.0f) - 1.0f.xxx;
+    float param_2 = scale;
+    return perturbNormalBase(param, param_1, param_2);
+}
+
+lightingInfo computeHemisphericLighting(float3 viewDirectionW, float3 vNormal, float4 lightData, float3 diffuseColor, float3 specularColor, float3 groundColor, float glossiness)
+{
+    float ndl = (dot(vNormal, lightData.xyz) * 0.5f) + 0.5f;
+    lightingInfo result = { 0.0f.xxx, 0.0f.xxx };
+    result.diffuse = lerp(groundColor, diffuseColor, ndl.xxx);
+    float3 angleW = normalize(viewDirectionW + lightData.xyz);
+    float specComp = max(0.0f, dot(vNormal, angleW));
+    specComp = pow(specComp, max(1.0f, glossiness));
+    result.specular = specularColor * specComp;
+    return result;
+}
+
+void frag_main()
+{
+    u_Float = 100.0f;
+    u_Color = 0.5f.xxx;
+    float4 tempTextureRead = TextureSamplerTexture.Sample(TextureSamplerSampler, vMainuv);
+    float3 rgb = tempTextureRead.xyz * _269_textureInfoName;
+    float3 output5 = normalize(_269_u_cameraPosition - v_output1.xyz);
+    float4 output4 = 0.0f.xxxx;
+    float2 uvOffset = 0.0f.xx;
+    float normalScale = 1.0f / _269_u_bumpStrength;
+    float2 _299 = 0.0f.xx;
+    if (gl_FrontFacing)
+    {
+        _299 = v_uv;
+    }
+    else
+    {
+        _299 = -v_uv;
+    }
+    float2 TBNUV = _299;
+    float3 param = v_output2.xyz * normalScale;
+    float3 param_1 = v_output1.xyz;
+    float2 param_2 = TBNUV;
+    float2 param_3 = _269_tangentSpaceParameter0;
+    float3x3 TBN = cotangent_frame(param, param_1, param_2, param_3);
+    float3x3 param_4 = TBN;
+    float3x3 invTBN = transposeMat3(param_4);
+    float parallaxLimit = length(mul(-output5, invTBN).xy) / mul(-output5, invTBN).z;
+    parallaxLimit *= _269_u_parallaxScale;
+    float2 vOffsetDir = normalize(mul(-output5, invTBN).xy);
+    float2 vMaxOffset = vOffsetDir * parallaxLimit;
+    float numSamples = 15.0f + (dot(mul(-output5, invTBN), mul(v_output2.xyz, invTBN)) * (-11.0f));
+    float stepSize = 1.0f / numSamples;
+    float currRayHeight = 1.0f;
+    float2 vCurrOffset = 0.0f.xx;
+    float2 vLastOffset = 0.0f.xx;
+    float lastSampledHeight = 1.0f;
+    float currSampledHeight = 1.0f;
+    for (int i = 0; i < 15; i++)
+    {
+        currSampledHeight = TextureSamplerTexture.Sample(TextureSamplerSampler, v_uv + vCurrOffset).w;
+        if (currSampledHeight > currRayHeight)
+        {
+            float delta1 = currSampledHeight - currRayHeight;
+            float delta2 = (currRayHeight + stepSize) - lastSampledHeight;
+            float ratio = delta1 / (delta1 + delta2);
+            vCurrOffset = (vLastOffset * ratio) + (vCurrOffset * (1.0f - ratio));
+            break;
+        }
+        else
+        {
+            currRayHeight -= stepSize;
+            vLastOffset = vCurrOffset;
+            vCurrOffset += (vMaxOffset * stepSize);
+            lastSampledHeight = currSampledHeight;
+        }
+    }
+    float2 parallaxOcclusion_0 = vCurrOffset;
+    uvOffset = parallaxOcclusion_0;
+    float3x3 param_5 = TBN;
+    float3 param_6 = TextureSamplerTexture.Sample(TextureSamplerSampler, v_uv + uvOffset).xyz;
+    float param_7 = 1.0f / _269_u_bumpStrength;
+    float3 _461 = perturbNormal(param_5, param_6, param_7);
+    output4 = float4(_461.x, _461.y, _461.z, output4.w);
+    float2 output6 = v_uv + uvOffset;
+    float4 tempTextureRead1 = TextureSampler1Texture.Sample(TextureSampler1Sampler, output6);
+    float3 rgb1 = tempTextureRead1.xyz;
+    float3 viewDirectionW = normalize(_269_u_cameraPosition - v_output1.xyz);
+    float shadow = 1.0f;
+    float glossiness = 1.0f * u_Float;
+    float3 diffuseBase = 0.0f.xxx;
+    float3 specularBase = 0.0f.xxx;
+    float3 normalW = output4.xyz;
+    float3 param_8 = viewDirectionW;
+    float3 param_9 = normalW;
+    float4 param_10 = light0_vLightData;
+    float3 param_11 = light0_vLightDiffuse.xyz;
+    float3 param_12 = light0_vLightSpecular.xyz;
+    float3 param_13 = light0_vLightGround;
+    float param_14 = glossiness;
+    lightingInfo info = computeHemisphericLighting(param_8, param_9, param_10, param_11, param_12, param_13, param_14);
+    shadow = 1.0f;
+    diffuseBase += (info.diffuse * shadow);
+    specularBase += (info.specular * shadow);
+    float3 diffuseOutput = diffuseBase * rgb1;
+    float3 specularOutput = specularBase * u_Color;
+    float3 output3 = diffuseOutput + specularOutput;
+    glFragColor = float4(output3, 1.0f);
+}
+
+SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
+{
+    gl_FrontFacing = stage_input.gl_FrontFacing;
+    vMainuv = stage_input.vMainuv;
+    v_output1 = stage_input.v_output1;
+    v_uv = stage_input.v_uv;
+    v_output2 = stage_input.v_output2;
+    frag_main();
+    SPIRV_Cross_Output stage_output;
+    stage_output.glFragColor = glFragColor;
+    return stage_output;
+}
\ No newline at end of file
diff --git a/test/fxc_bugs/vector_assignment_in_loop/loop_call_with_loop.wgsl.expected.hlsl b/test/fxc_bugs/vector_assignment_in_loop/loop_call_with_loop.wgsl.expected.hlsl
index 5b47c06..6496cf5 100644
--- a/test/fxc_bugs/vector_assignment_in_loop/loop_call_with_loop.wgsl.expected.hlsl
+++ b/test/fxc_bugs/vector_assignment_in_loop/loop_call_with_loop.wgsl.expected.hlsl
@@ -33,17 +33,11 @@
 void foo() {
   {
     int i = 0;
-    while (true) {
-      if (!((i < 2))) {
-        break;
-      }
+    for(; !(!((i < 2))); i = (i + 1)) {
       Set_float2(v2f, i, 1.0f);
       Set_int3(v3i, i, 1);
       Set_uint4(v4u, i, 1u);
       Set_bool2(v2b, i, true);
-      {
-        i = (i + 1);
-      }
     }
   }
 }
@@ -52,14 +46,8 @@
 void main() {
   {
     int i = 0;
-    while (true) {
-      if (!((i < 2))) {
-        break;
-      }
+    for(; !(!((i < 2))); i = (i + 1)) {
       foo();
-      {
-        i = (i + 1);
-      }
     }
   }
   return;
diff --git a/test/fxc_bugs/vector_assignment_in_loop/loop_call_with_no_loop.wgsl.expected.hlsl b/test/fxc_bugs/vector_assignment_in_loop/loop_call_with_no_loop.wgsl.expected.hlsl
index 6e34e56..33a99b9 100644
--- a/test/fxc_bugs/vector_assignment_in_loop/loop_call_with_no_loop.wgsl.expected.hlsl
+++ b/test/fxc_bugs/vector_assignment_in_loop/loop_call_with_no_loop.wgsl.expected.hlsl
@@ -15,14 +15,8 @@
 void main() {
   {
     int i = 0;
-    while (true) {
-      if (!((i < 2))) {
-        break;
-      }
+    for(; !(!((i < 2))); i = (i + 1)) {
       foo();
-      {
-        i = (i + 1);
-      }
     }
   }
   return;
diff --git a/test/fxc_bugs/vector_assignment_in_loop/loop_types_all.wgsl.expected.hlsl b/test/fxc_bugs/vector_assignment_in_loop/loop_types_all.wgsl.expected.hlsl
index 3600e49..c8fa518 100644
--- a/test/fxc_bugs/vector_assignment_in_loop/loop_types_all.wgsl.expected.hlsl
+++ b/test/fxc_bugs/vector_assignment_in_loop/loop_types_all.wgsl.expected.hlsl
@@ -98,10 +98,7 @@
   bool4 v4b = bool4(false, false, false, false);
   {
     int i = 0;
-    while (true) {
-      if (!((i < 2))) {
-        break;
-      }
+    for(; !(!((i < 2))); i = (i + 1)) {
       Set_float2(v2f, i, 1.0f);
       Set_float3(v3f, i, 1.0f);
       Set_float4(v4f, i, 1.0f);
@@ -114,9 +111,6 @@
       Set_bool2(v2b, i, true);
       Set_bool3(v3b, i, true);
       Set_bool4(v4b, i, true);
-      {
-        i = (i + 1);
-      }
     }
   }
   return;
diff --git a/test/fxc_bugs/vector_assignment_in_loop/loop_types_repeated.wgsl.expected.hlsl b/test/fxc_bugs/vector_assignment_in_loop/loop_types_repeated.wgsl.expected.hlsl
index 8dc8159..cbc4e6a 100644
--- a/test/fxc_bugs/vector_assignment_in_loop/loop_types_repeated.wgsl.expected.hlsl
+++ b/test/fxc_bugs/vector_assignment_in_loop/loop_types_repeated.wgsl.expected.hlsl
@@ -37,10 +37,7 @@
   bool2 v2b_2 = bool2(false, false);
   {
     int i = 0;
-    while (true) {
-      if (!((i < 2))) {
-        break;
-      }
+    for(; !(!((i < 2))); i = (i + 1)) {
       Set_float2(v2f, i, 1.0f);
       Set_int3(v3i, i, 1);
       Set_uint4(v4u, i, 1u);
@@ -49,9 +46,6 @@
       Set_int3(v3i_2, i, 1);
       Set_uint4(v4u_2, i, 1u);
       Set_bool2(v2b_2, i, true);
-      {
-        i = (i + 1);
-      }
     }
   }
   return;
diff --git a/test/fxc_bugs/vector_assignment_in_loop/loop_types_some.wgsl.expected.hlsl b/test/fxc_bugs/vector_assignment_in_loop/loop_types_some.wgsl.expected.hlsl
index 953595e..aed923f 100644
--- a/test/fxc_bugs/vector_assignment_in_loop/loop_types_some.wgsl.expected.hlsl
+++ b/test/fxc_bugs/vector_assignment_in_loop/loop_types_some.wgsl.expected.hlsl
@@ -38,17 +38,11 @@
   bool4 v4b = bool4(false, false, false, false);
   {
     int i = 0;
-    while (true) {
-      if (!((i < 2))) {
-        break;
-      }
+    for(; !(!((i < 2))); i = (i + 1)) {
       Set_float2(v2f, i, 1.0f);
       Set_int2(v2i, i, 1);
       Set_uint2(v2u, i, 1u);
       Set_bool2(v2b, i, true);
-      {
-        i = (i + 1);
-      }
     }
   }
   int i = 0;
diff --git a/test/ptr_ref/load/global/i32.spvasm.expected.hlsl b/test/ptr_ref/load/global/i32.spvasm.expected.hlsl
index 949fd0b..a75ddfa 100644
--- a/test/ptr_ref/load/global/i32.spvasm.expected.hlsl
+++ b/test/ptr_ref/load/global/i32.spvasm.expected.hlsl
@@ -1,8 +1,7 @@
 static int I = 0;
 
 void main_1() {
-  const int x_9 = I;
-  const int x_11 = (x_9 + 1);
+  const int x_11 = (I + 1);
   return;
 }
 
diff --git a/test/ptr_ref/load/global/i32.wgsl.expected.hlsl b/test/ptr_ref/load/global/i32.wgsl.expected.hlsl
index 85b0204..788136b 100644
--- a/test/ptr_ref/load/global/i32.wgsl.expected.hlsl
+++ b/test/ptr_ref/load/global/i32.wgsl.expected.hlsl
@@ -2,7 +2,6 @@
 
 [numthreads(1, 1, 1)]
 void main() {
-  const int i = I;
-  const int use = (i + 1);
+  const int use = (I + 1);
   return;
 }
diff --git a/test/ptr_ref/load/local/i32.spvasm.expected.hlsl b/test/ptr_ref/load/local/i32.spvasm.expected.hlsl
index e93814c..3f9ee13 100644
--- a/test/ptr_ref/load/local/i32.spvasm.expected.hlsl
+++ b/test/ptr_ref/load/local/i32.spvasm.expected.hlsl
@@ -1,8 +1,7 @@
 void main_1() {
   int i = 0;
   i = 123;
-  const int x_10 = i;
-  const int x_12 = (x_10 + 1);
+  const int x_12 = (i + 1);
   return;
 }
 
diff --git a/test/ptr_ref/load/param/ptr.spvasm.expected.hlsl b/test/ptr_ref/load/param/ptr.spvasm.expected.hlsl
index abdb81c..2ddad5c 100644
--- a/test/ptr_ref/load/param/ptr.spvasm.expected.hlsl
+++ b/test/ptr_ref/load/param/ptr.spvasm.expected.hlsl
@@ -6,8 +6,7 @@
 void main_1() {
   int i = 0;
   i = 123;
-  const int x_19 = i;
-  const int x_18 = func(x_19, i);
+  const int x_18 = func(i, i);
   return;
 }
 
diff --git a/test/samples/compute_boids.wgsl.expected.hlsl b/test/samples/compute_boids.wgsl.expected.hlsl
index 1593974..d98a316 100644
--- a/test/samples/compute_boids.wgsl.expected.hlsl
+++ b/test/samples/compute_boids.wgsl.expected.hlsl
@@ -54,14 +54,8 @@
   float2 vel = float2(0.0f, 0.0f);
   {
     uint i = 0u;
-    while (true) {
-      if (!((i < 5u))) {
-        break;
-      }
+    for(; !(!((i < 5u))); i = (i + 1u)) {
       if ((i == index)) {
-        {
-          i = (i + 1u);
-        }
         continue;
       }
       pos = asfloat(particlesA.Load2((16u * i))).xy;
@@ -80,9 +74,6 @@
         cVel = (cVel + vel);
         cVelCount = (cVelCount + 1);
       }
-      {
-        i = (i + 1u);
-      }
     }
   }
   if ((cMassCount > 0)) {