Remove Common Uniform Elimination Pass (#2731)

Remove Common Uniform Elimination Pass

Fixes #2520.
diff --git a/Android.mk b/Android.mk
index 075dc61..82d9776 100644
--- a/Android.mk
+++ b/Android.mk
@@ -84,7 +84,6 @@
 		source/opt/ccp_pass.cpp \
 		source/opt/code_sink.cpp \
 		source/opt/combine_access_chains.cpp \
-		source/opt/common_uniform_elim_pass.cpp \
 		source/opt/compact_ids_pass.cpp \
 		source/opt/composite.cpp \
 		source/opt/const_folding_rules.cpp \
diff --git a/BUILD.gn b/BUILD.gn
index 8852584..70772b9 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -469,8 +469,6 @@
     "source/opt/code_sink.h",
     "source/opt/combine_access_chains.cpp",
     "source/opt/combine_access_chains.h",
-    "source/opt/common_uniform_elim_pass.cpp",
-    "source/opt/common_uniform_elim_pass.h",
     "source/opt/compact_ids_pass.cpp",
     "source/opt/compact_ids_pass.h",
     "source/opt/composite.cpp",
diff --git a/include/spirv-tools/optimizer.hpp b/include/spirv-tools/optimizer.hpp
index 1d8d6e0..4c668b4 100644
--- a/include/spirv-tools/optimizer.hpp
+++ b/include/spirv-tools/optimizer.hpp
@@ -492,20 +492,6 @@
 // inserts created by that pass.
 Optimizer::PassToken CreateDeadInsertElimPass();
 
-// Creates a pass to consolidate uniform references.
-// For each entry point function in the module, first change all constant index
-// access chain loads into equivalent composite extracts. Then consolidate
-// identical uniform loads into one uniform load. Finally, consolidate
-// identical uniform extracts into one uniform extract. This may require
-// moving a load or extract to a point which dominates all uses.
-//
-// This pass requires a module to have structured control flow ie shader
-// capability. It also requires logical addressing ie Addresses capability
-// is not enabled. It also currently does not support any extensions.
-//
-// This pass currently only optimizes loads with a single index.
-Optimizer::PassToken CreateCommonUniformElimPass();
-
 // Create aggressive dead code elimination pass
 // This pass eliminates unused code from the module. In addition,
 // it detects and eliminates code which may have spurious uses but which do
diff --git a/source/opt/CMakeLists.txt b/source/opt/CMakeLists.txt
index 4cd8001..3e1280e 100644
--- a/source/opt/CMakeLists.txt
+++ b/source/opt/CMakeLists.txt
@@ -22,7 +22,6 @@
   cfg.h
   code_sink.h
   combine_access_chains.h
-  common_uniform_elim_pass.h
   compact_ids_pass.h
   composite.h
   const_folding_rules.h
@@ -123,7 +122,6 @@
   cfg.cpp
   code_sink.cpp
   combine_access_chains.cpp
-  common_uniform_elim_pass.cpp
   compact_ids_pass.cpp
   composite.cpp
   const_folding_rules.cpp
diff --git a/source/opt/common_uniform_elim_pass.cpp b/source/opt/common_uniform_elim_pass.cpp
deleted file mode 100644
index 86889a6..0000000
--- a/source/opt/common_uniform_elim_pass.cpp
+++ /dev/null
@@ -1,596 +0,0 @@
-// Copyright (c) 2017 The Khronos Group Inc.
-// Copyright (c) 2017 Valve Corporation
-// Copyright (c) 2017 LunarG Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "source/opt/common_uniform_elim_pass.h"
-#include "source/cfa.h"
-#include "source/opt/ir_context.h"
-
-namespace spvtools {
-namespace opt {
-
-namespace {
-
-const uint32_t kAccessChainPtrIdInIdx = 0;
-const uint32_t kTypePointerStorageClassInIdx = 0;
-const uint32_t kTypePointerTypeIdInIdx = 1;
-const uint32_t kConstantValueInIdx = 0;
-const uint32_t kExtractCompositeIdInIdx = 0;
-const uint32_t kExtractIdx0InIdx = 1;
-const uint32_t kStorePtrIdInIdx = 0;
-const uint32_t kLoadPtrIdInIdx = 0;
-const uint32_t kCopyObjectOperandInIdx = 0;
-const uint32_t kTypeIntWidthInIdx = 0;
-
-}  // anonymous namespace
-
-bool CommonUniformElimPass::IsNonPtrAccessChain(const SpvOp opcode) const {
-  return opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain;
-}
-
-bool CommonUniformElimPass::IsSamplerOrImageType(
-    const Instruction* typeInst) const {
-  switch (typeInst->opcode()) {
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampledImage:
-      return true;
-    default:
-      break;
-  }
-  if (typeInst->opcode() != SpvOpTypeStruct) return false;
-  // Return true if any member is a sampler or image
-  return !typeInst->WhileEachInId([this](const uint32_t* tid) {
-    const Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid);
-    if (IsSamplerOrImageType(compTypeInst)) {
-      return false;
-    }
-    return true;
-  });
-}
-
-bool CommonUniformElimPass::IsSamplerOrImageVar(uint32_t varId) const {
-  const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
-  assert(varInst->opcode() == SpvOpVariable);
-  const uint32_t varTypeId = varInst->type_id();
-  const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  const uint32_t varPteTypeId =
-      varTypeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx);
-  Instruction* varPteTypeInst = get_def_use_mgr()->GetDef(varPteTypeId);
-  return IsSamplerOrImageType(varPteTypeInst);
-}
-
-Instruction* CommonUniformElimPass::GetPtr(Instruction* ip, uint32_t* objId) {
-  const SpvOp op = ip->opcode();
-  assert(op == SpvOpStore || op == SpvOpLoad);
-  *objId = ip->GetSingleWordInOperand(op == SpvOpStore ? kStorePtrIdInIdx
-                                                       : kLoadPtrIdInIdx);
-  Instruction* ptrInst = get_def_use_mgr()->GetDef(*objId);
-  while (ptrInst->opcode() == SpvOpCopyObject) {
-    *objId = ptrInst->GetSingleWordInOperand(kCopyObjectOperandInIdx);
-    ptrInst = get_def_use_mgr()->GetDef(*objId);
-  }
-  Instruction* objInst = ptrInst;
-  while (objInst->opcode() != SpvOpVariable &&
-         objInst->opcode() != SpvOpFunctionParameter) {
-    if (IsNonPtrAccessChain(objInst->opcode())) {
-      *objId = objInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx);
-    } else {
-      assert(objInst->opcode() == SpvOpCopyObject);
-      *objId = objInst->GetSingleWordInOperand(kCopyObjectOperandInIdx);
-    }
-    objInst = get_def_use_mgr()->GetDef(*objId);
-  }
-  return ptrInst;
-}
-
-bool CommonUniformElimPass::IsVolatileStruct(uint32_t type_id) {
-  assert(get_def_use_mgr()->GetDef(type_id)->opcode() == SpvOpTypeStruct);
-  return !get_decoration_mgr()->WhileEachDecoration(
-      type_id, SpvDecorationVolatile, [](const Instruction&) { return false; });
-}
-
-bool CommonUniformElimPass::IsAccessChainToVolatileStructType(
-    const Instruction& AccessChainInst) {
-  assert(AccessChainInst.opcode() == SpvOpAccessChain);
-
-  uint32_t ptr_id = AccessChainInst.GetSingleWordInOperand(0);
-  const Instruction* ptr_inst = get_def_use_mgr()->GetDef(ptr_id);
-  uint32_t pointee_type_id = GetPointeeTypeId(ptr_inst);
-  const uint32_t num_operands = AccessChainInst.NumOperands();
-
-  // walk the type tree:
-  for (uint32_t idx = 3; idx < num_operands; ++idx) {
-    Instruction* pointee_type = get_def_use_mgr()->GetDef(pointee_type_id);
-
-    switch (pointee_type->opcode()) {
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-        pointee_type_id = pointee_type->GetSingleWordOperand(1);
-        break;
-      case SpvOpTypeStruct:
-        // check for volatile decorations:
-        if (IsVolatileStruct(pointee_type_id)) return true;
-
-        if (idx < num_operands - 1) {
-          const uint32_t index_id = AccessChainInst.GetSingleWordOperand(idx);
-          const Instruction* index_inst = get_def_use_mgr()->GetDef(index_id);
-          uint32_t index_value = index_inst->GetSingleWordOperand(
-              2);  // TODO: replace with GetUintValueFromConstant()
-          pointee_type_id = pointee_type->GetSingleWordInOperand(index_value);
-        }
-        break;
-      default:
-        assert(false && "Unhandled pointee type.");
-    }
-  }
-  return false;
-}
-
-bool CommonUniformElimPass::IsVolatileLoad(const Instruction& loadInst) {
-  assert(loadInst.opcode() == SpvOpLoad);
-  // Check if this Load instruction has Volatile Memory Access flag
-  if (loadInst.NumOperands() == 4) {
-    uint32_t memory_access_mask = loadInst.GetSingleWordOperand(3);
-    if (memory_access_mask & SpvMemoryAccessVolatileMask) return true;
-  }
-  // If we load a struct directly (result type is struct),
-  // check if the struct is decorated volatile
-  uint32_t type_id = loadInst.type_id();
-  if (get_def_use_mgr()->GetDef(type_id)->opcode() == SpvOpTypeStruct)
-    return IsVolatileStruct(type_id);
-  else
-    return false;
-}
-
-bool CommonUniformElimPass::IsUniformVar(uint32_t varId) {
-  const Instruction* varInst =
-      get_def_use_mgr()->id_to_defs().find(varId)->second;
-  if (varInst->opcode() != SpvOpVariable) return false;
-  const uint32_t varTypeId = varInst->type_id();
-  const Instruction* varTypeInst =
-      get_def_use_mgr()->id_to_defs().find(varTypeId)->second;
-  return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
-             SpvStorageClassUniform ||
-         varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
-             SpvStorageClassUniformConstant;
-}
-
-bool CommonUniformElimPass::HasUnsupportedDecorates(uint32_t id) const {
-  return !get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) {
-    if (IsNonTypeDecorate(user->opcode())) return false;
-    return true;
-  });
-}
-
-bool CommonUniformElimPass::HasOnlyNamesAndDecorates(uint32_t id) const {
-  return get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) {
-    SpvOp op = user->opcode();
-    if (op != SpvOpName && !IsNonTypeDecorate(op)) return false;
-    return true;
-  });
-}
-
-void CommonUniformElimPass::DeleteIfUseless(Instruction* inst) {
-  const uint32_t resId = inst->result_id();
-  assert(resId != 0);
-  if (HasOnlyNamesAndDecorates(resId)) {
-    context()->KillInst(inst);
-  }
-}
-
-Instruction* CommonUniformElimPass::ReplaceAndDeleteLoad(Instruction* loadInst,
-                                                         uint32_t replId,
-                                                         Instruction* ptrInst) {
-  const uint32_t loadId = loadInst->result_id();
-  context()->KillNamesAndDecorates(loadId);
-  (void)context()->ReplaceAllUsesWith(loadId, replId);
-  // remove load instruction
-  Instruction* next_instruction = context()->KillInst(loadInst);
-  // if access chain, see if it can be removed as well
-  if (IsNonPtrAccessChain(ptrInst->opcode())) DeleteIfUseless(ptrInst);
-  return next_instruction;
-}
-
-void CommonUniformElimPass::GenACLoadRepl(
-    const Instruction* ptrInst,
-    std::vector<std::unique_ptr<Instruction>>* newInsts, uint32_t* resultId) {
-  // Build and append Load
-  const uint32_t ldResultId = TakeNextId();
-  const uint32_t varId =
-      ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx);
-  const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
-  assert(varInst->opcode() == SpvOpVariable);
-  const uint32_t varPteTypeId = GetPointeeTypeId(varInst);
-  std::vector<Operand> load_in_operands;
-  load_in_operands.push_back(Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
-                                     std::initializer_list<uint32_t>{varId}));
-  std::unique_ptr<Instruction> newLoad(new Instruction(
-      context(), SpvOpLoad, varPteTypeId, ldResultId, load_in_operands));
-  get_def_use_mgr()->AnalyzeInstDefUse(&*newLoad);
-  newInsts->emplace_back(std::move(newLoad));
-
-  // Build and append Extract
-  const uint32_t extResultId = TakeNextId();
-  const uint32_t ptrPteTypeId = GetPointeeTypeId(ptrInst);
-  std::vector<Operand> ext_in_opnds;
-  ext_in_opnds.push_back(Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
-                                 std::initializer_list<uint32_t>{ldResultId}));
-  uint32_t iidIdx = 0;
-  ptrInst->ForEachInId([&iidIdx, &ext_in_opnds, this](const uint32_t* iid) {
-    if (iidIdx > 0) {
-      const Instruction* cInst = get_def_use_mgr()->GetDef(*iid);
-      uint32_t val = cInst->GetSingleWordInOperand(kConstantValueInIdx);
-      ext_in_opnds.push_back(
-          Operand(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                  std::initializer_list<uint32_t>{val}));
-    }
-    ++iidIdx;
-  });
-  std::unique_ptr<Instruction> newExt(
-      new Instruction(context(), SpvOpCompositeExtract, ptrPteTypeId,
-                      extResultId, ext_in_opnds));
-  get_def_use_mgr()->AnalyzeInstDefUse(&*newExt);
-  newInsts->emplace_back(std::move(newExt));
-  *resultId = extResultId;
-}
-
-bool CommonUniformElimPass::IsConstantIndexAccessChain(Instruction* acp) {
-  uint32_t inIdx = 0;
-  return acp->WhileEachInId([&inIdx, this](uint32_t* tid) {
-    if (inIdx > 0) {
-      Instruction* opInst = get_def_use_mgr()->GetDef(*tid);
-      if (opInst->opcode() != SpvOpConstant) return false;
-    }
-    ++inIdx;
-    return true;
-  });
-}
-
-bool CommonUniformElimPass::UniformAccessChainConvert(Function* func) {
-  bool modified = false;
-  for (auto bi = func->begin(); bi != func->end(); ++bi) {
-    for (Instruction* inst = &*bi->begin(); inst; inst = inst->NextNode()) {
-      if (inst->opcode() != SpvOpLoad) continue;
-      uint32_t varId;
-      Instruction* ptrInst = GetPtr(inst, &varId);
-      if (!IsNonPtrAccessChain(ptrInst->opcode())) continue;
-      // Do not convert nested access chains
-      if (ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx) != varId)
-        continue;
-      if (!IsUniformVar(varId)) continue;
-      if (!IsConstantIndexAccessChain(ptrInst)) continue;
-      if (HasUnsupportedDecorates(inst->result_id())) continue;
-      if (HasUnsupportedDecorates(ptrInst->result_id())) continue;
-      if (IsVolatileLoad(*inst)) continue;
-      if (IsAccessChainToVolatileStructType(*ptrInst)) continue;
-      std::vector<std::unique_ptr<Instruction>> newInsts;
-      uint32_t replId;
-      GenACLoadRepl(ptrInst, &newInsts, &replId);
-      inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
-      assert(inst->opcode() != SpvOpPhi);
-      inst = inst->InsertBefore(std::move(newInsts));
-      modified = true;
-    }
-  }
-  return modified;
-}
-
-void CommonUniformElimPass::ComputeStructuredSuccessors(Function* func) {
-  block2structured_succs_.clear();
-  for (auto& blk : *func) {
-    // If header, make merge block first successor.
-    uint32_t mbid = blk.MergeBlockIdIfAny();
-    if (mbid != 0) {
-      block2structured_succs_[&blk].push_back(cfg()->block(mbid));
-      uint32_t cbid = blk.ContinueBlockIdIfAny();
-      if (cbid != 0) {
-        block2structured_succs_[&blk].push_back(cfg()->block(mbid));
-      }
-    }
-    // add true successors
-    const auto& const_blk = blk;
-    const_blk.ForEachSuccessorLabel([&blk, this](const uint32_t sbid) {
-      block2structured_succs_[&blk].push_back(cfg()->block(sbid));
-    });
-  }
-}
-
-void CommonUniformElimPass::ComputeStructuredOrder(
-    Function* func, std::list<BasicBlock*>* order) {
-  // Compute structured successors and do DFS
-  ComputeStructuredSuccessors(func);
-  auto ignore_block = [](cbb_ptr) {};
-  auto ignore_edge = [](cbb_ptr, cbb_ptr) {};
-  auto get_structured_successors = [this](const BasicBlock* block) {
-    return &(block2structured_succs_[block]);
-  };
-  // TODO(greg-lunarg): Get rid of const_cast by making moving const
-  // out of the cfa.h prototypes and into the invoking code.
-  auto post_order = [&](cbb_ptr b) {
-    order->push_front(const_cast<BasicBlock*>(b));
-  };
-
-  order->clear();
-  CFA<BasicBlock>::DepthFirstTraversal(&*func->begin(),
-                                       get_structured_successors, ignore_block,
-                                       post_order, ignore_edge);
-}
-
-bool CommonUniformElimPass::CommonUniformLoadElimination(Function* func) {
-  // Process all blocks in structured order. This is just one way (the
-  // simplest?) to keep track of the most recent block outside of control
-  // flow, used to copy common instructions, guaranteed to dominate all
-  // following load sites.
-  std::list<BasicBlock*> structuredOrder;
-  ComputeStructuredOrder(func, &structuredOrder);
-  uniform2load_id_.clear();
-  bool modified = false;
-  // Find insertion point in first block to copy non-dominating loads.
-  auto insertItr = func->begin()->begin();
-  while (insertItr->opcode() == SpvOpVariable ||
-         insertItr->opcode() == SpvOpNop)
-    ++insertItr;
-  // Update insertItr until it will not be removed. Without this code,
-  // ReplaceAndDeleteLoad() can set |insertItr| as a dangling pointer.
-  while (IsUniformLoadToBeRemoved(&*insertItr)) ++insertItr;
-  uint32_t mergeBlockId = 0;
-  for (auto bi = structuredOrder.begin(); bi != structuredOrder.end(); ++bi) {
-    BasicBlock* bp = *bi;
-    // Check if we are exiting outermost control construct. If so, remember
-    // new load insertion point. Trying to keep register pressure down.
-    if (mergeBlockId == bp->id()) {
-      mergeBlockId = 0;
-      insertItr = bp->begin();
-      while (insertItr->opcode() == SpvOpPhi) {
-        ++insertItr;
-      }
-
-      // Update insertItr until it will not be removed. Without this code,
-      // ReplaceAndDeleteLoad() can set |insertItr| as a dangling pointer.
-      while (IsUniformLoadToBeRemoved(&*insertItr)) ++insertItr;
-    }
-    for (Instruction* inst = &*bp->begin(); inst; inst = inst->NextNode()) {
-      if (inst->opcode() != SpvOpLoad) continue;
-      uint32_t varId;
-      Instruction* ptrInst = GetPtr(inst, &varId);
-      if (ptrInst->opcode() != SpvOpVariable) continue;
-      if (!IsUniformVar(varId)) continue;
-      if (IsSamplerOrImageVar(varId)) continue;
-      if (HasUnsupportedDecorates(inst->result_id())) continue;
-      if (IsVolatileLoad(*inst)) continue;
-      uint32_t replId;
-      const auto uItr = uniform2load_id_.find(varId);
-      if (uItr != uniform2load_id_.end()) {
-        replId = uItr->second;
-      } else {
-        if (mergeBlockId == 0) {
-          // Load is in dominating block; just remember it
-          uniform2load_id_[varId] = inst->result_id();
-          continue;
-        } else {
-          // Copy load into most recent dominating block and remember it
-          replId = TakeNextId();
-          std::unique_ptr<Instruction> newLoad(new Instruction(
-              context(), SpvOpLoad, inst->type_id(), replId,
-              {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {varId}}}));
-          get_def_use_mgr()->AnalyzeInstDefUse(&*newLoad);
-          insertItr = insertItr.InsertBefore(std::move(newLoad));
-          ++insertItr;
-          uniform2load_id_[varId] = replId;
-        }
-      }
-      inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
-      modified = true;
-    }
-    // If we are outside of any control construct and entering one, remember
-    // the id of the merge block
-    if (mergeBlockId == 0) {
-      mergeBlockId = bp->MergeBlockIdIfAny();
-    }
-  }
-  return modified;
-}
-
-bool CommonUniformElimPass::CommonUniformLoadElimBlock(Function* func) {
-  bool modified = false;
-  for (auto& blk : *func) {
-    uniform2load_id_.clear();
-    for (Instruction* inst = &*blk.begin(); inst; inst = inst->NextNode()) {
-      if (inst->opcode() != SpvOpLoad) continue;
-      uint32_t varId;
-      Instruction* ptrInst = GetPtr(inst, &varId);
-      if (ptrInst->opcode() != SpvOpVariable) continue;
-      if (!IsUniformVar(varId)) continue;
-      if (!IsSamplerOrImageVar(varId)) continue;
-      if (HasUnsupportedDecorates(inst->result_id())) continue;
-      if (IsVolatileLoad(*inst)) continue;
-      uint32_t replId;
-      const auto uItr = uniform2load_id_.find(varId);
-      if (uItr != uniform2load_id_.end()) {
-        replId = uItr->second;
-      } else {
-        uniform2load_id_[varId] = inst->result_id();
-        continue;
-      }
-      inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
-      modified = true;
-    }
-  }
-  return modified;
-}
-
-bool CommonUniformElimPass::CommonExtractElimination(Function* func) {
-  // Find all composite ids with duplicate extracts.
-  for (auto bi = func->begin(); bi != func->end(); ++bi) {
-    for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
-      if (ii->opcode() != SpvOpCompositeExtract) continue;
-      // TODO(greg-lunarg): Support multiple indices
-      if (ii->NumInOperands() > 2) continue;
-      if (HasUnsupportedDecorates(ii->result_id())) continue;
-      uint32_t compId = ii->GetSingleWordInOperand(kExtractCompositeIdInIdx);
-      uint32_t idx = ii->GetSingleWordInOperand(kExtractIdx0InIdx);
-      comp2idx2inst_[compId][idx].push_back(&*ii);
-    }
-  }
-  // For all defs of ids with duplicate extracts, insert new extracts
-  // after def, and replace and delete old extracts
-  bool modified = false;
-  for (auto bi = func->begin(); bi != func->end(); ++bi) {
-    for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
-      const auto cItr = comp2idx2inst_.find(ii->result_id());
-      if (cItr == comp2idx2inst_.end()) continue;
-      for (auto idxItr : cItr->second) {
-        if (idxItr.second.size() < 2) continue;
-        uint32_t replId = TakeNextId();
-        std::unique_ptr<Instruction> newExtract(
-            idxItr.second.front()->Clone(context()));
-        newExtract->SetResultId(replId);
-        get_def_use_mgr()->AnalyzeInstDefUse(&*newExtract);
-        ++ii;
-        ii = ii.InsertBefore(std::move(newExtract));
-        for (auto instItr : idxItr.second) {
-          uint32_t resId = instItr->result_id();
-          context()->KillNamesAndDecorates(resId);
-          (void)context()->ReplaceAllUsesWith(resId, replId);
-          context()->KillInst(instItr);
-        }
-        modified = true;
-      }
-    }
-  }
-  return modified;
-}
-
-bool CommonUniformElimPass::EliminateCommonUniform(Function* func) {
-  bool modified = false;
-  modified |= UniformAccessChainConvert(func);
-  modified |= CommonUniformLoadElimination(func);
-  modified |= CommonExtractElimination(func);
-
-  modified |= CommonUniformLoadElimBlock(func);
-  return modified;
-}
-
-void CommonUniformElimPass::Initialize() {
-  // Clear collections.
-  comp2idx2inst_.clear();
-
-  // Initialize extension whitelist
-  InitExtensions();
-}
-
-bool CommonUniformElimPass::AllExtensionsSupported() const {
-  // If any extension not in whitelist, return false
-  for (auto& ei : get_module()->extensions()) {
-    const char* extName =
-        reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
-    if (extensions_whitelist_.find(extName) == extensions_whitelist_.end())
-      return false;
-  }
-  return true;
-}
-
-Pass::Status CommonUniformElimPass::ProcessImpl() {
-  // Assumes all control flow structured.
-  // TODO(greg-lunarg): Do SSA rewrite for non-structured control flow
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
-    return Status::SuccessWithoutChange;
-  // Assumes logical addressing only
-  // TODO(greg-lunarg): Add support for physical addressing
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
-    return Status::SuccessWithoutChange;
-  if (context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointersStorageBuffer))
-    return Status::SuccessWithoutChange;
-  // Do not process if any disallowed extensions are enabled
-  if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
-  // Do not process if module contains OpGroupDecorate. Additional
-  // support required in KillNamesAndDecorates().
-  // TODO(greg-lunarg): Add support for OpGroupDecorate
-  for (auto& ai : get_module()->annotations())
-    if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
-  // If non-32-bit integer type in module, terminate processing
-  // TODO(): Handle non-32-bit integer constants in access chains
-  for (const Instruction& inst : get_module()->types_values())
-    if (inst.opcode() == SpvOpTypeInt &&
-        inst.GetSingleWordInOperand(kTypeIntWidthInIdx) != 32)
-      return Status::SuccessWithoutChange;
-  // Process entry point functions
-  ProcessFunction pfn = [this](Function* fp) {
-    return EliminateCommonUniform(fp);
-  };
-  bool modified = context()->ProcessEntryPointCallTree(pfn);
-  return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
-}
-
-CommonUniformElimPass::CommonUniformElimPass() = default;
-
-Pass::Status CommonUniformElimPass::Process() {
-  Initialize();
-  return ProcessImpl();
-}
-
-void CommonUniformElimPass::InitExtensions() {
-  extensions_whitelist_.clear();
-  extensions_whitelist_.insert({
-      "SPV_AMD_shader_explicit_vertex_parameter",
-      "SPV_AMD_shader_trinary_minmax",
-      "SPV_AMD_gcn_shader",
-      "SPV_KHR_shader_ballot",
-      "SPV_AMD_shader_ballot",
-      "SPV_AMD_gpu_shader_half_float",
-      "SPV_KHR_shader_draw_parameters",
-      "SPV_KHR_subgroup_vote",
-      "SPV_KHR_16bit_storage",
-      "SPV_KHR_device_group",
-      "SPV_KHR_multiview",
-      "SPV_NVX_multiview_per_view_attributes",
-      "SPV_NV_viewport_array2",
-      "SPV_NV_stereo_view_rendering",
-      "SPV_NV_sample_mask_override_coverage",
-      "SPV_NV_geometry_shader_passthrough",
-      "SPV_AMD_texture_gather_bias_lod",
-      "SPV_KHR_storage_buffer_storage_class",
-      // SPV_KHR_variable_pointers
-      //   Currently do not support extended pointer expressions
-      "SPV_AMD_gpu_shader_int16",
-      "SPV_KHR_post_depth_coverage",
-      "SPV_KHR_shader_atomic_counter_ops",
-      "SPV_EXT_shader_stencil_export",
-      "SPV_EXT_shader_viewport_index_layer",
-      "SPV_AMD_shader_image_load_store_lod",
-      "SPV_AMD_shader_fragment_mask",
-      "SPV_EXT_fragment_fully_covered",
-      "SPV_AMD_gpu_shader_half_float_fetch",
-      "SPV_GOOGLE_decorate_string",
-      "SPV_GOOGLE_hlsl_functionality1",
-      "SPV_GOOGLE_user_type",
-      "SPV_NV_shader_subgroup_partitioned",
-      "SPV_EXT_descriptor_indexing",
-      "SPV_NV_fragment_shader_barycentric",
-      "SPV_NV_compute_shader_derivatives",
-      "SPV_NV_shader_image_footprint",
-      "SPV_NV_shading_rate",
-      "SPV_NV_mesh_shader",
-      "SPV_NV_ray_tracing",
-      "SPV_EXT_fragment_invocation_density",
-  });
-}
-
-}  // namespace opt
-}  // namespace spvtools
diff --git a/source/opt/common_uniform_elim_pass.h b/source/opt/common_uniform_elim_pass.h
deleted file mode 100644
index e6ef69c..0000000
--- a/source/opt/common_uniform_elim_pass.h
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright (c) 2016 The Khronos Group Inc.
-// Copyright (c) 2016 Valve Corporation
-// Copyright (c) 2016 LunarG Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SOURCE_OPT_COMMON_UNIFORM_ELIM_PASS_H_
-#define SOURCE_OPT_COMMON_UNIFORM_ELIM_PASS_H_
-
-#include <algorithm>
-#include <list>
-#include <map>
-#include <memory>
-#include <queue>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-#include "source/opt/basic_block.h"
-#include "source/opt/decoration_manager.h"
-#include "source/opt/def_use_manager.h"
-#include "source/opt/ir_context.h"
-#include "source/opt/module.h"
-#include "source/opt/pass.h"
-
-namespace spvtools {
-namespace opt {
-
-// See optimizer.hpp for documentation.
-class CommonUniformElimPass : public Pass {
-  using cbb_ptr = const BasicBlock*;
-
- public:
-  using GetBlocksFunction =
-      std::function<std::vector<BasicBlock*>*(const BasicBlock*)>;
-
-  CommonUniformElimPass();
-
-  const char* name() const override { return "eliminate-common-uniform"; }
-  Status Process() override;
-
- private:
-  // Returns true if |opcode| is a non-ptr access chain op
-  bool IsNonPtrAccessChain(const SpvOp opcode) const;
-
-  // Returns true if |typeInst| is a sampler or image type or a struct
-  // containing one, recursively.
-  bool IsSamplerOrImageType(const Instruction* typeInst) const;
-
-  // Returns true if |varId| is a variable containing a sampler or image.
-  bool IsSamplerOrImageVar(uint32_t varId) const;
-
-  // Given a load or store pointed at by |ip|, return the top-most
-  // non-CopyObj in its pointer operand. Also return the base pointer
-  // in |objId|.
-  Instruction* GetPtr(Instruction* ip, uint32_t* objId);
-
-  // Return true if variable is uniform
-  bool IsUniformVar(uint32_t varId);
-
-  // Given the type id for a struct type, checks if the struct type
-  // or any struct member is volatile decorated
-  bool IsVolatileStruct(uint32_t type_id);
-
-  // Given an OpAccessChain instruction, return true
-  // if the accessed variable belongs to a volatile
-  // decorated object or member of a struct type
-  bool IsAccessChainToVolatileStructType(const Instruction& AccessChainInst);
-
-  // Given an OpLoad instruction, return true if
-  // OpLoad has a Volatile Memory Access flag or if
-  // the resulting type is a volatile decorated struct
-  bool IsVolatileLoad(const Instruction& loadInst);
-
-  // Return true if any uses of |id| are decorate ops.
-  bool HasUnsupportedDecorates(uint32_t id) const;
-
-  // Return true if all uses of |id| are only name or decorate ops.
-  bool HasOnlyNamesAndDecorates(uint32_t id) const;
-
-  // Delete inst if it has no uses. Assumes inst has a resultId.
-  void DeleteIfUseless(Instruction* inst);
-
-  // Replace all instances of load's id with replId and delete load
-  // and its access chain, if any
-  Instruction* ReplaceAndDeleteLoad(Instruction* loadInst, uint32_t replId,
-                                    Instruction* ptrInst);
-
-  // For the (constant index) access chain ptrInst, create an
-  // equivalent load and extract
-  void GenACLoadRepl(const Instruction* ptrInst,
-                     std::vector<std::unique_ptr<Instruction>>* newInsts,
-                     uint32_t* resultId);
-
-  // Return true if all indices are constant
-  bool IsConstantIndexAccessChain(Instruction* acp);
-
-  // Convert all uniform access chain loads into load/extract.
-  bool UniformAccessChainConvert(Function* func);
-
-  // Compute structured successors for function |func|.
-  // A block's structured successors are the blocks it branches to
-  // together with its declared merge block if it has one.
-  // When order matters, the merge block always appears first.
-  // This assures correct depth first search in the presence of early
-  // returns and kills. If the successor vector contain duplicates
-  // if the merge block, they are safely ignored by DFS.
-  //
-  // TODO(dnovillo): This pass computes structured successors slightly different
-  // than the implementation in class Pass. Can this be re-factored?
-  void ComputeStructuredSuccessors(Function* func);
-
-  // Compute structured block order for |func| into |structuredOrder|. This
-  // order has the property that dominators come before all blocks they
-  // dominate and merge blocks come after all blocks that are in the control
-  // constructs of their header.
-  //
-  // TODO(dnovillo): This pass computes structured order slightly different
-  // than the implementation in class Pass. Can this be re-factored?
-  void ComputeStructuredOrder(Function* func, std::list<BasicBlock*>* order);
-
-  // Eliminate loads of uniform variables which have previously been loaded.
-  // If first load is in control flow, move it to first block of function.
-  // Most effective if preceded by UniformAccessChainRemoval().
-  bool CommonUniformLoadElimination(Function* func);
-
-  // Eliminate loads of uniform sampler and image variables which have
-  // previously
-  // been loaded in the same block for types whose loads cannot cross blocks.
-  bool CommonUniformLoadElimBlock(Function* func);
-
-  // Eliminate duplicated extracts of same id. Extract may be moved to same
-  // block as the id definition. This is primarily intended for extracts
-  // from uniform loads. Most effective if preceded by
-  // CommonUniformLoadElimination().
-  bool CommonExtractElimination(Function* func);
-
-  // For function |func|, first change all uniform constant index
-  // access chain loads into equivalent composite extracts. Then consolidate
-  // identical uniform loads into one uniform load. Finally, consolidate
-  // identical uniform extracts into one uniform extract. This may require
-  // moving a load or extract to a point which dominates all uses.
-  // Return true if func is modified.
-  //
-  // This pass requires the function to have structured control flow ie shader
-  // capability. It also requires logical addressing ie Addresses capability
-  // is not enabled. It also currently does not support any extensions.
-  //
-  // This function currently only optimizes loads with a single index.
-  bool EliminateCommonUniform(Function* func);
-
-  // Initialize extensions whitelist
-  void InitExtensions();
-
-  // Return true if all extensions in this module are allowed by this pass.
-  bool AllExtensionsSupported() const;
-
-  // Return true if |op| is a decorate for non-type instruction
-  inline bool IsNonTypeDecorate(uint32_t op) const {
-    return (op == SpvOpDecorate || op == SpvOpDecorateId);
-  }
-
-  // Return true if |inst| is an instruction that loads uniform variable and
-  // can be replaced with other uniform load instruction.
-  bool IsUniformLoadToBeRemoved(Instruction* inst) {
-    if (inst->opcode() == SpvOpLoad) {
-      uint32_t varId;
-      Instruction* ptrInst = GetPtr(inst, &varId);
-      if (ptrInst->opcode() == SpvOpVariable && IsUniformVar(varId) &&
-          !IsSamplerOrImageVar(varId) &&
-          !HasUnsupportedDecorates(inst->result_id()) && !IsVolatileLoad(*inst))
-        return true;
-    }
-    return false;
-  }
-
-  void Initialize();
-  Pass::Status ProcessImpl();
-
-  // Map from uniform variable id to its common load id
-  std::unordered_map<uint32_t, uint32_t> uniform2load_id_;
-
-  // Map of extract composite ids to map of indices to insts
-  // TODO(greg-lunarg): Consider std::vector.
-  std::unordered_map<uint32_t,
-                     std::unordered_map<uint32_t, std::list<Instruction*>>>
-      comp2idx2inst_;
-
-  // Extensions supported by this pass.
-  std::unordered_set<std::string> extensions_whitelist_;
-
-  // Map from block to its structured successor blocks. See
-  // ComputeStructuredSuccessors() for definition.
-  std::unordered_map<const BasicBlock*, std::vector<BasicBlock*>>
-      block2structured_succs_;
-};
-
-}  // namespace opt
-}  // namespace spvtools
-
-#endif  // SOURCE_OPT_COMMON_UNIFORM_ELIM_PASS_H_
diff --git a/source/opt/optimizer.cpp b/source/opt/optimizer.cpp
index 6206f64..5c1e6ca 100644
--- a/source/opt/optimizer.cpp
+++ b/source/opt/optimizer.cpp
@@ -186,8 +186,6 @@
       .RegisterPass(CreateDeadBranchElimPass())
       .RegisterPass(CreateBlockMergePass())
       .RegisterPass(CreateSimplificationPass());
-  // Currently exposing driver bugs resulting in crashes (#946)
-  // .RegisterPass(CreateCommonUniformElimPass())
 }
 
 Optimizer& Optimizer::RegisterSizePasses() {
@@ -215,8 +213,6 @@
       .RegisterPass(CreateDeadInsertElimPass())
       .RegisterPass(CreateRedundancyEliminationPass())
       .RegisterPass(CreateCFGCleanupPass())
-      // Currently exposing driver bugs resulting in crashes (#946)
-      // .RegisterPass(CreateCommonUniformElimPass())
       .RegisterPass(CreateAggressiveDCEPass());
 }
 
@@ -340,8 +336,6 @@
     RegisterPass(CreateEliminateDeadFunctionsPass());
   } else if (pass_name == "eliminate-local-multi-store") {
     RegisterPass(CreateLocalMultiStoreElimPass());
-  } else if (pass_name == "eliminate-common-uniform") {
-    RegisterPass(CreateCommonUniformElimPass());
   } else if (pass_name == "eliminate-dead-const") {
     RegisterPass(CreateEliminateDeadConstantPass());
   } else if (pass_name == "eliminate-dead-inserts") {
@@ -713,11 +707,6 @@
       MakeUnique<opt::ProcessLinesPass>(opt::kLinesEliminateDeadLines));
 }
 
-Optimizer::PassToken CreateCommonUniformElimPass() {
-  return MakeUnique<Optimizer::PassToken::Impl>(
-      MakeUnique<opt::CommonUniformElimPass>());
-}
-
 Optimizer::PassToken CreateCompactIdsPass() {
   return MakeUnique<Optimizer::PassToken::Impl>(
       MakeUnique<opt::CompactIdsPass>());
diff --git a/source/opt/passes.h b/source/opt/passes.h
index b7a9cb0..0a348e4 100644
--- a/source/opt/passes.h
+++ b/source/opt/passes.h
@@ -23,7 +23,6 @@
 #include "source/opt/cfg_cleanup_pass.h"
 #include "source/opt/code_sink.h"
 #include "source/opt/combine_access_chains.h"
-#include "source/opt/common_uniform_elim_pass.h"
 #include "source/opt/compact_ids_pass.h"
 #include "source/opt/copy_prop_arrays.h"
 #include "source/opt/dead_branch_elim_pass.h"
diff --git a/test/opt/CMakeLists.txt b/test/opt/CMakeLists.txt
index ba29cf8..246c116 100644
--- a/test/opt/CMakeLists.txt
+++ b/test/opt/CMakeLists.txt
@@ -24,7 +24,6 @@
        cfg_test.cpp
        code_sink_test.cpp
        combine_access_chains_test.cpp
-       common_uniform_elim_test.cpp
        compact_ids_test.cpp
        constant_manager_test.cpp
        copy_prop_array_test.cpp
diff --git a/test/opt/common_uniform_elim_test.cpp b/test/opt/common_uniform_elim_test.cpp
deleted file mode 100644
index 923f786..0000000
--- a/test/opt/common_uniform_elim_test.cpp
+++ /dev/null
@@ -1,1479 +0,0 @@
-// Copyright (c) 2017 Valve Corporation
-// Copyright (c) 2017 LunarG Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <string>
-
-#include "test/opt/pass_fixture.h"
-
-namespace spvtools {
-namespace opt {
-namespace {
-
-using CommonUniformElimTest = PassTest<::testing::Test>;
-
-TEST_F(CommonUniformElimTest, Basic1) {
-  // Note: This test exemplifies the following:
-  // - Common uniform (%_) load floated to nearest non-controlled block
-  // - Common extract (g_F) floated to non-controlled block
-  // - Non-common extract (g_F2) not floated, but common uniform load shared
-  //
-  // #version 140
-  // in vec4 BaseColor;
-  // in float fi;
-  //
-  // layout(std140) uniform U_t
-  // {
-  //     float g_F;
-  //     float g_F2;
-  // } ;
-  //
-  // void main()
-  // {
-  //     vec4 v = BaseColor;
-  //     if (fi > 0) {
-  //       v = v * g_F;
-  //     }
-  //     else {
-  //       float f2 = g_F2 - g_F;
-  //       v = v * f2;
-  //     }
-  //     gl_FragColor = v;
-  // }
-
-  const std::string predefs =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpName %gl_FragColor "gl_FragColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%11 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
-  const std::string before =
-      R"(%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%34 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%35 = OpLoad %float %34
-%36 = OpVectorTimesScalar %v4float %33 %35
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%37 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%38 = OpLoad %float %37
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39
-%41 = OpFSub %float %38 %40
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string after =
-      R"(%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%52 = OpLoad %U_t %_
-%53 = OpCompositeExtract %float %52 0
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%36 = OpVectorTimesScalar %v4float %33 %53
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%49 = OpCompositeExtract %float %52 1
-%41 = OpFSub %float %49 %53
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
-                                               predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Basic2) {
-  // Note: This test exemplifies the following:
-  // - Common uniform (%_) load floated to nearest non-controlled block
-  // - Common extract (g_F) floated to non-controlled block
-  // - Non-common extract (g_F2) not floated, but common uniform load shared
-  //
-  // #version 140
-  // in vec4 BaseColor;
-  // in float fi;
-  // in float fi2;
-  //
-  // layout(std140) uniform U_t
-  // {
-  //     float g_F;
-  //     float g_F2;
-  // } ;
-  //
-  // void main()
-  // {
-  //     float f = fi;
-  //     if (f < 0)
-  //       f = -f;
-  //     if (fi2 > 0) {
-  //       f = f * g_F;
-  //     }
-  //     else {
-  //       f = g_F2 - g_F;
-  //     }
-  //     gl_FragColor = f * BaseColor;
-  // }
-
-  const std::string predefs =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %fi %fi2 %gl_FragColor %BaseColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %f "f"
-OpName %fi "fi"
-OpName %fi2 "fi2"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %gl_FragColor "gl_FragColor"
-OpName %BaseColor "BaseColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%11 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%_ptr_Function_float = OpTypePointer Function %float
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%fi2 = OpVariable %_ptr_Input_float Input
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%int_1 = OpConstant %int 1
-%v4float = OpTypeVector %float 4
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-)";
-
-  const std::string before =
-      R"(%main = OpFunction %void None %11
-%25 = OpLabel
-%f = OpVariable %_ptr_Function_float Function
-%26 = OpLoad %float %fi
-OpStore %f %26
-%27 = OpLoad %float %f
-%28 = OpFOrdLessThan %bool %27 %float_0
-OpSelectionMerge %29 None
-OpBranchConditional %28 %30 %29
-%30 = OpLabel
-%31 = OpLoad %float %f
-%32 = OpFNegate %float %31
-OpStore %f %32
-OpBranch %29
-%29 = OpLabel
-%33 = OpLoad %float %fi2
-%34 = OpFOrdGreaterThan %bool %33 %float_0
-OpSelectionMerge %35 None
-OpBranchConditional %34 %36 %37
-%36 = OpLabel
-%38 = OpLoad %float %f
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39
-%41 = OpFMul %float %38 %40
-OpStore %f %41
-OpBranch %35
-%37 = OpLabel
-%42 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%43 = OpLoad %float %42
-%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%45 = OpLoad %float %44
-%46 = OpFSub %float %43 %45
-OpStore %f %46
-OpBranch %35
-%35 = OpLabel
-%47 = OpLoad %v4float %BaseColor
-%48 = OpLoad %float %f
-%49 = OpVectorTimesScalar %v4float %47 %48
-OpStore %gl_FragColor %49
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string after =
-      R"(%main = OpFunction %void None %11
-%25 = OpLabel
-%f = OpVariable %_ptr_Function_float Function
-%26 = OpLoad %float %fi
-OpStore %f %26
-%27 = OpLoad %float %f
-%28 = OpFOrdLessThan %bool %27 %float_0
-OpSelectionMerge %29 None
-OpBranchConditional %28 %30 %29
-%30 = OpLabel
-%31 = OpLoad %float %f
-%32 = OpFNegate %float %31
-OpStore %f %32
-OpBranch %29
-%29 = OpLabel
-%56 = OpLoad %U_t %_
-%57 = OpCompositeExtract %float %56 0
-%33 = OpLoad %float %fi2
-%34 = OpFOrdGreaterThan %bool %33 %float_0
-OpSelectionMerge %35 None
-OpBranchConditional %34 %36 %37
-%36 = OpLabel
-%38 = OpLoad %float %f
-%41 = OpFMul %float %38 %57
-OpStore %f %41
-OpBranch %35
-%37 = OpLabel
-%53 = OpCompositeExtract %float %56 1
-%46 = OpFSub %float %53 %57
-OpStore %f %46
-OpBranch %35
-%35 = OpLabel
-%47 = OpLoad %v4float %BaseColor
-%48 = OpLoad %float %f
-%49 = OpVectorTimesScalar %v4float %47 %48
-OpStore %gl_FragColor %49
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
-                                               predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Basic3) {
-  // Note: This test exemplifies the following:
-  // - Existing common uniform (%_) load kept in place and shared
-  //
-  // #version 140
-  // in vec4 BaseColor;
-  // in float fi;
-  //
-  // layout(std140) uniform U_t
-  // {
-  //     bool g_B;
-  //     float g_F;
-  // } ;
-  //
-  // void main()
-  // {
-  //     vec4 v = BaseColor;
-  //     if (g_B)
-  //       v = v * g_F;
-  //     gl_FragColor = v;
-  // }
-
-  const std::string predefs =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor %fi
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_B"
-OpMemberName %U_t 1 "g_F"
-OpName %_ ""
-OpName %gl_FragColor "gl_FragColor"
-OpName %fi "fi"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%10 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%uint = OpTypeInt 32 0
-%U_t = OpTypeStruct %uint %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%bool = OpTypeBool
-%uint_0 = OpConstant %uint 0
-%int_1 = OpConstant %int 1
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-)";
-
-  const std::string before =
-      R"(%main = OpFunction %void None %10
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
-%29 = OpLoad %uint %28
-%30 = OpINotEqual %bool %29 %uint_0
-OpSelectionMerge %31 None
-OpBranchConditional %30 %32 %31
-%32 = OpLabel
-%33 = OpLoad %v4float %v
-%34 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%35 = OpLoad %float %34
-%36 = OpVectorTimesScalar %v4float %33 %35
-OpStore %v %36
-OpBranch %31
-%31 = OpLabel
-%37 = OpLoad %v4float %v
-OpStore %gl_FragColor %37
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string after =
-      R"(%main = OpFunction %void None %10
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%38 = OpLoad %U_t %_
-%39 = OpCompositeExtract %uint %38 0
-%30 = OpINotEqual %bool %39 %uint_0
-OpSelectionMerge %31 None
-OpBranchConditional %30 %32 %31
-%32 = OpLabel
-%33 = OpLoad %v4float %v
-%41 = OpCompositeExtract %float %38 1
-%36 = OpVectorTimesScalar %v4float %33 %41
-OpStore %v %36
-OpBranch %31
-%31 = OpLabel
-%37 = OpLoad %v4float %v
-OpStore %gl_FragColor %37
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
-                                               predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Loop) {
-  // Note: This test exemplifies the following:
-  // - Common extract (g_F) shared between two loops
-  // #version 140
-  // in vec4 BC;
-  // in vec4 BC2;
-  //
-  // layout(std140) uniform U_t
-  // {
-  //     float g_F;
-  // } ;
-  //
-  // void main()
-  // {
-  //     vec4 v = BC;
-  //     for (int i = 0; i < 4; i++)
-  //       v[i] = v[i] / g_F;
-  //     vec4 v2 = BC2;
-  //     for (int i = 0; i < 4; i++)
-  //       v2[i] = v2[i] * g_F;
-  //     gl_FragColor = v + v2;
-  // }
-
-  const std::string predefs =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BC %BC2 %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BC "BC"
-OpName %i "i"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpName %_ ""
-OpName %v2 "v2"
-OpName %BC2 "BC2"
-OpName %i_0 "i"
-OpName %gl_FragColor "gl_FragColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%13 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BC = OpVariable %_ptr_Input_v4float Input
-%int = OpTypeInt 32 1
-%_ptr_Function_int = OpTypePointer Function %int
-%int_0 = OpConstant %int 0
-%int_4 = OpConstant %int 4
-%bool = OpTypeBool
-%_ptr_Function_float = OpTypePointer Function %float
-%U_t = OpTypeStruct %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%int_1 = OpConstant %int 1
-%BC2 = OpVariable %_ptr_Input_v4float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
-  const std::string before =
-      R"(%main = OpFunction %void None %13
-%28 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%i = OpVariable %_ptr_Function_int Function
-%v2 = OpVariable %_ptr_Function_v4float Function
-%i_0 = OpVariable %_ptr_Function_int Function
-%29 = OpLoad %v4float %BC
-OpStore %v %29
-OpStore %i %int_0
-OpBranch %30
-%30 = OpLabel
-OpLoopMerge %31 %32 None
-OpBranch %33
-%33 = OpLabel
-%34 = OpLoad %int %i
-%35 = OpSLessThan %bool %34 %int_4
-OpBranchConditional %35 %36 %31
-%36 = OpLabel
-%37 = OpLoad %int %i
-%38 = OpLoad %int %i
-%39 = OpAccessChain %_ptr_Function_float %v %38
-%40 = OpLoad %float %39
-%41 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%42 = OpLoad %float %41
-%43 = OpFDiv %float %40 %42
-%44 = OpAccessChain %_ptr_Function_float %v %37
-OpStore %44 %43
-OpBranch %32
-%32 = OpLabel
-%45 = OpLoad %int %i
-%46 = OpIAdd %int %45 %int_1
-OpStore %i %46
-OpBranch %30
-%31 = OpLabel
-%47 = OpLoad %v4float %BC2
-OpStore %v2 %47
-OpStore %i_0 %int_0
-OpBranch %48
-%48 = OpLabel
-OpLoopMerge %49 %50 None
-OpBranch %51
-%51 = OpLabel
-%52 = OpLoad %int %i_0
-%53 = OpSLessThan %bool %52 %int_4
-OpBranchConditional %53 %54 %49
-%54 = OpLabel
-%55 = OpLoad %int %i_0
-%56 = OpLoad %int %i_0
-%57 = OpAccessChain %_ptr_Function_float %v2 %56
-%58 = OpLoad %float %57
-%59 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%60 = OpLoad %float %59
-%61 = OpFMul %float %58 %60
-%62 = OpAccessChain %_ptr_Function_float %v2 %55
-OpStore %62 %61
-OpBranch %50
-%50 = OpLabel
-%63 = OpLoad %int %i_0
-%64 = OpIAdd %int %63 %int_1
-OpStore %i_0 %64
-OpBranch %48
-%49 = OpLabel
-%65 = OpLoad %v4float %v
-%66 = OpLoad %v4float %v2
-%67 = OpFAdd %v4float %65 %66
-OpStore %gl_FragColor %67
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string after =
-      R"(%main = OpFunction %void None %13
-%28 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%i = OpVariable %_ptr_Function_int Function
-%v2 = OpVariable %_ptr_Function_v4float Function
-%i_0 = OpVariable %_ptr_Function_int Function
-%72 = OpLoad %U_t %_
-%73 = OpCompositeExtract %float %72 0
-%29 = OpLoad %v4float %BC
-OpStore %v %29
-OpStore %i %int_0
-OpBranch %30
-%30 = OpLabel
-OpLoopMerge %31 %32 None
-OpBranch %33
-%33 = OpLabel
-%34 = OpLoad %int %i
-%35 = OpSLessThan %bool %34 %int_4
-OpBranchConditional %35 %36 %31
-%36 = OpLabel
-%37 = OpLoad %int %i
-%38 = OpLoad %int %i
-%39 = OpAccessChain %_ptr_Function_float %v %38
-%40 = OpLoad %float %39
-%43 = OpFDiv %float %40 %73
-%44 = OpAccessChain %_ptr_Function_float %v %37
-OpStore %44 %43
-OpBranch %32
-%32 = OpLabel
-%45 = OpLoad %int %i
-%46 = OpIAdd %int %45 %int_1
-OpStore %i %46
-OpBranch %30
-%31 = OpLabel
-%47 = OpLoad %v4float %BC2
-OpStore %v2 %47
-OpStore %i_0 %int_0
-OpBranch %48
-%48 = OpLabel
-OpLoopMerge %49 %50 None
-OpBranch %51
-%51 = OpLabel
-%52 = OpLoad %int %i_0
-%53 = OpSLessThan %bool %52 %int_4
-OpBranchConditional %53 %54 %49
-%54 = OpLabel
-%55 = OpLoad %int %i_0
-%56 = OpLoad %int %i_0
-%57 = OpAccessChain %_ptr_Function_float %v2 %56
-%58 = OpLoad %float %57
-%61 = OpFMul %float %58 %73
-%62 = OpAccessChain %_ptr_Function_float %v2 %55
-OpStore %62 %61
-OpBranch %50
-%50 = OpLabel
-%63 = OpLoad %int %i_0
-%64 = OpIAdd %int %63 %int_1
-OpStore %i_0 %64
-OpBranch %48
-%49 = OpLabel
-%65 = OpLoad %v4float %v
-%66 = OpLoad %v4float %v2
-%67 = OpFAdd %v4float %65 %66
-OpStore %gl_FragColor %67
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
-                                               predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Volatile1) {
-  // Note: This test exemplifies the following:
-  // - Same test as Basic1 with the exception that
-  //   the Load of g_F in else-branch is volatile
-  // - Common uniform (%_) load floated to nearest non-controlled block
-  //
-  // #version 140
-  // in vec4 BaseColor;
-  // in float fi;
-  //
-  // layout(std140) uniform U_t
-  // {
-  //     float g_F;
-  //     float g_F2;
-  // } ;
-  //
-  // void main()
-  // {
-  //     vec4 v = BaseColor;
-  //     if (fi > 0) {
-  //       v = v * g_F;
-  //     }
-  //     else {
-  //       float f2 = g_F2 - g_F;
-  //       v = v * f2;
-  //     }
-  //     gl_FragColor = v;
-  // }
-
-  const std::string predefs =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpName %gl_FragColor "gl_FragColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%11 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-)";
-
-  const std::string before =
-      R"(%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%34 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%35 = OpLoad %float %34
-%36 = OpVectorTimesScalar %v4float %33 %35
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%37 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%38 = OpLoad %float %37
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39 Volatile
-%41 = OpFSub %float %38 %40
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string after =
-      R"(%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%50 = OpLoad %U_t %_
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%47 = OpCompositeExtract %float %50 0
-%36 = OpVectorTimesScalar %v4float %33 %47
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%49 = OpCompositeExtract %float %50 1
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39 Volatile
-%41 = OpFSub %float %49 %40
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
-                                               predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, Volatile2) {
-  // Note: This test exemplifies the following:
-  // - Same test as Basic1 with the exception that
-  //   U_t is Volatile.
-  // - No optimizations are applied
-  //
-  // #version 430
-  // in vec4 BaseColor;
-  // in float fi;
-  //
-  // layout(std430) volatile buffer U_t
-  // {
-  //   float g_F;
-  //   float g_F2;
-  // };
-  //
-  //
-  // void main(void)
-  // {
-  //   vec4 v = BaseColor;
-  //   if (fi > 0) {
-  //     v = v * g_F;
-  //   } else {
-  //     float f2 = g_F2 - g_F;
-  //     v = v * f2;
-  //   }
-  // }
-
-  const std::string text =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 430
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpDecorate %BaseColor Location 0
-OpDecorate %fi Location 0
-OpMemberDecorate %U_t 0 Volatile
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Volatile
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t BufferBlock
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%3 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%main = OpFunction %void None %3
-%5 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%12 = OpLoad %v4float %BaseColor
-OpStore %v %12
-%15 = OpLoad %float %fi
-%18 = OpFOrdGreaterThan %bool %15 %float_0
-OpSelectionMerge %20 None
-OpBranchConditional %18 %19 %31
-%19 = OpLabel
-%21 = OpLoad %v4float %v
-%28 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%29 = OpLoad %float %28
-%30 = OpVectorTimesScalar %v4float %21 %29
-OpStore %v %30
-OpBranch %20
-%31 = OpLabel
-%35 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%36 = OpLoad %float %35
-%37 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%38 = OpLoad %float %37
-%39 = OpFSub %float %36 %38
-OpStore %f2 %39
-%40 = OpLoad %v4float %v
-%41 = OpLoad %float %f2
-%42 = OpVectorTimesScalar %v4float %40 %41
-OpStore %v %42
-OpBranch %20
-%20 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  Pass::Status res = std::get<1>(
-      SinglePassRunAndDisassemble<CommonUniformElimPass>(text, true, false));
-  EXPECT_EQ(res, Pass::Status::SuccessWithoutChange);
-}
-
-TEST_F(CommonUniformElimTest, Volatile3) {
-  // Note: This test exemplifies the following:
-  // - Same test as Volatile2 with the exception that
-  //   the nested struct S is volatile
-  // - No optimizations are applied
-  //
-  // #version 430
-  // in vec4 BaseColor;
-  // in float fi;
-  //
-  // struct S {
-  //   volatile float a;
-  // };
-  //
-  // layout(std430) buffer U_t
-  // {
-  //   S g_F;
-  //   S g_F2;
-  // };
-  //
-  //
-  // void main(void)
-  // {
-  //   vec4 v = BaseColor;
-  //   if (fi > 0) {
-  //     v = v * g_F.a;
-  //   } else {
-  //     float f2 = g_F2.a - g_F.a;
-  //     v = v * f2;
-  //   }
-  // }
-
-  const std::string text =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 430
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %S "S"
-OpMemberName %S 0 "a"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpDecorate %BaseColor Location 0
-OpDecorate %fi Location 0
-OpMemberDecorate %S 0 Offset 0
-OpMemberDecorate %S 0 Volatile
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t BufferBlock
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%3 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%S = OpTypeStruct %float
-%U_t = OpTypeStruct %S %S
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%main = OpFunction %void None %3
-%5 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%12 = OpLoad %v4float %BaseColor
-OpStore %v %12
-%15 = OpLoad %float %fi
-%18 = OpFOrdGreaterThan %bool %15 %float_0
-OpSelectionMerge %20 None
-OpBranchConditional %18 %19 %32
-%19 = OpLabel
-%21 = OpLoad %v4float %v
-%29 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_0
-%30 = OpLoad %float %29
-%31 = OpVectorTimesScalar %v4float %21 %30
-OpStore %v %31
-OpBranch %20
-%32 = OpLabel
-%36 = OpAccessChain %_ptr_Uniform_float %_ %int_1 %int_0
-%37 = OpLoad %float %36
-%38 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %int_0
-%39 = OpLoad %float %38
-%40 = OpFSub %float %37 %39
-OpStore %f2 %40
-%41 = OpLoad %v4float %v
-%42 = OpLoad %float %f2
-%43 = OpVectorTimesScalar %v4float %41 %42
-OpStore %v %43
-OpBranch %20
-%20 = OpLabel
-OpReturn
-OpFunctionEnd
-)";
-
-  Pass::Status res = std::get<1>(
-      SinglePassRunAndDisassemble<CommonUniformElimPass>(text, true, false));
-  EXPECT_EQ(res, Pass::Status::SuccessWithoutChange);
-}
-
-TEST_F(CommonUniformElimTest, IteratorDanglingPointer) {
-  // Note: This test exemplifies the following:
-  // - Existing common uniform (%_) load kept in place and shared
-  //
-  // #version 140
-  // in vec4 BaseColor;
-  // in float fi;
-  //
-  // layout(std140) uniform U_t
-  // {
-  //     bool g_B;
-  //     float g_F;
-  // } ;
-  //
-  // uniform float alpha;
-  // uniform bool alpha_B;
-  //
-  // void main()
-  // {
-  //     vec4 v = BaseColor;
-  //     if (g_B) {
-  //       v = v * g_F;
-  //       if (alpha_B)
-  //         v = v * alpha;
-  //       else
-  //         v = v * fi;
-  //     }
-  //     gl_FragColor = v;
-  // }
-
-  const std::string predefs =
-      R"(OpCapability Shader
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor %fi
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_B"
-OpMemberName %U_t 1 "g_F"
-OpName %alpha "alpha"
-OpName %alpha_B "alpha_B"
-OpName %_ ""
-OpName %gl_FragColor "gl_FragColor"
-OpName %fi "fi"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%12 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%uint = OpTypeInt 32 0
-%U_t = OpTypeStruct %uint %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-%bool = OpTypeBool
-%uint_0 = OpConstant %uint 0
-%int_1 = OpConstant %int 1
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%alpha = OpVariable %_ptr_Uniform_float Uniform
-%alpha_B = OpVariable %_ptr_Uniform_uint Uniform
-)";
-
-  const std::string before =
-      R"(%main = OpFunction %void None %12
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
-%29 = OpLoad %uint %28
-%30 = OpINotEqual %bool %29 %uint_0
-OpSelectionMerge %31 None
-OpBranchConditional %30 %31 %32
-%32 = OpLabel
-%47 = OpLoad %v4float %v
-OpStore %gl_FragColor %47
-OpReturn
-%31 = OpLabel
-%33 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%34 = OpLoad %float %33
-%35 = OpLoad %v4float %v
-%36 = OpVectorTimesScalar %v4float %35 %34
-OpStore %v %36
-%37 = OpLoad %uint %alpha_B
-%38 = OpIEqual %bool %37 %uint_0
-OpSelectionMerge %43 None
-OpBranchConditional %38 %43 %39
-%39 = OpLabel
-%40 = OpLoad %float %alpha
-%41 = OpLoad %v4float %v
-%42 = OpVectorTimesScalar %v4float %41 %40
-OpStore %v %42
-OpBranch %50
-%50 = OpLabel
-%51 = OpLoad %v4float %v
-OpStore %gl_FragColor %51
-OpReturn
-%43 = OpLabel
-%44 = OpLoad %float %fi
-%45 = OpLoad %v4float %v
-%46 = OpVectorTimesScalar %v4float %45 %44
-OpStore %v %46
-OpBranch %60
-%60 = OpLabel
-%61 = OpLoad %v4float %v
-OpStore %gl_FragColor %61
-OpReturn
-OpFunctionEnd
-)";
-
-  const std::string after =
-      R"(%main = OpFunction %void None %12
-%28 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%29 = OpLoad %v4float %BaseColor
-OpStore %v %29
-%54 = OpLoad %U_t %_
-%55 = OpCompositeExtract %uint %54 0
-%32 = OpINotEqual %bool %55 %uint_0
-OpSelectionMerge %33 None
-OpBranchConditional %32 %33 %34
-%34 = OpLabel
-%35 = OpLoad %v4float %v
-OpStore %gl_FragColor %35
-OpReturn
-%33 = OpLabel
-%58 = OpLoad %float %alpha
-%57 = OpCompositeExtract %float %54 1
-%38 = OpLoad %v4float %v
-%39 = OpVectorTimesScalar %v4float %38 %57
-OpStore %v %39
-%40 = OpLoad %uint %alpha_B
-%41 = OpIEqual %bool %40 %uint_0
-OpSelectionMerge %42 None
-OpBranchConditional %41 %42 %43
-%43 = OpLabel
-%45 = OpLoad %v4float %v
-%46 = OpVectorTimesScalar %v4float %45 %58
-OpStore %v %46
-OpBranch %47
-%47 = OpLabel
-%48 = OpLoad %v4float %v
-OpStore %gl_FragColor %48
-OpReturn
-%42 = OpLabel
-%49 = OpLoad %float %fi
-%50 = OpLoad %v4float %v
-%51 = OpVectorTimesScalar %v4float %50 %49
-OpStore %v %51
-OpBranch %52
-%52 = OpLabel
-%53 = OpLoad %v4float %v
-OpStore %gl_FragColor %53
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<CommonUniformElimPass>(predefs + before,
-                                               predefs + after, true, true);
-}
-
-TEST_F(CommonUniformElimTest, MixedConstantAndNonConstantIndexes) {
-  const std::string text = R"(
-; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
-; CHECK: %501 = OpLabel
-; CHECK: [[ld:%\w+]] = OpLoad
-; CHECK-NOT: OpCompositeExtract {{%\w+}} {{%\w+}} 0 2 484
-; CHECK: OpAccessChain {{%\w+}} [[var]] %int_0 %int_2 [[ld]]
-               OpCapability Shader
-          %1 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint Fragment %4 "ringeffectLayer_px" %gl_FragCoord %178 %182
-               OpExecutionMode %4 OriginUpperLeft
-               OpSource HLSL 500
-               OpDecorate %_arr_v4float_uint_10 ArrayStride 16
-               OpMemberDecorate %_struct_20 0 Offset 0
-               OpMemberDecorate %_struct_20 1 Offset 16
-               OpMemberDecorate %_struct_20 2 Offset 32
-               OpMemberDecorate %_struct_21 0 Offset 0
-               OpDecorate %_struct_21 Block
-               OpDecorate %23 DescriptorSet 0
-               OpDecorate %gl_FragCoord BuiltIn FragCoord
-               OpDecorate %178 Location 0
-               OpDecorate %182 Location 0
-       %void = OpTypeVoid
-          %3 = OpTypeFunction %void
-      %float = OpTypeFloat 32
-    %v4float = OpTypeVector %float 4
-    %v2float = OpTypeVector %float 2
-%_ptr_Function_v2float = OpTypePointer Function %v2float
-       %uint = OpTypeInt 32 0
-    %uint_10 = OpConstant %uint 10
-%_arr_v4float_uint_10 = OpTypeArray %v4float %uint_10
- %_struct_20 = OpTypeStruct %v4float %v4float %_arr_v4float_uint_10
- %_struct_21 = OpTypeStruct %_struct_20
-%_ptr_Uniform__struct_21 = OpTypePointer Uniform %_struct_21
-         %23 = OpVariable %_ptr_Uniform__struct_21 Uniform
-        %int = OpTypeInt 32 1
-      %int_0 = OpConstant %int 0
-%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-     %uint_3 = OpConstant %uint 3
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-    %float_0 = OpConstant %float 0
-         %43 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
-%_ptr_Function_int = OpTypePointer Function %int
-      %int_5 = OpConstant %int 5
-       %bool = OpTypeBool
-      %int_1 = OpConstant %int 1
-      %int_2 = OpConstant %int 2
-     %uint_5 = OpConstant %uint 5
-%_arr_v2float_uint_5 = OpTypeArray %v2float %uint_5
-%_ptr_Function__arr_v2float_uint_5 = OpTypePointer Function %_arr_v2float_uint_5
-         %82 = OpTypeImage %float 2D 0 0 0 1 Unknown
-%_ptr_UniformConstant_82 = OpTypePointer UniformConstant %82
-         %86 = OpTypeSampler
-%_ptr_UniformConstant_86 = OpTypePointer UniformConstant %86
-         %90 = OpTypeSampledImage %82
-    %v3float = OpTypeVector %float 3
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%gl_FragCoord = OpVariable %_ptr_Input_v4float Input
-        %178 = OpVariable %_ptr_Input_v4float Input
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-        %182 = OpVariable %_ptr_Output_v4float Output
-          %4 = OpFunction %void None %3
-          %5 = OpLabel
-        %483 = OpVariable %_ptr_Function_v4float Function
-        %484 = OpVariable %_ptr_Function_int Function
-        %486 = OpVariable %_ptr_Function__arr_v2float_uint_5 Function
-        %179 = OpLoad %v4float %178
-        %493 = OpAccessChain %_ptr_Uniform_float %23 %int_0 %int_0 %uint_3
-        %494 = OpLoad %float %493
-               OpStore %483 %43
-               OpStore %484 %int_0
-               OpBranch %495
-        %495 = OpLabel
-               OpLoopMerge %496 %497 None
-               OpBranch %498
-        %498 = OpLabel
-        %499 = OpLoad %int %484
-        %500 = OpSLessThan %bool %499 %int_5
-               OpBranchConditional %500 %501 %496
-        %501 = OpLabel
-        %504 = OpVectorShuffle %v2float %179 %179 0 1
-        %505 = OpLoad %int %484
-        %506 = OpAccessChain %_ptr_Uniform_v4float %23 %int_0 %int_2 %505
-        %507 = OpLoad %v4float %506
-        %508 = OpVectorShuffle %v2float %507 %507 0 1
-        %509 = OpFAdd %v2float %504 %508
-        %512 = OpAccessChain %_ptr_Uniform_v4float %23 %int_0 %int_1
-        %513 = OpLoad %v4float %512
-        %514 = OpVectorShuffle %v2float %513 %513 0 1
-        %517 = OpVectorShuffle %v2float %513 %513 2 3
-        %518 = OpExtInst %v2float %1 FClamp %509 %514 %517
-        %519 = OpAccessChain %_ptr_Function_v2float %486 %505
-               OpStore %519 %518
-               OpBranch %497
-        %497 = OpLabel
-        %520 = OpLoad %int %484
-        %521 = OpIAdd %int %520 %int_1
-               OpStore %484 %521
-               OpBranch %495
-        %496 = OpLabel
-               OpReturn
-               OpFunctionEnd
-)";
-
-  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndMatch<CommonUniformElimPass>(text, true);
-}
-
-TEST_F(CommonUniformElimTest, LoadPlacedAfterPhi) {
-  const std::string text = R"(
-; CHECK: [[var:%\w+]] = OpVariable {{%\w+}} Uniform
-; CHECK: OpSelectionMerge [[merge:%\w+]]
-; CHECK: [[merge]] = OpLabel
-; CHECK-NEXT: OpPhi
-; CHECK-NEXT: OpLoad {{%\w+}} [[var]]
-               OpCapability Shader
-          %1 = OpExtInstImport "GLSL.std.450"
-               OpMemoryModel Logical GLSL450
-               OpEntryPoint Fragment %2 "main"
-               OpExecutionMode %2 OriginUpperLeft
-               OpSource ESSL 310
-               OpMemberDecorate %_struct_3 0 Offset 0
-               OpDecorate %_struct_3 Block
-               OpDecorate %4 DescriptorSet 0
-               OpDecorate %4 Binding 0
-       %void = OpTypeVoid
-          %6 = OpTypeFunction %void
-       %bool = OpTypeBool
-      %false = OpConstantFalse %bool
-       %uint = OpTypeInt 32 0
-     %v2uint = OpTypeVector %uint 2
-  %_struct_3 = OpTypeStruct %v2uint
-%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
-          %4 = OpVariable %_ptr_Uniform__struct_3 Uniform
-     %uint_0 = OpConstant %uint 0
-%_ptr_Uniform_uint = OpTypePointer Uniform %uint
-     %uint_2 = OpConstant %uint 2
-          %2 = OpFunction %void None %6
-         %15 = OpLabel
-               OpSelectionMerge %16 None
-               OpBranchConditional %false %17 %16
-         %17 = OpLabel
-               OpBranch %16
-         %16 = OpLabel
-         %18 = OpPhi %bool %false %15 %false %17
-               OpSelectionMerge %19 None
-               OpBranchConditional %false %20 %21
-         %20 = OpLabel
-         %22 = OpAccessChain %_ptr_Uniform_uint %4 %uint_0 %uint_0
-         %23 = OpLoad %uint %22
-               OpBranch %19
-         %21 = OpLabel
-               OpBranch %19
-         %19 = OpLabel
-               OpReturn
-               OpFunctionEnd
-)";
-
-  SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-  SinglePassRunAndMatch<CommonUniformElimPass>(text, true);
-}
-
-TEST_F(CommonUniformElimTest, TestVariablePointer) {
-  // Same test a basic1 except the variable pointers capability has been added.
-  // This should stop the transformation from running.
-  const std::string test =
-      R"(OpCapability Shader
-OpCapability VariablePointers
-%1 = OpExtInstImport "GLSL.std.450"
-OpMemoryModel Logical GLSL450
-OpEntryPoint Fragment %main "main" %BaseColor %fi %gl_FragColor
-OpExecutionMode %main OriginUpperLeft
-OpSource GLSL 140
-OpName %main "main"
-OpName %v "v"
-OpName %BaseColor "BaseColor"
-OpName %fi "fi"
-OpName %U_t "U_t"
-OpMemberName %U_t 0 "g_F"
-OpMemberName %U_t 1 "g_F2"
-OpName %_ ""
-OpName %f2 "f2"
-OpName %gl_FragColor "gl_FragColor"
-OpMemberDecorate %U_t 0 Offset 0
-OpMemberDecorate %U_t 1 Offset 4
-OpDecorate %U_t Block
-OpDecorate %_ DescriptorSet 0
-%void = OpTypeVoid
-%11 = OpTypeFunction %void
-%float = OpTypeFloat 32
-%v4float = OpTypeVector %float 4
-%_ptr_Function_v4float = OpTypePointer Function %v4float
-%_ptr_Input_v4float = OpTypePointer Input %v4float
-%BaseColor = OpVariable %_ptr_Input_v4float Input
-%_ptr_Input_float = OpTypePointer Input %float
-%fi = OpVariable %_ptr_Input_float Input
-%float_0 = OpConstant %float 0
-%bool = OpTypeBool
-%U_t = OpTypeStruct %float %float
-%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
-%_ = OpVariable %_ptr_Uniform_U_t Uniform
-%int = OpTypeInt 32 1
-%int_0 = OpConstant %int 0
-%_ptr_Uniform_float = OpTypePointer Uniform %float
-%_ptr_Function_float = OpTypePointer Function %float
-%int_1 = OpConstant %int 1
-%_ptr_Output_v4float = OpTypePointer Output %v4float
-%gl_FragColor = OpVariable %_ptr_Output_v4float Output
-%main = OpFunction %void None %11
-%26 = OpLabel
-%v = OpVariable %_ptr_Function_v4float Function
-%f2 = OpVariable %_ptr_Function_float Function
-%27 = OpLoad %v4float %BaseColor
-OpStore %v %27
-%28 = OpLoad %float %fi
-%29 = OpFOrdGreaterThan %bool %28 %float_0
-OpSelectionMerge %30 None
-OpBranchConditional %29 %31 %32
-%31 = OpLabel
-%33 = OpLoad %v4float %v
-%34 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%35 = OpLoad %float %34
-%36 = OpVectorTimesScalar %v4float %33 %35
-OpStore %v %36
-OpBranch %30
-%32 = OpLabel
-%37 = OpAccessChain %_ptr_Uniform_float %_ %int_1
-%38 = OpLoad %float %37
-%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0
-%40 = OpLoad %float %39
-%41 = OpFSub %float %38 %40
-OpStore %f2 %41
-%42 = OpLoad %v4float %v
-%43 = OpLoad %float %f2
-%44 = OpVectorTimesScalar %v4float %42 %43
-OpStore %v %44
-OpBranch %30
-%30 = OpLabel
-%45 = OpLoad %v4float %v
-OpStore %gl_FragColor %45
-OpReturn
-OpFunctionEnd
-)";
-
-  SinglePassRunAndCheck<CommonUniformElimPass>(test, test, true, true);
-}
-
-// TODO(greg-lunarg): Add tests to verify handling of these cases:
-//
-//    Disqualifying cases: extensions, decorations, non-logical addressing,
-//      non-structured control flow
-//    Others?
-
-}  // namespace
-}  // namespace opt
-}  // namespace spvtools
diff --git a/test/opt/optimizer_test.cpp b/test/opt/optimizer_test.cpp
index b427804..ee6e949 100644
--- a/test/opt/optimizer_test.cpp
+++ b/test/opt/optimizer_test.cpp
@@ -163,7 +163,6 @@
       "--eliminate-dead-branches",
       "--eliminate-dead-functions",
       "--eliminate-local-multi-store",
-      "--eliminate-common-uniform",
       "--eliminate-dead-const",
       "--eliminate-dead-inserts",
       "--eliminate-dead-variables",
diff --git a/test/tools/opt/flags.py b/test/tools/opt/flags.py
index ca873c7..07e4e3e 100644
--- a/test/tools/opt/flags.py
+++ b/test/tools/opt/flags.py
@@ -59,7 +59,7 @@
   flags = [
       '--ccp', '--cfg-cleanup', '--combine-access-chains', '--compact-ids',
       '--convert-local-access-chains', '--copy-propagate-arrays',
-      '--eliminate-common-uniform', '--eliminate-dead-branches',
+      '--eliminate-dead-branches',
       '--eliminate-dead-code-aggressive', '--eliminate-dead-const',
       '--eliminate-dead-functions', '--eliminate-dead-inserts',
       '--eliminate-dead-variables', '--eliminate-insert-extract',
@@ -82,7 +82,6 @@
       'compact-ids',
       'convert-local-access-chains',
       'copy-propagate-arrays',
-      'eliminate-common-uniform',
       'eliminate-dead-branches',
       'eliminate-dead-code-aggressive',
       'eliminate-dead-const',
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index d29b8a0..a09b888 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -147,13 +147,6 @@
                around known issues with some Vulkan drivers for initialize
                variables.)");
   printf(R"(
-  --eliminate-common-uniform
-               Perform load/load elimination for duplicate uniform values.
-               Converts any constant index access chain uniform loads into
-               its equivalent load and extract. Some loads will be moved
-               to facilitate sharing. Performed only on entry point
-               call tree functions.)");
-  printf(R"(
   --eliminate-dead-branches
                Convert conditional branches with constant condition to the
                indicated unconditional brranch. Delete all resulting dead