// Copyright (c) 2018 Google LLC
//
// 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/folding_rules.h"

#include <limits>
#include <memory>
#include <optional>
#include <utility>

#include "ir_builder.h"
#include "source/latest_version_glsl_std_450_header.h"
#include "source/opt/ir_context.h"

namespace spvtools {
namespace opt {
namespace {

constexpr uint32_t kExtractCompositeIdInIdx = 0;
constexpr uint32_t kInsertObjectIdInIdx = 0;
constexpr uint32_t kInsertCompositeIdInIdx = 1;
constexpr uint32_t kExtInstSetIdInIdx = 0;
constexpr uint32_t kExtInstInstructionInIdx = 1;
constexpr uint32_t kFMixXIdInIdx = 2;
constexpr uint32_t kFMixYIdInIdx = 3;
constexpr uint32_t kFMixAIdInIdx = 4;
constexpr uint32_t kStoreObjectInIdx = 1;

// Some image instructions may contain an "image operands" argument.
// Returns the operand index for the "image operands".
// Returns -1 if the instruction does not have image operands.
int32_t ImageOperandsMaskInOperandIndex(Instruction* inst) {
  const auto opcode = inst->opcode();
  switch (opcode) {
    case spv::Op::OpImageSampleImplicitLod:
    case spv::Op::OpImageSampleExplicitLod:
    case spv::Op::OpImageSampleProjImplicitLod:
    case spv::Op::OpImageSampleProjExplicitLod:
    case spv::Op::OpImageFetch:
    case spv::Op::OpImageRead:
    case spv::Op::OpImageSparseSampleImplicitLod:
    case spv::Op::OpImageSparseSampleExplicitLod:
    case spv::Op::OpImageSparseSampleProjImplicitLod:
    case spv::Op::OpImageSparseSampleProjExplicitLod:
    case spv::Op::OpImageSparseFetch:
    case spv::Op::OpImageSparseRead:
      return inst->NumOperands() > 4 ? 2 : -1;
    case spv::Op::OpImageSampleDrefImplicitLod:
    case spv::Op::OpImageSampleDrefExplicitLod:
    case spv::Op::OpImageSampleProjDrefImplicitLod:
    case spv::Op::OpImageSampleProjDrefExplicitLod:
    case spv::Op::OpImageGather:
    case spv::Op::OpImageDrefGather:
    case spv::Op::OpImageSparseSampleDrefImplicitLod:
    case spv::Op::OpImageSparseSampleDrefExplicitLod:
    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
    case spv::Op::OpImageSparseGather:
    case spv::Op::OpImageSparseDrefGather:
      return inst->NumOperands() > 5 ? 3 : -1;
    case spv::Op::OpImageWrite:
      return inst->NumOperands() > 3 ? 3 : -1;
    default:
      return -1;
  }
}

// Returns the element width of |type|.
uint32_t ElementWidth(const analysis::Type* type) {
  if (const analysis::CooperativeVectorNV* coopvec_type =
          type->AsCooperativeVectorNV()) {
    return ElementWidth(coopvec_type->component_type());
  } else if (const analysis::Vector* vec_type = type->AsVector()) {
    return ElementWidth(vec_type->element_type());
  } else if (const analysis::Float* float_type = type->AsFloat()) {
    return float_type->width();
  } else {
    assert(type->AsInteger());
    return type->AsInteger()->width();
  }
}

// Returns true if |type| is Float or a vector of Float.
bool HasFloatingPoint(const analysis::Type* type) {
  if (type->AsFloat()) {
    return true;
  } else if (const analysis::Vector* vec_type = type->AsVector()) {
    return vec_type->element_type()->AsFloat() != nullptr;
  }

  return false;
}

// Returns false if |val| is NaN, infinite or subnormal.
template <typename T>
bool IsValidResult(T val) {
  int classified = std::fpclassify(val);
  switch (classified) {
    case FP_NAN:
    case FP_INFINITE:
    case FP_SUBNORMAL:
      return false;
    default:
      return true;
  }
}

const analysis::Constant* ConstInput(
    const std::vector<const analysis::Constant*>& constants) {
  return constants[0] ? constants[0] : constants[1];
}

Instruction* NonConstInput(IRContext* context, const analysis::Constant* c,
                           Instruction* inst) {
  uint32_t in_op = c ? 1u : 0u;
  return context->get_def_use_mgr()->GetDef(
      inst->GetSingleWordInOperand(in_op));
}

std::vector<uint32_t> ExtractInts(uint64_t val) {
  std::vector<uint32_t> words;
  words.push_back(static_cast<uint32_t>(val));
  words.push_back(static_cast<uint32_t>(val >> 32));
  return words;
}

std::vector<uint32_t> GetWordsFromScalarIntConstant(
    const analysis::IntConstant* c) {
  assert(c != nullptr);
  uint32_t width = c->type()->AsInteger()->width();
  assert(width == 8 || width == 16 || width == 32 || width == 64);
  if (width == 64) {
    uint64_t uval = static_cast<uint64_t>(c->GetU64());
    return ExtractInts(uval);
  }
  // Section 2.2.1 of the SPIR-V spec guarantees that all integer types
  // smaller than 32-bits are automatically zero or sign extended to 32-bits.
  return {c->GetU32BitValue()};
}

std::vector<uint32_t> GetWordsFromScalarFloatConstant(
    const analysis::FloatConstant* c) {
  assert(c != nullptr);
  uint32_t width = c->type()->AsFloat()->width();
  assert(width == 16 || width == 32 || width == 64);
  if (width == 64) {
    utils::FloatProxy<double> result(c->GetDouble());
    return result.GetWords();
  }
  // Section 2.2.1 of the SPIR-V spec guarantees that all floating-point types
  // smaller than 32-bits are automatically zero extended to 32-bits.
  return {c->GetU32BitValue()};
}

std::vector<uint32_t> GetWordsFromNumericScalarOrVectorConstant(
    analysis::ConstantManager* const_mgr, const analysis::Constant* c) {
  if (const auto* float_constant = c->AsFloatConstant()) {
    return GetWordsFromScalarFloatConstant(float_constant);
  } else if (const auto* int_constant = c->AsIntConstant()) {
    return GetWordsFromScalarIntConstant(int_constant);
  } else if (const auto* vec_constant = c->AsVectorConstant()) {
    std::vector<uint32_t> words;
    // Retrieve all the components as 32bit words.
    for (const auto* comp : vec_constant->GetComponents()) {
      auto comp_in_words =
          GetWordsFromNumericScalarOrVectorConstant(const_mgr, comp);
      words.insert(words.end(), comp_in_words.begin(), comp_in_words.end());
    }

    if (ElementWidth(c->type()) >= 32) {
      return words;
    }
    // Check the element width and concactenate if the width is less than 32.
    if (ElementWidth(c->type()) == 8) {
      assert(words.size() <= 4);
      // Each 32-bit word will comprise 4 8-bit integers.
      // reverse the order when compacting.
      uint32_t compacted_word = 0;
      for (int32_t i = static_cast<int32_t>(words.size()) - 1; i >= 0; --i) {
        compacted_word <<= 8;
        compacted_word |= (words[i] & 0xFF);
      }
      return {compacted_word};
    } else if (ElementWidth(c->type()) == 16) {
      assert(words.size() <= 4);
      std::vector<uint32_t> compacted_words;
      // Each 32-bit word will comprise 2 16-bit integers.
      // reverse the order pair-wise when compacting.
      for (uint32_t i = 0; i < words.size(); i += 2) {
        uint32_t word1 = words[i];
        uint32_t word2 = (i + 1 < words.size()) ? words[i + 1] : 0;
        uint32_t compacted_word = (word2 << 16) | (word1 & 0xFFFF);
        compacted_words.push_back(compacted_word);
      }
      return compacted_words;
    }
    assert(false && "Unhandled element width");
  } else if (c->AsNullConstant()) {
    uint32_t num_elements = 1;

    if (const auto* vec_type = c->type()->AsVector()) {
      num_elements = vec_type->element_count();
    }

    // We need to check the element width to determine how many 32-bit words are
    // needed.
    uint32_t element_width = ElementWidth(c->type());
    if (element_width < 32) {
      num_elements = (num_elements + 1) / 2;
    } else if (element_width == 64) {
      num_elements = num_elements * 2;
    }
    return std::vector<uint32_t>(num_elements, 0);
  }
  return {};
}

const analysis::Constant* ConvertWordsToNumericScalarOrVectorConstant(
    analysis::ConstantManager* const_mgr, const std::vector<uint32_t>& words,
    const analysis::Type* type) {
  const spvtools::opt::analysis::Integer* int_type = type->AsInteger();

  if (int_type && int_type->width() <= 32) {
    assert(words.size() == 1);
    return const_mgr->GenerateIntegerConstant(int_type, words[0]);
  }

  if (int_type || type->AsFloat()) return const_mgr->GetConstant(type, words);
  if (const auto* vec_type = type->AsVector())
    return const_mgr->GetNumericVectorConstantWithWords(vec_type, words);
  return nullptr;
}

// Returns the negation of |c|. |c| must be a 32 or 64 bit floating point
// constant.
uint32_t NegateFloatingPointConstant(analysis::ConstantManager* const_mgr,
                                     const analysis::Constant* c) {
  assert(c);
  assert(c->type()->AsFloat());
  uint32_t width = c->type()->AsFloat()->width();
  assert(width == 32 || width == 64);
  std::vector<uint32_t> words;
  if (width == 64) {
    utils::FloatProxy<double> result(c->GetDouble() * -1.0);
    words = result.GetWords();
  } else {
    utils::FloatProxy<float> result(c->GetFloat() * -1.0f);
    words = result.GetWords();
  }

  const analysis::Constant* negated_const =
      const_mgr->GetConstant(c->type(), std::move(words));
  return const_mgr->GetDefiningInstruction(negated_const)->result_id();
}

// Negates the integer constant |c|. Returns the id of the defining instruction.
uint32_t NegateIntegerConstant(analysis::ConstantManager* const_mgr,
                               const analysis::Constant* c) {
  assert(c);
  assert(c->type()->AsInteger());
  uint32_t width = c->type()->AsInteger()->width();
  assert(width == 32 || width == 64);
  std::vector<uint32_t> words;
  if (width == 64) {
    uint64_t uval = static_cast<uint64_t>(0 - c->GetU64());
    words = ExtractInts(uval);
  } else {
    words.push_back(static_cast<uint32_t>(0 - c->GetU32()));
  }

  const analysis::Constant* negated_const =
      const_mgr->GetConstant(c->type(), std::move(words));
  return const_mgr->GetDefiningInstruction(negated_const)->result_id();
}

// Negates the vector constant |c|. Returns the id of the defining instruction.
uint32_t NegateVectorConstant(analysis::ConstantManager* const_mgr,
                              const analysis::Constant* c) {
  assert(const_mgr && c);
  assert(c->type()->AsVector());
  if (c->AsNullConstant()) {
    // 0.0 vs -0.0 shouldn't matter.
    return const_mgr->GetDefiningInstruction(c)->result_id();
  } else {
    const analysis::Type* component_type =
        c->AsVectorConstant()->component_type();
    std::vector<uint32_t> words;
    for (auto& comp : c->AsVectorConstant()->GetComponents()) {
      if (component_type->AsFloat()) {
        words.push_back(NegateFloatingPointConstant(const_mgr, comp));
      } else {
        assert(component_type->AsInteger());
        words.push_back(NegateIntegerConstant(const_mgr, comp));
      }
    }

    const analysis::Constant* negated_const =
        const_mgr->GetConstant(c->type(), std::move(words));
    return const_mgr->GetDefiningInstruction(negated_const)->result_id();
  }
}

// Negates |c|. Returns the id of the defining instruction.
uint32_t NegateConstant(analysis::ConstantManager* const_mgr,
                        const analysis::Constant* c) {
  if (c->type()->AsVector()) {
    return NegateVectorConstant(const_mgr, c);
  } else if (c->type()->AsFloat()) {
    return NegateFloatingPointConstant(const_mgr, c);
  } else {
    assert(c->type()->AsInteger());
    return NegateIntegerConstant(const_mgr, c);
  }
}

// Takes the reciprocal of |c|. |c|'s type must be Float or a vector of Float.
// Returns 0 if the reciprocal is NaN, infinite or subnormal.
uint32_t Reciprocal(analysis::ConstantManager* const_mgr,
                    const analysis::Constant* c) {
  assert(const_mgr && c);
  assert(c->type()->AsFloat());

  uint32_t width = c->type()->AsFloat()->width();
  assert(width == 32 || width == 64);
  std::vector<uint32_t> words;

  if (c->IsZero()) {
    return 0;
  }

  if (width == 64) {
    spvtools::utils::FloatProxy<double> result(1.0 / c->GetDouble());
    if (!IsValidResult(result.getAsFloat())) return 0;
    words = result.GetWords();
  } else {
    spvtools::utils::FloatProxy<float> result(1.0f / c->GetFloat());
    if (!IsValidResult(result.getAsFloat())) return 0;
    words = result.GetWords();
  }

  const analysis::Constant* negated_const =
      const_mgr->GetConstant(c->type(), std::move(words));
  return const_mgr->GetDefiningInstruction(negated_const)->result_id();
}

// Replaces fdiv where second operand is constant with fmul.
FoldingRule ReciprocalFDiv() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFDiv);
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    if (!inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    if (constants[1] != nullptr) {
      uint32_t id = 0;
      if (const analysis::VectorConstant* vector_const =
              constants[1]->AsVectorConstant()) {
        std::vector<uint32_t> neg_ids;
        for (auto& comp : vector_const->GetComponents()) {
          id = Reciprocal(const_mgr, comp);
          if (id == 0) return false;
          neg_ids.push_back(id);
        }
        const analysis::Constant* negated_const =
            const_mgr->GetConstant(constants[1]->type(), std::move(neg_ids));
        id = const_mgr->GetDefiningInstruction(negated_const)->result_id();
      } else if (constants[1]->AsFloatConstant()) {
        id = Reciprocal(const_mgr, constants[1]);
        if (id == 0) return false;
      } else {
        // Don't fold a null constant.
        return false;
      }
      inst->SetOpcode(spv::Op::OpFMul);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0u)}},
           {SPV_OPERAND_TYPE_ID, {id}}});
      return true;
    }

    return false;
  };
}

// Elides consecutive negate instructions.
FoldingRule MergeNegateArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFNegate ||
           inst->opcode() == spv::Op::OpSNegate);
    (void)constants;
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed())
      return false;

    Instruction* op_inst =
        context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u));
    if (HasFloatingPoint(type) && !op_inst->IsFloatingPointFoldingAllowed())
      return false;

    if (op_inst->opcode() == inst->opcode()) {
      // Elide negates.
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {op_inst->GetSingleWordInOperand(0u)}}});
      return true;
    }

    return false;
  };
}

// Merges negate into a mul or div operation if that operation contains a
// constant operand.
// Cases:
// -(x * 2) = x * -2
// -(2 * x) = x * -2
// -(x / 2) = x / -2
// -(2 / x) = -2 / x
FoldingRule MergeNegateMulDivArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFNegate ||
           inst->opcode() == spv::Op::OpSNegate);
    (void)constants;
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed())
      return false;

    Instruction* op_inst =
        context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u));
    if (HasFloatingPoint(type) && !op_inst->IsFloatingPointFoldingAllowed())
      return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    spv::Op opcode = op_inst->opcode();
    if (opcode != spv::Op::OpFMul && opcode != spv::Op::OpFDiv &&
        opcode != spv::Op::OpIMul && opcode != spv::Op::OpSDiv) {
      return false;
    }

    std::vector<const analysis::Constant*> op_constants =
        const_mgr->GetOperandConstants(op_inst);
    // Merge negate into mul or div if one operand is constant.
    if (op_constants[0] == nullptr && op_constants[1] == nullptr) {
      return false;
    }

    bool zero_is_variable = op_constants[0] == nullptr;
    const analysis::Constant* c = ConstInput(op_constants);
    uint32_t neg_id = NegateConstant(const_mgr, c);
    uint32_t non_const_id = zero_is_variable
                                ? op_inst->GetSingleWordInOperand(0u)
                                : op_inst->GetSingleWordInOperand(1u);
    // Change this instruction to a mul/div.
    inst->SetOpcode(op_inst->opcode());
    if (opcode == spv::Op::OpFDiv || opcode == spv::Op::OpUDiv ||
        opcode == spv::Op::OpSDiv) {
      uint32_t op0 = zero_is_variable ? non_const_id : neg_id;
      uint32_t op1 = zero_is_variable ? neg_id : non_const_id;
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {op0}}, {SPV_OPERAND_TYPE_ID, {op1}}});
    } else {
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {non_const_id}},
                           {SPV_OPERAND_TYPE_ID, {neg_id}}});
    }
    return true;
  };
}

// Merges negate into a add or sub operation if that operation contains a
// constant operand.
// Cases:
// -(x + 2) = -2 - x
// -(2 + x) = -2 - x
// -(x - 2) = 2 - x
// -(2 - x) = x - 2
FoldingRule MergeNegateAddSubArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFNegate ||
           inst->opcode() == spv::Op::OpSNegate);
    (void)constants;
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed())
      return false;

    Instruction* op_inst =
        context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u));
    if (HasFloatingPoint(type) && !op_inst->IsFloatingPointFoldingAllowed())
      return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    if (op_inst->opcode() == spv::Op::OpFAdd ||
        op_inst->opcode() == spv::Op::OpFSub ||
        op_inst->opcode() == spv::Op::OpIAdd ||
        op_inst->opcode() == spv::Op::OpISub) {
      std::vector<const analysis::Constant*> op_constants =
          const_mgr->GetOperandConstants(op_inst);
      if (op_constants[0] || op_constants[1]) {
        bool zero_is_variable = op_constants[0] == nullptr;
        bool is_add = (op_inst->opcode() == spv::Op::OpFAdd) ||
                      (op_inst->opcode() == spv::Op::OpIAdd);
        bool swap_operands = !is_add || zero_is_variable;
        bool negate_const = is_add;
        const analysis::Constant* c = ConstInput(op_constants);
        uint32_t const_id = 0;
        if (negate_const) {
          const_id = NegateConstant(const_mgr, c);
        } else {
          const_id = zero_is_variable ? op_inst->GetSingleWordInOperand(1u)
                                      : op_inst->GetSingleWordInOperand(0u);
        }

        // Swap operands if necessary and make the instruction a subtraction.
        uint32_t op0 =
            zero_is_variable ? op_inst->GetSingleWordInOperand(0u) : const_id;
        uint32_t op1 =
            zero_is_variable ? const_id : op_inst->GetSingleWordInOperand(1u);
        if (swap_operands) std::swap(op0, op1);
        inst->SetOpcode(HasFloatingPoint(type) ? spv::Op::OpFSub
                                               : spv::Op::OpISub);
        inst->SetInOperands(
            {{SPV_OPERAND_TYPE_ID, {op0}}, {SPV_OPERAND_TYPE_ID, {op1}}});
        return true;
      }
    }

    return false;
  };
}

// Returns true if |c| has a zero element.
bool HasZero(const analysis::Constant* c) {
  if (c->AsNullConstant()) {
    return true;
  }
  if (const analysis::VectorConstant* vec_const = c->AsVectorConstant()) {
    for (auto& comp : vec_const->GetComponents())
      if (HasZero(comp)) return true;
  } else {
    assert(c->AsScalarConstant());
    return c->AsScalarConstant()->IsZero();
  }

  return false;
}

// Performs |input1| |opcode| |input2| and returns the merged constant result
// id. Returns 0 if the result is not a valid value. The input types must be
// Float.
uint32_t PerformFloatingPointOperation(analysis::ConstantManager* const_mgr,
                                       spv::Op opcode,
                                       const analysis::Constant* input1,
                                       const analysis::Constant* input2) {
  const analysis::Type* type = input1->type();
  assert(type->AsFloat());
  uint32_t width = type->AsFloat()->width();
  assert(width == 32 || width == 64);
  std::vector<uint32_t> words;
#define FOLD_OP(op)                                                          \
  if (width == 64) {                                                         \
    utils::FloatProxy<double> val =                                          \
        input1->GetDouble() op input2->GetDouble();                          \
    double dval = val.getAsFloat();                                          \
    if (!IsValidResult(dval)) return 0;                                      \
    words = val.GetWords();                                                  \
  } else {                                                                   \
    utils::FloatProxy<float> val = input1->GetFloat() op input2->GetFloat(); \
    float fval = val.getAsFloat();                                           \
    if (!IsValidResult(fval)) return 0;                                      \
    words = val.GetWords();                                                  \
  }                                                                          \
  static_assert(true, "require extra semicolon")
  switch (opcode) {
    case spv::Op::OpFMul:
      FOLD_OP(*);
      break;
    case spv::Op::OpFDiv:
      if (HasZero(input2)) return 0;
      FOLD_OP(/);
      break;
    case spv::Op::OpFAdd:
      FOLD_OP(+);
      break;
    case spv::Op::OpFSub:
      FOLD_OP(-);
      break;
    default:
      assert(false && "Unexpected operation");
      break;
  }
#undef FOLD_OP
  const analysis::Constant* merged_const = const_mgr->GetConstant(type, words);
  return const_mgr->GetDefiningInstruction(merged_const)->result_id();
}

// Performs |input1| |opcode| |input2| and returns the merged constant result
// id. Returns 0 if the result is not a valid value. The input types must be
// Integers.
uint32_t PerformIntegerOperation(analysis::ConstantManager* const_mgr,
                                 spv::Op opcode,
                                 const analysis::Constant* input1,
                                 const analysis::Constant* input2) {
  assert(input1->type()->AsInteger());
  const analysis::Integer* type = input1->type()->AsInteger();
  uint32_t width = type->AsInteger()->width();
  assert(width == 32 || width == 64);
  std::vector<uint32_t> words;
  // Regardless of the sign of the constant, folding is performed on an unsigned
  // interpretation of the constant data. This avoids signed integer overflow
  // while folding, and works because sign is irrelevant for the IAdd, ISub and
  // IMul instructions.
#define FOLD_OP(op)                                      \
  if (width == 64) {                                     \
    uint64_t val = input1->GetU64() op input2->GetU64(); \
    words = ExtractInts(val);                            \
  } else {                                               \
    uint32_t val = input1->GetU32() op input2->GetU32(); \
    words.push_back(val);                                \
  }                                                      \
  static_assert(true, "require extra semicolon")
  switch (opcode) {
    case spv::Op::OpIMul:
      FOLD_OP(*);
      break;
    case spv::Op::OpSDiv:
    case spv::Op::OpUDiv:
      assert(false && "Should not merge integer division");
      break;
    case spv::Op::OpIAdd:
      FOLD_OP(+);
      break;
    case spv::Op::OpISub:
      FOLD_OP(-);
      break;
    case spv::Op::OpBitwiseXor:
      FOLD_OP(^);
      break;
    case spv::Op::OpBitwiseOr:
      FOLD_OP(|);
      break;
    case spv::Op::OpBitwiseAnd:
      FOLD_OP(&);
      break;
    default:
      assert(false && "Unexpected operation");
      break;
  }
#undef FOLD_OP
  const analysis::Constant* merged_const = const_mgr->GetConstant(type, words);
  return const_mgr->GetDefiningInstruction(merged_const)->result_id();
}

// Performs |input1| |opcode| |input2| and returns the merged constant result
// id. Returns 0 if the result is not a valid value. The input types must be
// Integers, Floats or Vectors of such.
uint32_t PerformOperation(analysis::ConstantManager* const_mgr, spv::Op opcode,
                          const analysis::Constant* input1,
                          const analysis::Constant* input2) {
  assert(input1 && input2);
  const analysis::Type* type = input1->type();
  std::vector<uint32_t> words;
  if (const analysis::Vector* vector_type = type->AsVector()) {
    const analysis::Type* ele_type = vector_type->element_type();
    for (uint32_t i = 0; i != vector_type->element_count(); ++i) {
      uint32_t id = 0;

      const analysis::Constant* input1_comp = nullptr;
      if (const analysis::VectorConstant* input1_vector =
              input1->AsVectorConstant()) {
        input1_comp = input1_vector->GetComponents()[i];
      } else {
        assert(input1->AsNullConstant());
        input1_comp = const_mgr->GetConstant(ele_type, {});
      }

      const analysis::Constant* input2_comp = nullptr;
      if (const analysis::VectorConstant* input2_vector =
              input2->AsVectorConstant()) {
        input2_comp = input2_vector->GetComponents()[i];
      } else {
        assert(input2->AsNullConstant());
        input2_comp = const_mgr->GetConstant(ele_type, {});
      }

      if (ele_type->AsFloat()) {
        id = PerformFloatingPointOperation(const_mgr, opcode, input1_comp,
                                           input2_comp);
      } else {
        assert(ele_type->AsInteger());
        id = PerformIntegerOperation(const_mgr, opcode, input1_comp,
                                     input2_comp);
      }
      if (id == 0) return 0;
      words.push_back(id);
    }
    const analysis::Constant* merged_const =
        const_mgr->GetConstant(type, words);
    return const_mgr->GetDefiningInstruction(merged_const)->result_id();
  } else if (type->AsFloat()) {
    return PerformFloatingPointOperation(const_mgr, opcode, input1, input2);
  } else {
    assert(type->AsInteger());
    return PerformIntegerOperation(const_mgr, opcode, input1, input2);
  }
}

// Merges consecutive multiplies where each contains one constant operand.
// Cases:
// 2 * (x * 2) = x * 4
// 2 * (2 * x) = x * 4
// (x * 2) * 2 = x * 4
// (2 * x) * 2 = x * 4
FoldingRule MergeMulMulArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFMul ||
           inst->opcode() == spv::Op::OpIMul);
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed())
      return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    // Determine the constant input and the variable input in |inst|.
    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (HasFloatingPoint(type) && !other_inst->IsFloatingPointFoldingAllowed())
      return false;

    if (other_inst->opcode() == inst->opcode()) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2) return false;

      bool other_first_is_variable = other_constants[0] == nullptr;
      uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(),
                                            const_input1, const_input2);
      if (merged_id == 0) return false;

      uint32_t non_const_id = other_first_is_variable
                                  ? other_inst->GetSingleWordInOperand(0u)
                                  : other_inst->GetSingleWordInOperand(1u);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {non_const_id}},
                           {SPV_OPERAND_TYPE_ID, {merged_id}}});
      return true;
    }

    return false;
  };
}

// Merges divides into subsequent multiplies if each instruction contains one
// constant operand. Does not support integer operations.
// Cases:
// 2 * (x / 2) = x * 1
// 2 * (2 / x) = 4 / x
// (x / 2) * 2 = x * 1
// (2 / x) * 2 = 4 / x
// (y / x) * x = y
// x * (y / x) = y
FoldingRule MergeMulDivArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFMul);
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    if (!inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    for (uint32_t i = 0; i < 2; i++) {
      uint32_t op_id = inst->GetSingleWordInOperand(i);
      Instruction* op_inst = def_use_mgr->GetDef(op_id);
      if (op_inst->opcode() == spv::Op::OpFDiv) {
        if (op_inst->GetSingleWordInOperand(1) ==
            inst->GetSingleWordInOperand(1 - i)) {
          inst->SetOpcode(spv::Op::OpCopyObject);
          inst->SetInOperands(
              {{SPV_OPERAND_TYPE_ID, {op_inst->GetSingleWordInOperand(0)}}});
          return true;
        }
      }
    }

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (!other_inst->IsFloatingPointFoldingAllowed()) return false;

    if (other_inst->opcode() == spv::Op::OpFDiv) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2 || HasZero(const_input2)) return false;

      bool other_first_is_variable = other_constants[0] == nullptr;
      // If the variable value is the second operand of the divide, multiply
      // the constants together. Otherwise divide the constants.
      uint32_t merged_id = PerformOperation(
          const_mgr,
          other_first_is_variable ? other_inst->opcode() : inst->opcode(),
          const_input1, const_input2);
      if (merged_id == 0) return false;

      uint32_t non_const_id = other_first_is_variable
                                  ? other_inst->GetSingleWordInOperand(0u)
                                  : other_inst->GetSingleWordInOperand(1u);

      // If the variable value is on the second operand of the div, then this
      // operation is a div. Otherwise it should be a multiply.
      inst->SetOpcode(other_first_is_variable ? inst->opcode()
                                              : other_inst->opcode());
      if (other_first_is_variable) {
        inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {non_const_id}},
                             {SPV_OPERAND_TYPE_ID, {merged_id}}});
      } else {
        inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {merged_id}},
                             {SPV_OPERAND_TYPE_ID, {non_const_id}}});
      }
      return true;
    }

    return false;
  };
}

// Merges multiply of constant and negation.
// Cases:
// (-x) * 2 = x * -2
// 2 * (-x) = x * -2
FoldingRule MergeMulNegateArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFMul ||
           inst->opcode() == spv::Op::OpIMul);
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
      return false;

    if (other_inst->opcode() == spv::Op::OpFNegate ||
        other_inst->opcode() == spv::Op::OpSNegate) {
      uint32_t neg_id = NegateConstant(const_mgr, const_input1);

      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {other_inst->GetSingleWordInOperand(0u)}},
           {SPV_OPERAND_TYPE_ID, {neg_id}}});
      return true;
    }

    return false;
  };
}

// Returns true if |inst| is negation op and is safe to fold.
static bool IsFoldableNegation(const Instruction* inst) {
  return (inst->opcode() == spv::Op::OpSNegate ||
          (inst->opcode() == spv::Op::OpFNegate &&
           inst->IsFloatingPointFoldingAllowed()));
}

// Merges multiplies / divisions of two negations.
// Cases:
// (-x) * (-y) = x * y
// (-x) / (-y) = x / y
FoldingRule MergeDivMulDoubleNegative() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpFMul ||
           inst->opcode() == spv::Op::OpVectorTimesScalar ||
           inst->opcode() == spv::Op::OpFDiv ||
           inst->opcode() == spv::Op::OpIMul ||
           inst->opcode() == spv::Op::OpSDiv);

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    Instruction* lhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
    Instruction* rhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));

    if (IsFoldableNegation(lhs) && IsFoldableNegation(rhs)) {
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {lhs->GetSingleWordInOperand(0u)}},
           {SPV_OPERAND_TYPE_ID, {rhs->GetSingleWordInOperand(0u)}}});
      return true;
    }
    return false;
  };
}

// Merges consecutive divides if each instruction contains one constant operand.
// Does not support integer division.
// Cases:
// 2 / (x / 2) = 4 / x
// 4 / (2 / x) = 2 * x
// (4 / x) / 2 = 2 / x
// (x / 2) / 2 = x / 4
FoldingRule MergeDivDivArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFDiv);
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    if (!inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1 || HasZero(const_input1)) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (!other_inst->IsFloatingPointFoldingAllowed()) return false;

    bool first_is_variable = constants[0] == nullptr;
    if (other_inst->opcode() == inst->opcode()) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2 || HasZero(const_input2)) return false;

      bool other_first_is_variable = other_constants[0] == nullptr;

      spv::Op merge_op = inst->opcode();
      if (other_first_is_variable) {
        // Constants magnify.
        merge_op = spv::Op::OpFMul;
      }

      // This is an x / (*) case. Swap the inputs. Doesn't harm multiply
      // because it is commutative.
      if (first_is_variable) std::swap(const_input1, const_input2);
      uint32_t merged_id =
          PerformOperation(const_mgr, merge_op, const_input1, const_input2);
      if (merged_id == 0) return false;

      uint32_t non_const_id = other_first_is_variable
                                  ? other_inst->GetSingleWordInOperand(0u)
                                  : other_inst->GetSingleWordInOperand(1u);

      spv::Op op = inst->opcode();
      if (!first_is_variable && !other_first_is_variable) {
        // Effectively div of 1/x, so change to multiply.
        op = spv::Op::OpFMul;
      }

      uint32_t op1 = merged_id;
      uint32_t op2 = non_const_id;
      if (first_is_variable && other_first_is_variable) std::swap(op1, op2);
      inst->SetOpcode(op);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}});
      return true;
    }

    return false;
  };
}

// Fold multiplies succeeded by divides where each instruction contains a
// constant operand. Does not support integer divide.
// Cases:
// 4 / (x * 2) = 2 / x
// 4 / (2 * x) = 2 / x
// (x * 4) / 2 = x * 2
// (4 * x) / 2 = x * 2
// (x * y) / x = y
// (y * x) / x = y
FoldingRule MergeDivMulArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFDiv);
    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    if (!inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    uint32_t op_id = inst->GetSingleWordInOperand(0);
    Instruction* op_inst = def_use_mgr->GetDef(op_id);

    if (op_inst->opcode() == spv::Op::OpFMul) {
      for (uint32_t i = 0; i < 2; i++) {
        if (op_inst->GetSingleWordInOperand(i) ==
            inst->GetSingleWordInOperand(1)) {
          inst->SetOpcode(spv::Op::OpCopyObject);
          inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                                {op_inst->GetSingleWordInOperand(1 - i)}}});
          return true;
        }
      }
    }

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1 || HasZero(const_input1)) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (!other_inst->IsFloatingPointFoldingAllowed()) return false;

    bool first_is_variable = constants[0] == nullptr;
    if (other_inst->opcode() == spv::Op::OpFMul) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2) return false;

      bool other_first_is_variable = other_constants[0] == nullptr;

      // This is an x / (*) case. Swap the inputs.
      if (first_is_variable) std::swap(const_input1, const_input2);
      uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(),
                                            const_input1, const_input2);
      if (merged_id == 0) return false;

      uint32_t non_const_id = other_first_is_variable
                                  ? other_inst->GetSingleWordInOperand(0u)
                                  : other_inst->GetSingleWordInOperand(1u);

      uint32_t op1 = merged_id;
      uint32_t op2 = non_const_id;
      if (first_is_variable) std::swap(op1, op2);

      // Convert to multiply
      if (first_is_variable) inst->SetOpcode(other_inst->opcode());
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}});
      return true;
    }

    return false;
  };
}

// Fold divides of a constant and a negation.
// Cases:
// (-x) / 2 = x / -2
// 2 / (-x) = -2 / x
FoldingRule MergeDivNegateArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFDiv);
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    if (!inst->IsFloatingPointFoldingAllowed()) return false;

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (!other_inst->IsFloatingPointFoldingAllowed()) return false;

    bool first_is_variable = constants[0] == nullptr;
    if (other_inst->opcode() == spv::Op::OpFNegate) {
      uint32_t neg_id = NegateConstant(const_mgr, const_input1);

      if (first_is_variable) {
        inst->SetInOperands(
            {{SPV_OPERAND_TYPE_ID, {other_inst->GetSingleWordInOperand(0u)}},
             {SPV_OPERAND_TYPE_ID, {neg_id}}});
      } else {
        inst->SetInOperands(
            {{SPV_OPERAND_TYPE_ID, {neg_id}},
             {SPV_OPERAND_TYPE_ID, {other_inst->GetSingleWordInOperand(0u)}}});
      }
      return true;
    }

    return false;
  };
}

// Folds addition, where one side is a negation.
// (-x) + y = y - x
// y + (-x) = y - x
FoldingRule MergeAddNegateArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpFAdd ||
           inst->opcode() == spv::Op::OpIAdd);
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    Instruction* lhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
    Instruction* rhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));

    auto TrySubstitute = [inst, uses_float](Instruction* first,
                                            Instruction* second) {
      if (IsFoldableNegation(first)) {
        inst->SetOpcode(uses_float ? spv::Op::OpFSub : spv::Op::OpISub);
        inst->SetInOperands(
            {{SPV_OPERAND_TYPE_ID, {second->result_id()}},
             {SPV_OPERAND_TYPE_ID, {first->GetSingleWordInOperand(0u)}}});
        return true;
      }
      return false;
    };

    return TrySubstitute(lhs, rhs) || TrySubstitute(rhs, lhs);
  };
}

// Folds subtraction, where one side is a negation.
// Cases:
// (-x) - 2 = -2 - x
// y - (-x) = x + y
FoldingRule MergeSubNegateArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFSub ||
           inst->opcode() == spv::Op::OpISub);
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    Instruction* lhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
    Instruction* rhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));

    if (IsFoldableNegation(rhs)) {
      inst->SetOpcode(uses_float ? spv::Op::OpFAdd : spv::Op::OpIAdd);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {lhs->result_id()}},
           {SPV_OPERAND_TYPE_ID, {rhs->GetSingleWordInOperand(0)}}});
      return true;
    }

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    if (constants[1] && IsFoldableNegation(lhs)) {
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID,
            {NegateConstant(context->get_constant_mgr(), constants[1])}},
           {SPV_OPERAND_TYPE_ID, {lhs->GetSingleWordInOperand(0)}}});
      return true;
    }
    return false;
  };
}

// Folds addition of an addition where each operation has a constant operand.
// Cases:
// (x + 2) + 2 = x + 4
// (2 + x) + 2 = x + 4
// 2 + (x + 2) = x + 4
// 2 + (2 + x) = x + 4
FoldingRule MergeAddAddArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFAdd ||
           inst->opcode() == spv::Op::OpIAdd);
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
      return false;

    if (other_inst->opcode() == spv::Op::OpFAdd ||
        other_inst->opcode() == spv::Op::OpIAdd) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2) return false;

      Instruction* non_const_input =
          NonConstInput(context, other_constants[0], other_inst);
      uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(),
                                            const_input1, const_input2);
      if (merged_id == 0) return false;

      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {non_const_input->result_id()}},
           {SPV_OPERAND_TYPE_ID, {merged_id}}});
      return true;
    }
    return false;
  };
}

// Folds addition of a subtraction where each operation has a constant operand.
// Cases:
// (x - 2) + 2 = x + 0
// (2 - x) + 2 = 4 - x
// 2 + (x - 2) = x + 0
// 2 + (2 - x) = 4 - x
FoldingRule MergeAddSubArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFAdd ||
           inst->opcode() == spv::Op::OpIAdd);
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
      return false;

    if (other_inst->opcode() == spv::Op::OpFSub ||
        other_inst->opcode() == spv::Op::OpISub) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2) return false;

      bool first_is_variable = other_constants[0] == nullptr;
      spv::Op op = inst->opcode();
      uint32_t op1 = 0;
      uint32_t op2 = 0;
      if (first_is_variable) {
        // Subtract constants. Non-constant operand is first.
        op1 = other_inst->GetSingleWordInOperand(0u);
        op2 = PerformOperation(const_mgr, other_inst->opcode(), const_input1,
                               const_input2);
      } else {
        // Add constants. Constant operand is first. Change the opcode.
        op1 = PerformOperation(const_mgr, inst->opcode(), const_input1,
                               const_input2);
        op2 = other_inst->GetSingleWordInOperand(1u);
        op = other_inst->opcode();
      }
      if (op1 == 0 || op2 == 0) return false;

      inst->SetOpcode(op);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}});
      return true;
    }
    return false;
  };
}

// Folds subtraction of an addition where each operand has a constant operand.
// Cases:
// (x + 2) - 2 = x + 0
// (2 + x) - 2 = x + 0
// 2 - (x + 2) = 0 - x
// 2 - (2 + x) = 0 - x
FoldingRule MergeSubAddArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFSub ||
           inst->opcode() == spv::Op::OpISub);
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
      return false;

    if (other_inst->opcode() == spv::Op::OpFAdd ||
        other_inst->opcode() == spv::Op::OpIAdd) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2) return false;

      Instruction* non_const_input =
          NonConstInput(context, other_constants[0], other_inst);

      // If the first operand of the sub is not a constant, swap the constants
      // so the subtraction has the correct operands.
      if (constants[0] == nullptr) std::swap(const_input1, const_input2);
      // Subtract the constants.
      uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(),
                                            const_input1, const_input2);
      spv::Op op = inst->opcode();
      uint32_t op1 = 0;
      uint32_t op2 = 0;
      if (constants[0] == nullptr) {
        // Non-constant operand is first. Change the opcode.
        op1 = non_const_input->result_id();
        op2 = merged_id;
        op = other_inst->opcode();
      } else {
        // Constant operand is first.
        op1 = merged_id;
        op2 = non_const_input->result_id();
      }
      if (op1 == 0 || op2 == 0) return false;

      inst->SetOpcode(op);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}});
      return true;
    }
    return false;
  };
}

// Folds subtraction of a subtraction where each operand has a constant operand.
// Cases:
// (x - 2) - 2 = x - 4
// (2 - x) - 2 = 0 - x
// 2 - (x - 2) = 4 - x
// 2 - (2 - x) = x + 0
FoldingRule MergeSubSubArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFSub ||
           inst->opcode() == spv::Op::OpISub);
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);
    if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
      return false;

    if (other_inst->opcode() == spv::Op::OpFSub ||
        other_inst->opcode() == spv::Op::OpISub) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2) return false;

      Instruction* non_const_input =
          NonConstInput(context, other_constants[0], other_inst);

      // Merge the constants.
      uint32_t merged_id = 0;
      spv::Op merge_op = inst->opcode();
      if (other_constants[0] == nullptr) {
        merge_op = uses_float ? spv::Op::OpFAdd : spv::Op::OpIAdd;
      } else if (constants[0] == nullptr) {
        std::swap(const_input1, const_input2);
      }
      merged_id =
          PerformOperation(const_mgr, merge_op, const_input1, const_input2);
      if (merged_id == 0) return false;

      spv::Op op = inst->opcode();
      if (constants[0] != nullptr && other_constants[0] != nullptr) {
        // Change the operation.
        op = uses_float ? spv::Op::OpFAdd : spv::Op::OpIAdd;
      }

      uint32_t op1 = 0;
      uint32_t op2 = 0;
      if ((constants[0] == nullptr) ^ (other_constants[0] == nullptr)) {
        op1 = merged_id;
        op2 = non_const_input->result_id();
      } else {
        op1 = non_const_input->result_id();
        op2 = merged_id;
      }

      inst->SetOpcode(op);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}});
      return true;
    }
    return false;
  };
}

// Helper function for MergeGenericAddSubArithmetic. If |addend| and
// subtrahend of |sub| is the same, merge to copy of minuend of |sub|.
bool MergeGenericAddendSub(uint32_t addend, uint32_t sub, Instruction* inst) {
  IRContext* context = inst->context();
  analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  Instruction* sub_inst = def_use_mgr->GetDef(sub);
  if (sub_inst->opcode() != spv::Op::OpFSub &&
      sub_inst->opcode() != spv::Op::OpISub)
    return false;
  if (sub_inst->opcode() == spv::Op::OpFSub &&
      !sub_inst->IsFloatingPointFoldingAllowed())
    return false;
  if (addend != sub_inst->GetSingleWordInOperand(1)) return false;
  inst->SetOpcode(spv::Op::OpCopyObject);
  inst->SetInOperands(
      {{SPV_OPERAND_TYPE_ID, {sub_inst->GetSingleWordInOperand(0)}}});
  context->UpdateDefUse(inst);
  return true;
}

// Folds addition of a subtraction where the subtrahend is equal to the
// other addend. Return a copy of the minuend. Accepts generic (const and
// non-const) operands.
// Cases:
// (a - b) + b = a
// b + (a - b) = a
FoldingRule MergeGenericAddSubArithmetic() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpFAdd ||
           inst->opcode() == spv::Op::OpIAdd);
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    uint32_t add_op0 = inst->GetSingleWordInOperand(0);
    uint32_t add_op1 = inst->GetSingleWordInOperand(1);
    if (MergeGenericAddendSub(add_op0, add_op1, inst)) return true;
    return MergeGenericAddendSub(add_op1, add_op0, inst);
  };
}

// Helper function for FactorAddSubMuls.
// If |factor0_0| is the same as |factor1_0|, generate:
//   |factor0_0| * (|factor0_1| + |factor1_1|)
//   |factor0_0| * (|factor0_1| - |factor1_1|)
bool FactorAddSubMulsOpnds(uint32_t factor0_0, uint32_t factor0_1,
                           uint32_t factor1_0, uint32_t factor1_1,
                           Instruction* inst) {
  IRContext* context = inst->context();
  if (factor0_0 != factor1_0) return false;
  InstructionBuilder ir_builder(
      context, inst,
      IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
  Instruction* new_add_inst = ir_builder.AddBinaryOp(
      inst->type_id(), inst->opcode(), factor0_1, factor1_1);
  if (!new_add_inst) {
    return false;
  }

  bool is_float =
      inst->opcode() == spv::Op::OpFAdd || inst->opcode() == spv::Op::OpFSub;
  inst->SetOpcode(is_float ? spv::Op::OpFMul : spv::Op::OpIMul);
  inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {factor0_0}},
                       {SPV_OPERAND_TYPE_ID, {new_add_inst->result_id()}}});
  context->UpdateDefUse(inst);
  return true;
}

// Perform the following factoring identity, handling all operand order
// combinations:
//   (a * b) + (a * c) = a * (b + c)
//   (a * b) - (a * c) = a * (b - c)
FoldingRule FactorAddSubMuls() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpFAdd ||
           inst->opcode() == spv::Op::OpFSub ||
           inst->opcode() == spv::Op::OpIAdd ||
           inst->opcode() == spv::Op::OpISub);
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    uint32_t add_op0 = inst->GetSingleWordInOperand(0);
    Instruction* add_op0_inst = def_use_mgr->GetDef(add_op0);
    if (add_op0_inst->opcode() != spv::Op::OpFMul &&
        add_op0_inst->opcode() != spv::Op::OpIMul)
      return false;
    uint32_t add_op1 = inst->GetSingleWordInOperand(1);
    Instruction* add_op1_inst = def_use_mgr->GetDef(add_op1);
    if (add_op1_inst->opcode() != spv::Op::OpFMul &&
        add_op1_inst->opcode() != spv::Op::OpIMul)
      return false;

    // Only perform this optimization if both of the muls only have one use.
    // Otherwise this is a deoptimization in size and performance.
    if (def_use_mgr->NumUses(add_op0_inst) > 1) return false;
    if (def_use_mgr->NumUses(add_op1_inst) > 1) return false;

    if (add_op0_inst->opcode() == spv::Op::OpFMul &&
        (!add_op0_inst->IsFloatingPointFoldingAllowed() ||
         !add_op1_inst->IsFloatingPointFoldingAllowed()))
      return false;

    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2; j++) {
        // Check if operand i in add_op0_inst matches operand j in add_op1_inst.
        if (FactorAddSubMulsOpnds(add_op0_inst->GetSingleWordInOperand(i),
                                  add_op0_inst->GetSingleWordInOperand(1 - i),
                                  add_op1_inst->GetSingleWordInOperand(j),
                                  add_op1_inst->GetSingleWordInOperand(1 - j),
                                  inst))
          return true;
      }
    }
    return false;
  };
}

// Reassociate integer instructions where both operands share the same opcode
// and both source instructions contain a constant.
// e.g:
//   (a * C0) * (C1 * b) = (C0 * C1) * (a * b)
//   (a ^ C0) ^ (b ^ C1) = (C0 ^ C1) ^ (a ^ b)
//   (C0 | a) | (b | C1) = (C0 | C1) | (a | b)
//   (a & C0) & (b & C1) = (C0 & C1) & (a & b)
static const constexpr spv::Op ReassociateNestedGenericIntOps[] = {
    spv::Op::OpIMul, spv::Op::OpBitwiseOr, spv::Op::OpBitwiseXor,
    spv::Op::OpBitwiseAnd};

FoldingRule ReassociateNestedGenericInt(spv::Op opcode) {
  assert(std::find(std::begin(ReassociateNestedGenericIntOps),
                   std::end(ReassociateNestedGenericIntOps),
                   opcode) != std::end(ReassociateNestedGenericIntOps) &&
         "Wrong opcode.");

  return [opcode](IRContext* context, Instruction* inst,
                  const std::vector<const analysis::Constant*>& constants) {
    // Handled by other folding rules.
    if (constants[0] || constants[1]) {
      return false;
    }

    if (inst->opcode() != opcode) {
      return false;
    }

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    Instruction* lhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
    Instruction* rhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));

    if (lhs->opcode() != opcode || rhs->opcode() != opcode) {
      return false;
    }

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    std::vector<const analysis::Constant*> lhs_constants =
        const_mgr->GetOperandConstants(lhs);
    const analysis::Constant* lhs_const = ConstInput(lhs_constants);
    if (!lhs_const) {
      return false;
    }

    std::vector<const analysis::Constant*> rhs_constants =
        const_mgr->GetOperandConstants(rhs);
    const analysis::Constant* rhs_const = ConstInput(rhs_constants);
    if (!rhs_const) {
      return false;
    }

    uint32_t merged_constant =
        PerformOperation(const_mgr, opcode, lhs_const, rhs_const);
    if (!merged_constant) {
      return false;
    }

    InstructionBuilder ir_builder(
        context, inst,
        IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);

    Instruction* new_rhs = ir_builder.AddBinaryOp(
        inst->type_id(), opcode,
        NonConstInput(context, lhs_constants[0], lhs)->result_id(),
        NonConstInput(context, rhs_constants[0], rhs)->result_id());

    if (!new_rhs) {
      return false;
    }

    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {merged_constant}},
                         {SPV_OPERAND_TYPE_ID, {new_rhs->result_id()}}});
    return true;
  };
}

// Reassociate floating point mul/div instructions, which have mul/div inputs,
// both of which contain a constant.
// e.g:
//   (a * C0) / (C1 / b) =  (C0 / C1) * (a * b)
//   (C0 / a) * (b / C1) =  (C0 / C1) * (b / a)
//   (a / C0) / (b * C1) =  (1 / (C0 * C1)) * (a / b)
FoldingRule ReassociateNestedMulDivFloat() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFMul ||
           inst->opcode() == spv::Op::OpFDiv);

    // Handled by other folding rules.
    if (constants[0] || constants[1]) {
      return false;
    }

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    if (!inst->IsFloatingPointFoldingAllowed()) return false;

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    Instruction* lhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
    Instruction* rhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));

    bool lhs_is_mul = lhs->opcode() == spv::Op::OpFMul;
    bool lhs_is_div = lhs->opcode() == spv::Op::OpFDiv;
    bool rhs_is_mul = rhs->opcode() == spv::Op::OpFMul;
    bool rhs_is_div = rhs->opcode() == spv::Op::OpFDiv;
    if (!(lhs_is_mul || lhs_is_div) || !(rhs_is_mul || rhs_is_div)) {
      return false;
    }

    if (!lhs->IsFloatingPointFoldingAllowed() ||
        !rhs->IsFloatingPointFoldingAllowed()) {
      return false;
    }

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    std::vector<const analysis::Constant*> lhs_constants =
        const_mgr->GetOperandConstants(lhs);
    if (!lhs_constants[0] && !lhs_constants[1]) {
      return false;
    }

    std::vector<const analysis::Constant*> rhs_constants =
        const_mgr->GetOperandConstants(rhs);
    if (!rhs_constants[0] && !rhs_constants[1]) {
      return false;
    }

    const analysis::Constant* lhs_const =
        lhs_constants[0] ? lhs_constants[0] : lhs_constants[1];
    const analysis::Constant* rhs_const =
        rhs_constants[0] ? rhs_constants[0] : rhs_constants[1];
    if (!lhs_const || !rhs_const) return false;

    bool const_lhs_rcp = lhs_constants[0] ? false : lhs_is_div;
    bool const_rhs_rcp = rhs_constants[0] ? false : rhs_is_div;

    uint32_t non_const_lhs = lhs_constants[0] ? lhs->GetSingleWordInOperand(1)
                                              : lhs->GetSingleWordInOperand(0);
    bool non_const_lhs_rcp = lhs_constants[0] ? lhs_is_div : false;

    uint32_t non_const_rhs = rhs_constants[0] ? rhs->GetSingleWordInOperand(1)
                                              : rhs->GetSingleWordInOperand(0);
    bool non_const_rhs_rcp = rhs_constants[0] ? rhs_is_div : false;

    // Rcp the rhs if we're actually dividing it.
    if (inst->opcode() == spv::Op::OpFDiv) {
      const_rhs_rcp = !const_rhs_rcp;
      non_const_rhs_rcp = !non_const_rhs_rcp;
    }

    if (const_lhs_rcp) {
      lhs_const =
          const_mgr->FindDeclaredConstant(Reciprocal(const_mgr, lhs_const));
      if (!lhs_const) {
        return false;
      }
    }
    if (const_rhs_rcp) {
      rhs_const =
          const_mgr->FindDeclaredConstant(Reciprocal(const_mgr, rhs_const));
      if (!rhs_const) {
        return false;
      }
    }

    uint32_t merged_constant =
        PerformOperation(const_mgr, spv::Op::OpFMul, lhs_const, rhs_const);

    if (!merged_constant) {
      return false;
    }

    spv::Op op = spv::Op::OpNop;
    Instruction* new_rhs = nullptr;

    InstructionBuilder ir_builder(
        context, inst,
        IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);

    //  a * b => C * (b * a)
    if (!non_const_lhs_rcp && !non_const_rhs_rcp) {
      new_rhs = ir_builder.AddBinaryOp(inst->type_id(), spv::Op::OpFMul,
                                       non_const_lhs, non_const_rhs);
      op = spv::Op::OpFMul;
    }
    // 1/a * b => C * (b / a)
    else if (non_const_lhs_rcp && !non_const_rhs_rcp) {
      new_rhs = ir_builder.AddBinaryOp(inst->type_id(), spv::Op::OpFDiv,
                                       non_const_rhs, non_const_lhs);
      op = spv::Op::OpFMul;
    }
    //  a * 1/b => C * (a / b)
    else if (!non_const_lhs_rcp && non_const_rhs_rcp) {
      new_rhs = ir_builder.AddBinaryOp(inst->type_id(), spv::Op::OpFDiv,
                                       non_const_lhs, non_const_rhs);
      op = spv::Op::OpFMul;
    }
    // 1/a * 1/b => C / (a * b)
    else {
      new_rhs = ir_builder.AddBinaryOp(inst->type_id(), spv::Op::OpFMul,
                                       non_const_lhs, non_const_rhs);
      op = spv::Op::OpFDiv;
    }

    if (!new_rhs) {
      return false;
    }

    inst->SetOpcode(op);
    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {merged_constant}},
                         {SPV_OPERAND_TYPE_ID, {new_rhs->result_id()}}});
    return true;
  };
}

// Reassociate add/sub instructions, which have add/sub inputs,
// both of which contain a constant.
// e.g:
//   (a + C0) - (C1 - b) =  (C0 - C1) + (a + b)
//   (C0 - a) + (b - C1) =  (C0 - C1) + (b - a)
//   (a - C0) - (b + C1) = (-C0 - C1) + (a - b)
FoldingRule ReassociateNestedAddSub() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFAdd ||
           inst->opcode() == spv::Op::OpIAdd ||
           inst->opcode() == spv::Op::OpFSub ||
           inst->opcode() == spv::Op::OpISub);

    // Handled by other folding rules.
    if (constants[0] || constants[1]) {
      return false;
    }

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());

    if (type->IsCooperativeMatrix()) {
      return false;
    }

    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) return false;

    bool uses_float = HasFloatingPoint(type);
    if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    Instruction* lhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
    Instruction* rhs = def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));

    spv::Op add_op = uses_float ? spv::Op::OpFAdd : spv::Op::OpIAdd;
    spv::Op sub_op = uses_float ? spv::Op::OpFSub : spv::Op::OpISub;

    bool lhs_is_add = lhs->opcode() == add_op;
    bool lhs_is_sub = lhs->opcode() == sub_op;
    bool rhs_is_add = rhs->opcode() == add_op;
    bool rhs_is_sub = rhs->opcode() == sub_op;
    if (!(lhs_is_add || lhs_is_sub) || !(rhs_is_add || rhs_is_sub)) {
      return false;
    }

    if (uses_float && (!lhs->IsFloatingPointFoldingAllowed() ||
                       !rhs->IsFloatingPointFoldingAllowed())) {
      return false;
    }

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    std::vector<const analysis::Constant*> lhs_constants =
        const_mgr->GetOperandConstants(lhs);
    if (!lhs_constants[0] && !lhs_constants[1]) {
      return false;
    }

    std::vector<const analysis::Constant*> rhs_constants =
        const_mgr->GetOperandConstants(rhs);
    if (!rhs_constants[0] && !rhs_constants[1]) {
      return false;
    }

    const analysis::Constant* lhs_const =
        lhs_constants[0] ? lhs_constants[0] : lhs_constants[1];
    const analysis::Constant* rhs_const =
        rhs_constants[0] ? rhs_constants[0] : rhs_constants[1];
    if (!lhs_const || !rhs_const) return false;

    bool const_lhs_neg = lhs_constants[0] ? false : lhs_is_sub;
    bool const_rhs_neg = rhs_constants[0] ? false : rhs_is_sub;

    uint32_t non_const_lhs = lhs_constants[0] ? lhs->GetSingleWordInOperand(1)
                                              : lhs->GetSingleWordInOperand(0);
    bool non_const_lhs_neg = lhs_constants[0] ? lhs_is_sub : false;

    uint32_t non_const_rhs = rhs_constants[0] ? rhs->GetSingleWordInOperand(1)
                                              : rhs->GetSingleWordInOperand(0);
    bool non_const_rhs_neg = rhs_constants[0] ? rhs_is_sub : false;

    // Negate the rhs if we're actually subtracting it.
    if (inst->opcode() == spv::Op::OpFSub ||
        inst->opcode() == spv::Op::OpISub) {
      const_rhs_neg = !const_rhs_neg;
      non_const_rhs_neg = !non_const_rhs_neg;
    }

    if (const_lhs_neg) {
      lhs_const =
          const_mgr->FindDeclaredConstant(NegateConstant(const_mgr, lhs_const));
      if (!lhs_const) {
        return false;
      }
    }
    if (const_rhs_neg) {
      rhs_const =
          const_mgr->FindDeclaredConstant(NegateConstant(const_mgr, rhs_const));
      if (!rhs_const) {
        return false;
      }
    }

    uint32_t merged_constant =
        PerformOperation(const_mgr, add_op, lhs_const, rhs_const);

    if (!merged_constant) {
      return false;
    }

    spv::Op op = spv::Op::OpNop;
    Instruction* new_rhs = nullptr;

    InstructionBuilder ir_builder(
        context, inst,
        IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);

    //  a +  b => C + (b + a)
    if (!non_const_lhs_neg && !non_const_rhs_neg) {
      new_rhs = ir_builder.AddBinaryOp(inst->type_id(), add_op, non_const_lhs,
                                       non_const_rhs);
      op = add_op;
    }
    // -a +  b => C + (b - a)
    else if (non_const_lhs_neg && !non_const_rhs_neg) {
      new_rhs = ir_builder.AddBinaryOp(inst->type_id(), sub_op, non_const_rhs,
                                       non_const_lhs);
      op = add_op;
    }
    //  a + -b => C + (a - b)
    else if (!non_const_lhs_neg && non_const_rhs_neg) {
      new_rhs = ir_builder.AddBinaryOp(inst->type_id(), sub_op, non_const_lhs,
                                       non_const_rhs);
      op = add_op;
    }
    // -a + -b => C - (a + b)
    else {
      new_rhs = ir_builder.AddBinaryOp(inst->type_id(), add_op, non_const_lhs,
                                       non_const_rhs);
      op = sub_op;
    }

    if (!new_rhs) {
      return false;
    }

    inst->SetOpcode(op);
    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {merged_constant}},
                         {SPV_OPERAND_TYPE_ID, {new_rhs->result_id()}}});
    return true;
  };
}

FoldingRule IntMultipleBy1() {
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpIMul &&
           "Wrong opcode.  Should be OpIMul.");
    for (uint32_t i = 0; i < 2; i++) {
      if (constants[i] == nullptr) {
        continue;
      }
      const analysis::IntConstant* int_constant = constants[i]->AsIntConstant();
      if (int_constant) {
        uint32_t width = ElementWidth(int_constant->type());
        if (width != 32 && width != 64) return false;
        bool is_one = (width == 32) ? int_constant->GetU32BitValue() == 1u
                                    : int_constant->GetU64BitValue() == 1ull;
        if (is_one) {
          inst->SetOpcode(spv::Op::OpCopyObject);
          inst->SetInOperands(
              {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(1 - i)}}});
          return true;
        }
      }
    }
    return false;
  };
}

// Returns the number of elements that the |index|th in operand in |inst|
// contributes to the result of |inst|.  |inst| must be an
// OpCompositeConstructInstruction.
uint32_t GetNumOfElementsContributedByOperand(IRContext* context,
                                              const Instruction* inst,
                                              uint32_t index) {
  assert(inst->opcode() == spv::Op::OpCompositeConstruct);
  analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  analysis::TypeManager* type_mgr = context->get_type_mgr();

  analysis::Vector* result_type =
      type_mgr->GetType(inst->type_id())->AsVector();
  if (result_type == nullptr) {
    // If the result of the OpCompositeConstruct is not a vector then every
    // operands corresponds to a single element in the result.
    return 1;
  }

  // If the result type is a vector then the operands are either scalars or
  // vectors. If it is a scalar, then it corresponds to a single element.  If it
  // is a vector, then each element in the vector will be an element in the
  // result.
  uint32_t id = inst->GetSingleWordInOperand(index);
  Instruction* def = def_use_mgr->GetDef(id);
  analysis::Vector* type = type_mgr->GetType(def->type_id())->AsVector();
  if (type == nullptr) {
    return 1;
  }
  return type->element_count();
}

// Returns the in-operands for an OpCompositeExtract instruction that are needed
// to extract the |result_index|th element in the result of |inst| without using
// the result of |inst|. Returns the empty vector if |result_index| is
// out-of-bounds. |inst| must be an |OpCompositeConstruct| instruction.
std::vector<Operand> GetExtractOperandsForElementOfCompositeConstruct(
    IRContext* context, const Instruction* inst, uint32_t result_index) {
  assert(inst->opcode() == spv::Op::OpCompositeConstruct);
  analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  analysis::TypeManager* type_mgr = context->get_type_mgr();

  analysis::Type* result_type = type_mgr->GetType(inst->type_id());
  if (result_type->AsVector() == nullptr) {
    if (result_index < inst->NumInOperands()) {
      uint32_t id = inst->GetSingleWordInOperand(result_index);
      return {Operand(SPV_OPERAND_TYPE_ID, {id})};
    }
    return {};
  }

  // If the result type is a vector, then vector operands are concatenated.
  uint32_t total_element_count = 0;
  for (uint32_t idx = 0; idx < inst->NumInOperands(); ++idx) {
    uint32_t element_count =
        GetNumOfElementsContributedByOperand(context, inst, idx);
    total_element_count += element_count;
    if (result_index < total_element_count) {
      std::vector<Operand> operands;
      uint32_t id = inst->GetSingleWordInOperand(idx);
      Instruction* operand_def = def_use_mgr->GetDef(id);
      analysis::Type* operand_type = type_mgr->GetType(operand_def->type_id());

      operands.push_back({SPV_OPERAND_TYPE_ID, {id}});
      if (operand_type->AsVector()) {
        uint32_t start_index_of_id = total_element_count - element_count;
        uint32_t index_into_id = result_index - start_index_of_id;
        operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {index_into_id}});
      }
      return operands;
    }
  }
  return {};
}

bool CompositeConstructFeedingExtract(
    IRContext* context, Instruction* inst,
    const std::vector<const analysis::Constant*>&) {
  // If the input to an OpCompositeExtract is an OpCompositeConstruct,
  // then we can simply use the appropriate element in the construction.
  assert(inst->opcode() == spv::Op::OpCompositeExtract &&
         "Wrong opcode.  Should be OpCompositeExtract.");
  analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();

  // If there are no index operands, then this rule cannot do anything.
  if (inst->NumInOperands() <= 1) {
    return false;
  }

  uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
  Instruction* cinst = def_use_mgr->GetDef(cid);

  if (cinst->opcode() != spv::Op::OpCompositeConstruct) {
    return false;
  }

  uint32_t index_into_result = inst->GetSingleWordInOperand(1);
  std::vector<Operand> operands =
      GetExtractOperandsForElementOfCompositeConstruct(context, cinst,
                                                       index_into_result);

  if (operands.empty()) {
    return false;
  }

  // Add the remaining indices for extraction.
  for (uint32_t i = 2; i < inst->NumInOperands(); ++i) {
    operands.push_back(
        {SPV_OPERAND_TYPE_LITERAL_INTEGER, {inst->GetSingleWordInOperand(i)}});
  }

  if (operands.size() == 1) {
    // If there were no extra indices, then we have the final object.  No need
    // to extract any more.
    inst->SetOpcode(spv::Op::OpCopyObject);
  }

  inst->SetInOperands(std::move(operands));
  return true;
}

// Walks the indexes chain from |start| to |end| of an OpCompositeInsert or
// OpCompositeExtract instruction, and returns the type id of the final element
// being accessed. Returns 0 if a valid type could not be found.
uint32_t GetElementType(uint32_t type_id, Instruction::iterator start,
                        Instruction::iterator end,
                        const analysis::DefUseManager* def_use_manager) {
  for (auto index : make_range(std::move(start), std::move(end))) {
    const Instruction* type_inst = def_use_manager->GetDef(type_id);
    assert(index.type == SPV_OPERAND_TYPE_LITERAL_INTEGER &&
           index.words.size() == 1);
    if (type_inst->opcode() == spv::Op::OpTypeArray) {
      type_id = type_inst->GetSingleWordInOperand(0);
    } else if (type_inst->opcode() == spv::Op::OpTypeMatrix) {
      type_id = type_inst->GetSingleWordInOperand(0);
    } else if (type_inst->opcode() == spv::Op::OpTypeStruct) {
      type_id = type_inst->GetSingleWordInOperand(index.words[0]);
    } else {
      return 0;
    }
  }
  return type_id;
}

// Returns true of |inst_1| and |inst_2| have the same indexes that will be used
// to index into a composite object, excluding the last index.  The two
// instructions must have the same opcode, and be either OpCompositeExtract or
// OpCompositeInsert instructions.
bool HaveSameIndexesExceptForLast(Instruction* inst_1, Instruction* inst_2) {
  assert(inst_1->opcode() == inst_2->opcode() &&
         "Expecting the opcodes to be the same.");
  assert((inst_1->opcode() == spv::Op::OpCompositeInsert ||
          inst_1->opcode() == spv::Op::OpCompositeExtract) &&
         "Instructions must be OpCompositeInsert or OpCompositeExtract.");

  if (inst_1->NumInOperands() != inst_2->NumInOperands()) {
    return false;
  }

  uint32_t first_index_position =
      (inst_1->opcode() == spv::Op::OpCompositeInsert ? 2 : 1);
  for (uint32_t i = first_index_position; i < inst_1->NumInOperands() - 1;
       i++) {
    if (inst_1->GetSingleWordInOperand(i) !=
        inst_2->GetSingleWordInOperand(i)) {
      return false;
    }
  }
  return true;
}

// If the OpCompositeConstruct is simply putting back together elements that
// where extracted from the same source, we can simply reuse the source.
//
// This is a common code pattern because of the way that scalar replacement
// works.
bool CompositeExtractFeedingConstruct(
    IRContext* context, Instruction* inst,
    const std::vector<const analysis::Constant*>&) {
  assert(inst->opcode() == spv::Op::OpCompositeConstruct &&
         "Wrong opcode.  Should be OpCompositeConstruct.");
  analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
  uint32_t original_id = 0;

  if (inst->NumInOperands() == 0) {
    // The struct being constructed has no members.
    return false;
  }

  // Check each element to make sure they are:
  // - extractions
  // - extracting the same position they are inserting
  // - all extract from the same id.
  Instruction* first_element_inst = nullptr;
  for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
    const uint32_t element_id = inst->GetSingleWordInOperand(i);
    Instruction* element_inst = def_use_mgr->GetDef(element_id);
    if (first_element_inst == nullptr) {
      first_element_inst = element_inst;
    }

    if (element_inst->opcode() != spv::Op::OpCompositeExtract) {
      return false;
    }

    if (!HaveSameIndexesExceptForLast(element_inst, first_element_inst)) {
      return false;
    }

    if (element_inst->GetSingleWordInOperand(element_inst->NumInOperands() -
                                             1) != i) {
      return false;
    }

    if (i == 0) {
      original_id =
          element_inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
    } else if (original_id !=
               element_inst->GetSingleWordInOperand(kExtractCompositeIdInIdx)) {
      return false;
    }
  }
  assert(first_element_inst != nullptr);

  // The last check it to see that the object being extracted from is the
  // correct type.
  Instruction* original_inst = def_use_mgr->GetDef(original_id);
  uint32_t original_type_id =
      GetElementType(original_inst->type_id(), first_element_inst->begin() + 3,
                     first_element_inst->end() - 1, def_use_mgr);

  if (inst->type_id() != original_type_id) {
    return false;
  }

  if (first_element_inst->NumInOperands() == 2) {
    // Simplify by using the original object.
    inst->SetOpcode(spv::Op::OpCopyObject);
    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {original_id}}});
    return true;
  }

  // Copies the original id and all indexes except for the last to the new
  // extract instruction.
  inst->SetOpcode(spv::Op::OpCompositeExtract);
  inst->SetInOperands(std::vector<Operand>(first_element_inst->begin() + 2,
                                           first_element_inst->end() - 1));
  return true;
}

FoldingRule InsertFeedingExtract() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
           "Wrong opcode.  Should be OpCompositeExtract.");
    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
    Instruction* cinst = def_use_mgr->GetDef(cid);

    if (cinst->opcode() != spv::Op::OpCompositeInsert) {
      return false;
    }

    // Find the first position where the list of insert and extract indicies
    // differ, if at all.
    uint32_t i;
    for (i = 1; i < inst->NumInOperands(); ++i) {
      if (i + 1 >= cinst->NumInOperands()) {
        break;
      }

      if (inst->GetSingleWordInOperand(i) !=
          cinst->GetSingleWordInOperand(i + 1)) {
        break;
      }
    }

    // We are extracting the element that was inserted.
    if (i == inst->NumInOperands() && i + 1 == cinst->NumInOperands()) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID,
            {cinst->GetSingleWordInOperand(kInsertObjectIdInIdx)}}});
      return true;
    }

    // Extracting the value that was inserted along with values for the base
    // composite.  Cannot do anything.
    if (i == inst->NumInOperands()) {
      return false;
    }

    // Extracting an element of the value that was inserted.  Extract from
    // that value directly.
    if (i + 1 == cinst->NumInOperands()) {
      std::vector<Operand> operands;
      operands.push_back(
          {SPV_OPERAND_TYPE_ID,
           {cinst->GetSingleWordInOperand(kInsertObjectIdInIdx)}});
      for (; i < inst->NumInOperands(); ++i) {
        operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER,
                            {inst->GetSingleWordInOperand(i)}});
      }
      inst->SetInOperands(std::move(operands));
      return true;
    }

    // Extracting a value that is disjoint from the element being inserted.
    // Rewrite the extract to use the composite input to the insert.
    std::vector<Operand> operands;
    operands.push_back(
        {SPV_OPERAND_TYPE_ID,
         {cinst->GetSingleWordInOperand(kInsertCompositeIdInIdx)}});
    for (i = 1; i < inst->NumInOperands(); ++i) {
      operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER,
                          {inst->GetSingleWordInOperand(i)}});
    }
    inst->SetInOperands(std::move(operands));
    return true;
  };
}

// When a VectorShuffle is feeding an Extract, we can extract from one of the
// operands of the VectorShuffle.  We just need to adjust the index in the
// extract instruction.
FoldingRule VectorShuffleFeedingExtract() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
           "Wrong opcode.  Should be OpCompositeExtract.");
    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    analysis::TypeManager* type_mgr = context->get_type_mgr();
    uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
    Instruction* cinst = def_use_mgr->GetDef(cid);

    if (cinst->opcode() != spv::Op::OpVectorShuffle) {
      return false;
    }

    // Find the size of the first vector operand of the VectorShuffle
    Instruction* first_input =
        def_use_mgr->GetDef(cinst->GetSingleWordInOperand(0));
    analysis::Type* first_input_type =
        type_mgr->GetType(first_input->type_id());
    assert(first_input_type->AsVector() &&
           "Input to vector shuffle should be vectors.");
    uint32_t first_input_size = first_input_type->AsVector()->element_count();

    // Get index of the element the vector shuffle is placing in the position
    // being extracted.
    uint32_t new_index =
        cinst->GetSingleWordInOperand(2 + inst->GetSingleWordInOperand(1));

    // Extracting an undefined value so fold this extract into an undef.
    const uint32_t undef_literal_value = 0xffffffff;
    if (new_index == undef_literal_value) {
      inst->SetOpcode(spv::Op::OpUndef);
      inst->SetInOperands({});
      return true;
    }

    // Get the id of the of the vector the elemtent comes from, and update the
    // index if needed.
    uint32_t new_vector = 0;
    if (new_index < first_input_size) {
      new_vector = cinst->GetSingleWordInOperand(0);
    } else {
      new_vector = cinst->GetSingleWordInOperand(1);
      new_index -= first_input_size;
    }

    // Update the extract instruction.
    inst->SetInOperand(kExtractCompositeIdInIdx, {new_vector});
    inst->SetInOperand(1, {new_index});
    return true;
  };
}

// When an FMix with is feeding an Extract that extracts an element whose
// corresponding |a| in the FMix is 0 or 1, we can extract from one of the
// operands of the FMix.
FoldingRule FMixFeedingExtract() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
           "Wrong opcode.  Should be OpCompositeExtract.");
    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    analysis::ConstantManager* const_mgr = context->get_constant_mgr();

    uint32_t composite_id =
        inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
    Instruction* composite_inst = def_use_mgr->GetDef(composite_id);

    if (composite_inst->opcode() != spv::Op::OpExtInst) {
      return false;
    }

    uint32_t inst_set_id =
        context->get_feature_mgr()->GetExtInstImportId_GLSLstd450();

    if (composite_inst->GetSingleWordInOperand(kExtInstSetIdInIdx) !=
            inst_set_id ||
        composite_inst->GetSingleWordInOperand(kExtInstInstructionInIdx) !=
            GLSLstd450FMix) {
      return false;
    }

    // Get the |a| for the FMix instruction.
    uint32_t a_id = composite_inst->GetSingleWordInOperand(kFMixAIdInIdx);
    std::unique_ptr<Instruction> a(inst->Clone(context));
    a->SetInOperand(kExtractCompositeIdInIdx, {a_id});
    context->get_instruction_folder().FoldInstruction(a.get());

    if (a->opcode() != spv::Op::OpCopyObject) {
      return false;
    }

    const analysis::Constant* a_const =
        const_mgr->FindDeclaredConstant(a->GetSingleWordInOperand(0));

    if (!a_const) {
      return false;
    }

    bool use_x = false;

    assert(a_const->type()->AsFloat());

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    uint32_t width = ElementWidth(type);
    if (width != 32 && width != 64) {
      // We won't support folding half float values.
      return false;
    }

    double element_value = a_const->GetValueAsDouble();
    if (element_value == 0.0) {
      use_x = true;
    } else if (element_value == 1.0) {
      use_x = false;
    } else {
      return false;
    }

    // Get the id of the of the vector the element comes from.
    uint32_t new_vector = 0;
    if (use_x) {
      new_vector = composite_inst->GetSingleWordInOperand(kFMixXIdInIdx);
    } else {
      new_vector = composite_inst->GetSingleWordInOperand(kFMixYIdInIdx);
    }

    // Update the extract instruction.
    inst->SetInOperand(kExtractCompositeIdInIdx, {new_vector});
    return true;
  };
}

// Returns the number of elements in the composite type |type|.  Returns 0 if
// |type| is a scalar value. Return UINT32_MAX when the size is unknown at
// compile time.
uint32_t GetNumberOfElements(const analysis::Type* type) {
  if (auto* vector_type = type->AsVector()) {
    return vector_type->element_count();
  }
  if (auto* matrix_type = type->AsMatrix()) {
    return matrix_type->element_count();
  }
  if (auto* struct_type = type->AsStruct()) {
    return static_cast<uint32_t>(struct_type->element_types().size());
  }
  if (auto* array_type = type->AsArray()) {
    if (array_type->length_info().words[0] ==
            analysis::Array::LengthInfo::kConstant &&
        array_type->length_info().words.size() == 2) {
      return array_type->length_info().words[1];
    }
    return UINT32_MAX;
  }
  return 0;
}

// Returns a map with the set of values that were inserted into an object by
// the chain of OpCompositeInsertInstruction starting with |inst|.
// The map will map the index to the value inserted at that index. An empty map
// will be returned if the map could not be properly generated.
std::map<uint32_t, uint32_t> GetInsertedValues(Instruction* inst) {
  analysis::DefUseManager* def_use_mgr = inst->context()->get_def_use_mgr();
  std::map<uint32_t, uint32_t> values_inserted;
  Instruction* current_inst = inst;
  while (current_inst->opcode() == spv::Op::OpCompositeInsert) {
    if (current_inst->NumInOperands() > inst->NumInOperands()) {
      // This is to catch the case
      //   %2 = OpCompositeInsert %m2x2int %v2int_1_0 %m2x2int_undef 0
      //   %3 = OpCompositeInsert %m2x2int %int_4 %2 0 0
      //   %4 = OpCompositeInsert %m2x2int %v2int_2_3 %3 1
      // In this case we cannot do a single construct to get the matrix.
      uint32_t partially_inserted_element_index =
          current_inst->GetSingleWordInOperand(inst->NumInOperands() - 1);
      if (values_inserted.count(partially_inserted_element_index) == 0)
        return {};
    }
    if (HaveSameIndexesExceptForLast(inst, current_inst)) {
      values_inserted.insert(
          {current_inst->GetSingleWordInOperand(current_inst->NumInOperands() -
                                                1),
           current_inst->GetSingleWordInOperand(kInsertObjectIdInIdx)});
    }
    current_inst = def_use_mgr->GetDef(
        current_inst->GetSingleWordInOperand(kInsertCompositeIdInIdx));
  }
  return values_inserted;
}

// Returns true of there is an entry in |values_inserted| for every element of
// |Type|.
bool DoInsertedValuesCoverEntireObject(
    const analysis::Type* type, std::map<uint32_t, uint32_t>& values_inserted) {
  uint32_t container_size = GetNumberOfElements(type);
  if (container_size != values_inserted.size()) {
    return false;
  }

  if (values_inserted.rbegin()->first >= container_size) {
    return false;
  }
  return true;
}

// Returns id of the type of the element that immediately contains the element
// being inserted by the OpCompositeInsert instruction |inst|. Returns 0 if it
// could not be found.
uint32_t GetContainerTypeId(Instruction* inst) {
  assert(inst->opcode() == spv::Op::OpCompositeInsert);
  analysis::DefUseManager* def_use_manager = inst->context()->get_def_use_mgr();
  uint32_t container_type_id = GetElementType(
      inst->type_id(), inst->begin() + 4, inst->end() - 1, def_use_manager);
  return container_type_id;
}

// Returns an OpCompositeConstruct instruction that build an object with
// |type_id| out of the values in |values_inserted|.  Each value will be
// placed at the index corresponding to the value.  The new instruction will
// be placed before |insert_before|.
Instruction* BuildCompositeConstruct(
    uint32_t type_id, const std::map<uint32_t, uint32_t>& values_inserted,
    Instruction* insert_before) {
  InstructionBuilder ir_builder(
      insert_before->context(), insert_before,
      IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);

  std::vector<uint32_t> ids_in_order;
  for (auto it : values_inserted) {
    ids_in_order.push_back(it.second);
  }
  Instruction* construct =
      ir_builder.AddCompositeConstruct(type_id, ids_in_order);
  return construct;
}

// Replaces the OpCompositeInsert |inst| that inserts |construct| into the same
// object as |inst| with final index removed.  If the resulting
// OpCompositeInsert instruction would have no remaining indexes, the
// instruction is replaced with an OpCopyObject instead.
void InsertConstructedObject(Instruction* inst, const Instruction* construct) {
  if (inst->NumInOperands() == 3) {
    inst->SetOpcode(spv::Op::OpCopyObject);
    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {construct->result_id()}}});
  } else {
    inst->SetInOperand(kInsertObjectIdInIdx, {construct->result_id()});
    inst->RemoveOperand(inst->NumOperands() - 1);
  }
}

// Replaces a series of |OpCompositeInsert| instruction that cover the entire
// object with an |OpCompositeConstruct|.
bool CompositeInsertToCompositeConstruct(
    IRContext* context, Instruction* inst,
    const std::vector<const analysis::Constant*>&) {
  assert(inst->opcode() == spv::Op::OpCompositeInsert &&
         "Wrong opcode.  Should be OpCompositeInsert.");
  if (inst->NumInOperands() < 3) return false;

  std::map<uint32_t, uint32_t> values_inserted = GetInsertedValues(inst);
  uint32_t container_type_id = GetContainerTypeId(inst);
  if (container_type_id == 0) {
    return false;
  }

  analysis::TypeManager* type_mgr = context->get_type_mgr();
  const analysis::Type* container_type = type_mgr->GetType(container_type_id);
  assert(container_type && "GetContainerTypeId returned a bad id.");
  if (!DoInsertedValuesCoverEntireObject(container_type, values_inserted)) {
    return false;
  }

  Instruction* construct =
      BuildCompositeConstruct(container_type_id, values_inserted, inst);
  InsertConstructedObject(inst, construct);
  return true;
}

FoldingRule RedundantPhi() {
  // An OpPhi instruction where all values are the same or the result of the phi
  // itself, can be replaced by the value itself.
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpPhi &&
           "Wrong opcode.  Should be OpPhi.");

    uint32_t incoming_value = 0;

    for (uint32_t i = 0; i < inst->NumInOperands(); i += 2) {
      uint32_t op_id = inst->GetSingleWordInOperand(i);
      if (op_id == inst->result_id()) {
        continue;
      }

      if (incoming_value == 0) {
        incoming_value = op_id;
      } else if (op_id != incoming_value) {
        // Found two possible value.  Can't simplify.
        return false;
      }
    }

    if (incoming_value == 0) {
      // Code looks invalid.  Don't do anything.
      return false;
    }

    // We have a single incoming value.  Simplify using that value.
    inst->SetOpcode(spv::Op::OpCopyObject);
    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {incoming_value}}});
    return true;
  };
}

FoldingRule BitCastScalarOrVector() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpBitcast && constants.size() == 1);
    if (constants[0] == nullptr) return false;

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    if (HasFloatingPoint(type) && !inst->IsFloatingPointFoldingAllowed())
      return false;

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    std::vector<uint32_t> words =
        GetWordsFromNumericScalarOrVectorConstant(const_mgr, constants[0]);
    if (words.size() == 0) return false;

    const analysis::Constant* bitcasted_constant =
        ConvertWordsToNumericScalarOrVectorConstant(const_mgr, words, type);
    if (!bitcasted_constant) return false;

    auto new_feeder_id =
        const_mgr->GetDefiningInstruction(bitcasted_constant, inst->type_id())
            ->result_id();
    inst->SetOpcode(spv::Op::OpCopyObject);
    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {new_feeder_id}}});
    return true;
  };
}

// Remove indirect bitcasts which have no effect.
//   uint32 x;  asuint32(x)            => x
//   uint32 x;  asuint32(asint32(x))   => x
//   float32 x; asuint32(asint32(x))   => asuint32(x)
FoldingRule RedundantBitcast() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpBitcast);

    analysis::DefUseManager* def_mgr = context->get_def_use_mgr();
    Instruction* child = def_mgr->GetDef(inst->GetSingleWordInOperand(0));

    if (inst->type_id() == child->type_id()) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {child->result_id()}}});
      return true;
    }

    if (child->opcode() != spv::Op::OpBitcast) {
      return false;
    }

    if (def_mgr->GetDef(child->GetSingleWordInOperand(0))->type_id() ==
        inst->type_id()) {
      inst->SetOpcode(spv::Op::OpCopyObject);
    }
    inst->SetInOperands(
        {{SPV_OPERAND_TYPE_ID, {child->GetSingleWordInOperand(0)}}});

    return true;
  };
}

FoldingRule BitReverseScalarOrVector() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpBitReverse && constants.size() == 1);
    if (constants[0] == nullptr) return false;

    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    assert(!HasFloatingPoint(type) &&
           "BitReverse cannot be applied to floating point types.");
    assert((type->AsInteger() || type->AsVector()) &&
           "BitReverse can only be applied to integer scalars or vectors.");
    assert((ElementWidth(type) == 32) &&
           "BitReverse can only be applied to integer types of width 32");

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    std::vector<uint32_t> words =
        GetWordsFromNumericScalarOrVectorConstant(const_mgr, constants[0]);
    if (words.size() == 0) return false;

    for (uint32_t& word : words) {
      // Reverse the bits in each word.
      word = ((word & 0x55555555) << 1) | ((word >> 1) & 0x55555555);
      word = ((word & 0x33333333) << 2) | ((word >> 2) & 0x33333333);
      word = ((word & 0x0F0F0F0F) << 4) | ((word >> 4) & 0x0F0F0F0F);
      word = ((word & 0x00FF00FF) << 8) | ((word >> 8) & 0x00FF00FF);
      word = (word << 16) | (word >> 16);
    }

    const analysis::Constant* bitreversed_constant =
        ConvertWordsToNumericScalarOrVectorConstant(const_mgr, words, type);
    if (!bitreversed_constant) return false;

    auto new_feeder_id =
        const_mgr->GetDefiningInstruction(bitreversed_constant, inst->type_id())
            ->result_id();
    inst->SetOpcode(spv::Op::OpCopyObject);
    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {new_feeder_id}}});
    return true;
  };
}

FoldingRule RedundantSelect() {
  // An OpSelect instruction where both values are the same or the condition is
  // constant can be replaced by one of the values
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpSelect &&
           "Wrong opcode.  Should be OpSelect.");
    assert(inst->NumInOperands() == 3);
    assert(constants.size() == 3);

    uint32_t true_id = inst->GetSingleWordInOperand(1);
    uint32_t false_id = inst->GetSingleWordInOperand(2);

    if (true_id == false_id) {
      // Both results are the same, condition doesn't matter
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {true_id}}});
      return true;
    } else if (constants[0]) {
      const analysis::Type* type = constants[0]->type();
      if (type->AsBool()) {
        // Scalar constant value, select the corresponding value.
        inst->SetOpcode(spv::Op::OpCopyObject);
        if (constants[0]->AsNullConstant() ||
            !constants[0]->AsBoolConstant()->value()) {
          inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {false_id}}});
        } else {
          inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {true_id}}});
        }
        return true;
      } else {
        assert(type->AsVector());
        if (constants[0]->AsNullConstant()) {
          // All values come from false id.
          inst->SetOpcode(spv::Op::OpCopyObject);
          inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {false_id}}});
          return true;
        } else {
          // Convert to a vector shuffle.
          std::vector<Operand> ops;
          ops.push_back({SPV_OPERAND_TYPE_ID, {true_id}});
          ops.push_back({SPV_OPERAND_TYPE_ID, {false_id}});
          const analysis::VectorConstant* vector_const =
              constants[0]->AsVectorConstant();
          uint32_t size =
              static_cast<uint32_t>(vector_const->GetComponents().size());
          for (uint32_t i = 0; i != size; ++i) {
            const analysis::Constant* component =
                vector_const->GetComponents()[i];
            if (component->AsNullConstant() ||
                !component->AsBoolConstant()->value()) {
              // Selecting from the false vector which is the second input
              // vector to the shuffle. Offset the index by |size|.
              ops.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {i + size}});
            } else {
              // Selecting from true vector which is the first input vector to
              // the shuffle.
              ops.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}});
            }
          }

          inst->SetOpcode(spv::Op::OpVectorShuffle);
          inst->SetInOperands(std::move(ops));
          return true;
        }
      }
    }

    return false;
  };
}

std::optional<bool> GetBoolConstantKind(const analysis::Constant* c) {
  if (!c) {
    return {};
  }
  if (auto composite = c->AsCompositeConstant()) {
    auto& components = composite->GetComponents();
    if (components.empty()) {
      return {};
    }
    auto first = GetBoolConstantKind(components[0]);
    if (!first) {
      return {};
    }
    if (std::all_of(std::begin(components) + 1, std::end(components),
                    [first](const analysis::Constant* c2) {
                      return GetBoolConstantKind(c2) == first;
                    })) {
      return first;
    }
    return {};
  } else if (c->AsNullConstant()) {
    return false;
  } else if (c->AsBoolConstant()) {
    return c->AsBoolConstant()->value();
  }
  return {};
}

// Fold OpSelect instructions which have constant booleans as their result.
//   x ? true  : false =  x
//   x ? false : true  = !x
FoldingRule FoldConstantBooleanSelect() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpSelect);
    assert(inst->NumInOperands() == 3);
    assert(constants.size() == 3);

    if (!constants[1] || !constants[2]) {
      return false;
    }

    analysis::DefUseManager* def_mgr = context->get_def_use_mgr();
    if (inst->type_id() !=
        def_mgr->GetDef(inst->GetSingleWordInOperand(0))->type_id()) {
      return false;
    }

    std::optional<bool> uniform_true = GetBoolConstantKind(constants[1]);
    std::optional<bool> uniform_false = GetBoolConstantKind(constants[2]);

    if (!uniform_true || !uniform_false) {
      return false;
    }

    if (uniform_true.value() && !uniform_false.value()) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
      return true;
    } else if (!uniform_true.value() && uniform_false.value()) {
      inst->SetOpcode(spv::Op::OpLogicalNot);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
      return true;
    }
    return false;
  };
}

// Fold OpLogicalAnd instructions which have a constant true on one side.
//   x && true = x
//   true && x = x
FoldingRule RedundantLogicalAnd() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpLogicalAnd);

    if (GetBoolConstantKind(ConstInput(constants)) ==
        std::optional<bool>(true)) {
      Instruction* other_inst = NonConstInput(context, constants[0], inst);
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {other_inst->result_id()}}});
      return true;
    }
    return false;
  };
}

// Fold OpLogicalOr instructions which have a constant false on one side.
//   x || false = x
//   false || x = x
FoldingRule RedundantLogicalOr() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpLogicalOr);

    if (GetBoolConstantKind(ConstInput(constants)) ==
        std::optional<bool>(false)) {
      Instruction* other_inst = NonConstInput(context, constants[0], inst);
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {other_inst->result_id()}}});
      return true;
    }
    return false;
  };
}

// Fold concurrent OpLogicalNot instructions:
//   !!x = x
FoldingRule RedundantLogicalNot() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpLogicalNot);
    Instruction* child =
        context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0));
    if (child->opcode() == spv::Op::OpLogicalNot) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {child->GetSingleWordInOperand(0)}}});
      return true;
    }
    return false;
  };
}

// Cases handled:
//  ((a ? C0 : C1) == C2)  =  ((a ? (C0 == C2) : (C1 == C2))
//  ((a ? C0 : C1) != C2)  =  ((a ? (C0 != C2) : (C1 != C2))
//  ((a ? C0 : C1) <  C2)  =  ((a ? (C0 <  C2) : (C1 <  C2))
//  ((a ? C0 : C1) <= C2)  =  ((a ? (C0 <= C2) : (C1 <= C2))
//  ((a ? C0 : C1) >  C2)  =  ((a ? (C0 >  C2) : (C1 >  C2))
//  ((a ? C0 : C1) >= C2)  =  ((a ? (C0 >= C2) : (C1 >= C2))
//  ((a ? C0 : C1) || C2)  =  ((a ? (C0 || C2) : (C1 || C2))
//  ((a ? C0 : C1) && C2)  =  ((a ? (C0 && C2) : (C1 && C2))
//  ((a ? C0 : C1) +  C2)  =  ((a ? (C0 +  C2) : (C1 +  C2))
//  ((a ? C0 : C1) -  C2)  =  ((a ? (C0 -  C2) : (C1 -  C2))
//  ((a ? C0 : C1) *  C2)  =  ((a ? (C0 *  C2) : (C1 *  C2))
//  ((a ? C0 : C1) /  C2)  =  ((a ? (C0 /  C2) : (C1 /  C2))
//  ((a ? C0 : C1) >> C2)  =  ((a ? (C0 >> C2) : (C1 >> C2))
//  ((a ? C0 : C1) << C2)  =  ((a ? (C0 << C2) : (C1 << C2))
//  ((a ? C0 : C1) ^  C2)  =  ((a ? (C0 ^  C2) : (C1 ^  C2))
//  ((a ? C0 : C1) |  C2)  =  ((a ? (C0 |  C2) : (C1 |  C2))
//  ((a ? C0 : C1) &  C2)  =  ((a ? (C0 &  C2) : (C1 &  C2))
static const constexpr spv::Op MergeBinaryOpSelectOps[] = {
    spv::Op::OpLogicalEqual,
    spv::Op::OpLogicalNotEqual,
    spv::Op::OpLogicalAnd,
    spv::Op::OpLogicalOr,
    spv::Op::OpIEqual,
    spv::Op::OpINotEqual,
    spv::Op::OpUGreaterThan,
    spv::Op::OpSGreaterThan,
    spv::Op::OpUGreaterThanEqual,
    spv::Op::OpSGreaterThanEqual,
    spv::Op::OpULessThan,
    spv::Op::OpSLessThan,
    spv::Op::OpULessThanEqual,
    spv::Op::OpSLessThanEqual,
    spv::Op::OpFOrdEqual,
    spv::Op::OpFUnordEqual,
    spv::Op::OpFOrdNotEqual,
    spv::Op::OpFUnordNotEqual,
    spv::Op::OpFOrdLessThan,
    spv::Op::OpFUnordLessThan,
    spv::Op::OpFOrdGreaterThan,
    spv::Op::OpFUnordGreaterThan,
    spv::Op::OpFOrdLessThanEqual,
    spv::Op::OpFUnordLessThanEqual,
    spv::Op::OpFOrdGreaterThanEqual,
    spv::Op::OpFUnordGreaterThanEqual,
    spv::Op::OpIAdd,
    spv::Op::OpFAdd,
    spv::Op::OpISub,
    spv::Op::OpFSub,
    spv::Op::OpIMul,
    spv::Op::OpFMul,
    spv::Op::OpUDiv,
    spv::Op::OpSDiv,
    spv::Op::OpFDiv,
    spv::Op::OpVectorTimesScalar,
    spv::Op::OpShiftRightLogical,
    spv::Op::OpShiftRightArithmetic,
    spv::Op::OpShiftLeftLogical,
    spv::Op::OpBitwiseXor,
    spv::Op::OpBitwiseOr,
    spv::Op::OpBitwiseAnd};

FoldingRule MergeBinaryOpSelect(spv::Op opcode) {
  assert(std::find(std::begin(MergeBinaryOpSelectOps),
                   std::end(MergeBinaryOpSelectOps),
                   opcode) != std::end(MergeBinaryOpSelectOps) &&
         "Wrong opcode.");

  return [opcode](IRContext* context, Instruction* inst,
                  const std::vector<const analysis::Constant*>& constants) {
    const analysis::Constant* const_input = ConstInput(constants);
    if (!const_input) {
      return false;
    }
    Instruction* non_const = NonConstInput(context, constants[0], inst);
    if (non_const->opcode() != spv::Op::OpSelect) {
      return false;
    }
    std::vector<const analysis::Constant*> select_constants =
        context->get_constant_mgr()->GetOperandConstants(non_const);
    if (!select_constants[1] || !select_constants[2]) {
      return false;
    }

    InstructionBuilder ir_builder(
        context, inst,
        IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);

    Instruction *lhs, *rhs;
    if (constants[0]) {
      lhs = ir_builder.AddBinaryOp(inst->type_id(), opcode,
                                   inst->GetSingleWordInOperand(0),
                                   non_const->GetSingleWordInOperand(1));
      rhs = ir_builder.AddBinaryOp(inst->type_id(), opcode,
                                   inst->GetSingleWordInOperand(0),
                                   non_const->GetSingleWordInOperand(2));
    } else {
      lhs = ir_builder.AddBinaryOp(inst->type_id(), opcode,
                                   non_const->GetSingleWordInOperand(1),
                                   inst->GetSingleWordInOperand(1));
      rhs = ir_builder.AddBinaryOp(inst->type_id(), opcode,
                                   non_const->GetSingleWordInOperand(2),
                                   inst->GetSingleWordInOperand(1));
    }

    if (!lhs || !rhs) {
      return false;
    }

    if (context->get_instruction_folder().FoldInstruction(lhs)) {
      context->AnalyzeDefUse(lhs);
      while (lhs->opcode() == spv::Op::OpCopyObject) {
        lhs =
            context->get_def_use_mgr()->GetDef(lhs->GetSingleWordInOperand(0));
      }
    }
    if (context->get_instruction_folder().FoldInstruction(rhs)) {
      context->AnalyzeDefUse(rhs);
      while (rhs->opcode() == spv::Op::OpCopyObject) {
        rhs =
            context->get_def_use_mgr()->GetDef(rhs->GetSingleWordInOperand(0));
      }
    }
    inst->SetOpcode(spv::Op::OpSelect);
    inst->SetInOperands(
        {{SPV_OPERAND_TYPE_ID, {non_const->GetSingleWordInOperand(0)}},
         {SPV_OPERAND_TYPE_ID, {lhs->result_id()}},
         {SPV_OPERAND_TYPE_ID, {rhs->result_id()}}});
    return true;
  };
}

// Fold OpLogicalNot instructions that follow a comparison,
// if the comparison is only used by that instruction.
//
// !(a == b) = (a != b)
// !(a != b) = (a == b)
// !(a < b)  = (a >= b)
// !(a >= b) = (a < b)
// !(a > b)  = (a <= b)
// !(a <= b) = (a > b)
FoldingRule FoldLogicalNotComparison() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpLogicalNot);
    analysis::DefUseManager* def_mgr = context->get_def_use_mgr();
    Instruction* child =
        context->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0));

    if (def_mgr->NumUses(child) > 1) {
      return false;
    }

    spv::Op new_opcode = spv::Op::OpNop;
    switch (child->opcode()) {
      // (a == b) <=> (a != b)
      case spv::Op::OpIEqual:
        new_opcode = spv::Op::OpINotEqual;
        break;
      case spv::Op::OpINotEqual:
        new_opcode = spv::Op::OpIEqual;
        break;
      case spv::Op::OpFOrdEqual:
        new_opcode = spv::Op::OpFUnordNotEqual;
        break;
      case spv::Op::OpFOrdNotEqual:
        new_opcode = spv::Op::OpFUnordEqual;
        break;
      case spv::Op::OpFUnordEqual:
        new_opcode = spv::Op::OpFOrdNotEqual;
        break;
      case spv::Op::OpFUnordNotEqual:
        new_opcode = spv::Op::OpFOrdEqual;
        break;
      case spv::Op::OpLogicalEqual:
        new_opcode = spv::Op::OpLogicalNotEqual;
        break;
      case spv::Op::OpLogicalNotEqual:
        new_opcode = spv::Op::OpLogicalEqual;
        break;

      // (a > b) <=> (a <= b)
      case spv::Op::OpUGreaterThan:
        new_opcode = spv::Op::OpULessThanEqual;
        break;
      case spv::Op::OpULessThanEqual:
        new_opcode = spv::Op::OpUGreaterThan;
        break;
      case spv::Op::OpSGreaterThan:
        new_opcode = spv::Op::OpSLessThanEqual;
        break;
      case spv::Op::OpSLessThanEqual:
        new_opcode = spv::Op::OpSGreaterThan;
        break;
      case spv::Op::OpFOrdGreaterThan:
        new_opcode = spv::Op::OpFUnordLessThanEqual;
        break;
      case spv::Op::OpFOrdLessThanEqual:
        new_opcode = spv::Op::OpFUnordGreaterThan;
        break;
      case spv::Op::OpFUnordGreaterThan:
        new_opcode = spv::Op::OpFOrdLessThanEqual;
        break;
      case spv::Op::OpFUnordLessThanEqual:
        new_opcode = spv::Op::OpFOrdGreaterThan;
        break;

      // (a < b) <=> (a >= b)
      case spv::Op::OpULessThan:
        new_opcode = spv::Op::OpUGreaterThanEqual;
        break;
      case spv::Op::OpUGreaterThanEqual:
        new_opcode = spv::Op::OpULessThan;
        break;
      case spv::Op::OpSLessThan:
        new_opcode = spv::Op::OpSGreaterThanEqual;
        break;
      case spv::Op::OpSGreaterThanEqual:
        new_opcode = spv::Op::OpSLessThan;
        break;
      case spv::Op::OpFOrdLessThan:
        new_opcode = spv::Op::OpFUnordGreaterThanEqual;
        break;
      case spv::Op::OpFOrdGreaterThanEqual:
        new_opcode = spv::Op::OpFUnordLessThan;
        break;
      case spv::Op::OpFUnordLessThan:
        new_opcode = spv::Op::OpFOrdGreaterThanEqual;
        break;
      case spv::Op::OpFUnordGreaterThanEqual:
        new_opcode = spv::Op::OpFOrdLessThan;
        break;

      default:
        break;
    }

    if (new_opcode == spv::Op::OpNop) {
      return false;
    }

    inst->SetOpcode(new_opcode);
    inst->SetInOperands(
        {{SPV_OPERAND_TYPE_ID, {child->GetSingleWordInOperand(0)}},
         {SPV_OPERAND_TYPE_ID, {child->GetSingleWordInOperand(1)}}});

    return true;
  };
}

// (a == true)  =  a
// (a == false) = !a
// (a != true)  = !a
// (a != false) =  a
FoldingRule RedundantLogicalEqual() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpLogicalEqual ||
           inst->opcode() == spv::Op::OpLogicalNotEqual);

    const analysis::Constant* const_input = ConstInput(constants);
    if (!const_input) {
      return false;
    }

    analysis::DefUseManager* def_mgr = context->get_def_use_mgr();
    if (inst->type_id() !=
        def_mgr->GetDef(inst->GetSingleWordInOperand(0))->type_id()) {
      return false;
    }

    std::optional<bool> uniform_const = GetBoolConstantKind(const_input);
    if (!uniform_const) {
      return false;
    }

    bool direct_copy = inst->opcode() == spv::Op::OpLogicalEqual
                           ? uniform_const.value()
                           : !uniform_const.value();

    inst->SetOpcode(direct_copy ? spv::Op::OpCopyObject
                                : spv::Op::OpLogicalNot);
    inst->SetInOperands(
        {{SPV_OPERAND_TYPE_ID,
          {NonConstInput(context, constants[0], inst)->result_id()}}});
    return true;
  };
}

enum class FloatConstantKind { Unknown, Zero, One };

FloatConstantKind getFloatConstantKind(const analysis::Constant* constant) {
  if (constant == nullptr) {
    return FloatConstantKind::Unknown;
  }

  assert(HasFloatingPoint(constant->type()) && "Unexpected constant type");

  if (constant->AsNullConstant()) {
    return FloatConstantKind::Zero;
  } else if (const analysis::VectorConstant* vc =
                 constant->AsVectorConstant()) {
    const std::vector<const analysis::Constant*>& components =
        vc->GetComponents();
    assert(!components.empty());

    FloatConstantKind kind = getFloatConstantKind(components[0]);

    for (size_t i = 1; i < components.size(); ++i) {
      if (getFloatConstantKind(components[i]) != kind) {
        return FloatConstantKind::Unknown;
      }
    }

    return kind;
  } else if (const analysis::FloatConstant* fc = constant->AsFloatConstant()) {
    if (fc->IsZero()) return FloatConstantKind::Zero;

    uint32_t width = fc->type()->AsFloat()->width();
    if (width != 32 && width != 64) return FloatConstantKind::Unknown;

    double value = (width == 64) ? fc->GetDoubleValue() : fc->GetFloatValue();

    if (value == 0.0) {
      return FloatConstantKind::Zero;
    } else if (value == 1.0) {
      return FloatConstantKind::One;
    } else {
      return FloatConstantKind::Unknown;
    }
  } else {
    return FloatConstantKind::Unknown;
  }
}

FoldingRule RedundantFAdd() {
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFAdd &&
           "Wrong opcode.  Should be OpFAdd.");
    assert(constants.size() == 2);

    if (!inst->IsFloatingPointFoldingAllowed()) {
      return false;
    }

    FloatConstantKind kind0 = getFloatConstantKind(constants[0]);
    FloatConstantKind kind1 = getFloatConstantKind(constants[1]);

    if (kind0 == FloatConstantKind::Zero || kind1 == FloatConstantKind::Zero) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                            {inst->GetSingleWordInOperand(
                                kind0 == FloatConstantKind::Zero ? 1 : 0)}}});
      return true;
    }

    return false;
  };
}

FoldingRule RedundantFSub() {
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFSub &&
           "Wrong opcode.  Should be OpFSub.");
    assert(constants.size() == 2);

    if (!inst->IsFloatingPointFoldingAllowed()) {
      return false;
    }

    FloatConstantKind kind0 = getFloatConstantKind(constants[0]);
    FloatConstantKind kind1 = getFloatConstantKind(constants[1]);

    if (kind0 == FloatConstantKind::Zero) {
      inst->SetOpcode(spv::Op::OpFNegate);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(1)}}});
      return true;
    }

    if (kind1 == FloatConstantKind::Zero) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
      return true;
    }

    return false;
  };
}

FoldingRule RedundantFMul() {
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFMul &&
           "Wrong opcode.  Should be OpFMul.");
    assert(constants.size() == 2);

    if (!inst->IsFloatingPointFoldingAllowed()) {
      return false;
    }

    FloatConstantKind kind0 = getFloatConstantKind(constants[0]);
    FloatConstantKind kind1 = getFloatConstantKind(constants[1]);

    if (kind0 == FloatConstantKind::Zero || kind1 == FloatConstantKind::Zero) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                            {inst->GetSingleWordInOperand(
                                kind0 == FloatConstantKind::Zero ? 0 : 1)}}});
      return true;
    }

    if (kind0 == FloatConstantKind::One || kind1 == FloatConstantKind::One) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                            {inst->GetSingleWordInOperand(
                                kind0 == FloatConstantKind::One ? 1 : 0)}}});
      return true;
    }

    return false;
  };
}

FoldingRule RedundantFDiv() {
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFDiv &&
           "Wrong opcode.  Should be OpFDiv.");
    assert(constants.size() == 2);

    if (!inst->IsFloatingPointFoldingAllowed()) {
      return false;
    }

    FloatConstantKind kind0 = getFloatConstantKind(constants[0]);
    FloatConstantKind kind1 = getFloatConstantKind(constants[1]);

    if (kind0 == FloatConstantKind::Zero || kind1 == FloatConstantKind::One) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
      return true;
    }

    return false;
  };
}

FoldingRule RedundantFMod() {
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpFMod &&
           "Wrong opcode.  Should be OpFMod.");
    assert(constants.size() == 2);

    if (!inst->IsFloatingPointFoldingAllowed()) {
      return false;
    }

    FloatConstantKind kind0 = getFloatConstantKind(constants[0]);

    if (kind0 == FloatConstantKind::Zero) {
      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
      return true;
    }

    return false;
  };
}

FoldingRule RedundantFMix() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpExtInst &&
           "Wrong opcode.  Should be OpExtInst.");

    if (!inst->IsFloatingPointFoldingAllowed()) {
      return false;
    }

    uint32_t instSetId =
        context->get_feature_mgr()->GetExtInstImportId_GLSLstd450();

    if (inst->GetSingleWordInOperand(kExtInstSetIdInIdx) == instSetId &&
        inst->GetSingleWordInOperand(kExtInstInstructionInIdx) ==
            GLSLstd450FMix) {
      assert(constants.size() == 5);

      FloatConstantKind kind4 = getFloatConstantKind(constants[4]);

      if (kind4 == FloatConstantKind::Zero || kind4 == FloatConstantKind::One) {
        inst->SetOpcode(spv::Op::OpCopyObject);
        inst->SetInOperands(
            {{SPV_OPERAND_TYPE_ID,
              {inst->GetSingleWordInOperand(kind4 == FloatConstantKind::Zero
                                                ? kFMixXIdInIdx
                                                : kFMixYIdInIdx)}}});
        return true;
      }
    }

    return false;
  };
}

// Returns a folding rule that folds the instruction to operand |foldToArg|
// (0 or 1) if operand |arg| (0 or 1) is a zero constant.
FoldingRule RedundantBinaryOpWithZeroOperand(uint32_t arg, uint32_t foldToArg) {
  return [arg, foldToArg](
             IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
    assert(constants.size() == 2);

    if (constants[arg] && constants[arg]->IsZero()) {
      auto operand = inst->GetSingleWordInOperand(foldToArg);
      auto operand_type = constants[arg]->type();

      const analysis::Type* inst_type =
          context->get_type_mgr()->GetType(inst->type_id());
      if (inst_type->IsSame(operand_type)) {
        inst->SetOpcode(spv::Op::OpCopyObject);
      } else {
        inst->SetOpcode(spv::Op::OpBitcast);
      }
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {operand}}});
      return true;
    }
    return false;
  };
}

// This rule handles any of RedundantBinaryRhs0Ops with a 0 or vector 0 on the
// right-hand side (a | 0 => a).
static const constexpr spv::Op RedundantBinaryRhs0Ops[] = {
    spv::Op::OpBitwiseOr,
    spv::Op::OpBitwiseXor,
    spv::Op::OpShiftRightLogical,
    spv::Op::OpShiftRightArithmetic,
    spv::Op::OpShiftLeftLogical,
    spv::Op::OpIAdd,
    spv::Op::OpISub};
FoldingRule RedundantBinaryRhs0(spv::Op op) {
  assert(std::find(std::begin(RedundantBinaryRhs0Ops),
                   std::end(RedundantBinaryRhs0Ops),
                   op) != std::end(RedundantBinaryRhs0Ops) &&
         "Wrong opcode.");
  (void)op;
  return RedundantBinaryOpWithZeroOperand(1, 0);
}

// This rule handles any of RedundantBinaryLhs0Ops with a 0 or vector 0 on the
// left-hand side (0 | a => a).
static const constexpr spv::Op RedundantBinaryLhs0Ops[] = {
    spv::Op::OpBitwiseOr, spv::Op::OpBitwiseXor, spv::Op::OpIAdd};
FoldingRule RedundantBinaryLhs0(spv::Op op) {
  assert(std::find(std::begin(RedundantBinaryLhs0Ops),
                   std::end(RedundantBinaryLhs0Ops),
                   op) != std::end(RedundantBinaryLhs0Ops) &&
         "Wrong opcode.");
  (void)op;
  return RedundantBinaryOpWithZeroOperand(0, 1);
}

// This rule handles shifts and divisions of 0 or vector 0 by any amount
// (0 >> a => 0).
static const constexpr spv::Op RedundantBinaryLhs0To0Ops[] = {
    spv::Op::OpShiftRightLogical,
    spv::Op::OpShiftRightArithmetic,
    spv::Op::OpShiftLeftLogical,
    spv::Op::OpSDiv,
    spv::Op::OpUDiv,
    spv::Op::OpSMod,
    spv::Op::OpUMod};
FoldingRule RedundantBinaryLhs0To0(spv::Op op) {
  assert(std::find(std::begin(RedundantBinaryLhs0To0Ops),
                   std::end(RedundantBinaryLhs0To0Ops),
                   op) != std::end(RedundantBinaryLhs0To0Ops) &&
         "Wrong opcode.");
  (void)op;
  return RedundantBinaryOpWithZeroOperand(0, 0);
}

FoldingRule ReassociateCommutiveOp() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    uint32_t width = ElementWidth(type);
    if (width != 32) return false;

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);

    if (other_inst->opcode() == inst->opcode()) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2) return false;

      Instruction* non_const_input =
          NonConstInput(context, other_constants[0], other_inst);
      uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(),
                                            const_input1, const_input2);

      if (merged_id == 0) return false;
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {non_const_input->result_id()}},
           {SPV_OPERAND_TYPE_ID, {merged_id}}});
      return true;
    }

    return false;
  };
}

// A | (b | C) = b | (A | C)
// A ^ (b ^ C) = b ^ (A ^ C)
// A & (b & C) = b & (A & C)
// Where A and C are constants
static const constexpr spv::Op ReassociateCommutiveBitwiseOps[] = {
    spv::Op::OpBitwiseOr, spv::Op::OpBitwiseXor, spv::Op::OpBitwiseAnd};
FoldingRule ReassociateCommutiveBitwise(spv::Op op) {
  assert(std::find(std::begin(ReassociateCommutiveBitwiseOps),
                   std::end(ReassociateCommutiveBitwiseOps),
                   op) != std::end(ReassociateCommutiveBitwiseOps) &&
         "Wrong opcode.");
  (void)op;
  return ReassociateCommutiveOp();
}

// Returns true if all elements in |c| are 1.
bool IsAllInt1(const analysis::Constant* c) {
  if (auto composite = c->AsCompositeConstant()) {
    auto& components = composite->GetComponents();
    return std::all_of(std::begin(components), std::end(components), IsAllInt1);
  } else if (c->AsIntConstant()) {
    return c->GetSignExtendedValue() == 1;
  }

  return false;
}

// This rule handles divisions by 1 or vector 1 (a / 1 => a).
FoldingRule RedundantSUDiv() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(constants.size() == 2);
    assert((inst->opcode() == spv::Op::OpUDiv ||
            inst->opcode() == spv::Op::OpSDiv) &&
           "Wrong opcode.");

    if (constants[1] && IsAllInt1(constants[1])) {
      auto operand = inst->GetSingleWordInOperand(0);
      auto operand_type = constants[1]->type();

      const analysis::Type* inst_type =
          context->get_type_mgr()->GetType(inst->type_id());
      if (inst_type->IsSame(operand_type)) {
        inst->SetOpcode(spv::Op::OpCopyObject);
      } else {
        inst->SetOpcode(spv::Op::OpBitcast);
      }
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {operand}}});
      return true;
    }
    return false;
  };
}

// This rule handles modulo from division by 1 or vector 1 (a % 1 => 0).
FoldingRule RedundantSUMod() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(constants.size() == 2);
    assert((inst->opcode() == spv::Op::OpUMod ||
            inst->opcode() == spv::Op::OpSMod) &&
           "Wrong opcode.");

    if (constants[1] && IsAllInt1(constants[1])) {
      auto type = context->get_type_mgr()->GetType(inst->type_id());
      auto zero_id = context->get_constant_mgr()->GetNullConstId(type);

      inst->SetOpcode(spv::Op::OpCopyObject);
      inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {zero_id}}});
      return true;
    }
    return false;
  };
}

// Utility function for applying |callback| to |input1| and |input2|.
// If they are vectors it applies element wise.
// The constants |input1| and |input2| must be integers or a vector of integers.
template <typename Callback>
void ForEachIntegerConstantPair(analysis::ConstantManager* const_mgr,
                                const analysis::Constant* input1,
                                const analysis::Constant* input2,
                                Callback&& callback) {
  assert(input1 && input2);

  auto Dispatch = [&callback](const analysis::Constant* lhs,
                              const analysis::Constant* rhs) {
    assert(lhs->type()->AsInteger());
    const analysis::Integer* type = lhs->type()->AsInteger();
    uint32_t width = type->AsInteger()->width();
    assert(width == 32 || width == 64);
    if (width == 32) {
      callback(lhs->GetU32(), rhs->GetU32());
    } else {
      callback(lhs->GetU64(), rhs->GetU64());
    }
  };

  const analysis::Type* type = input1->type();
  if (const analysis::Vector* vector_type = type->AsVector()) {
    const analysis::Type* ele_type = vector_type->element_type();
    assert(ele_type->AsInteger());
    for (uint32_t i = 0; i != vector_type->element_count(); ++i) {
      const analysis::Constant* input1_comp = nullptr;
      if (const analysis::VectorConstant* input1_vector =
              input1->AsVectorConstant()) {
        input1_comp = input1_vector->GetComponents()[i];
      } else {
        assert(input1->AsNullConstant());
        input1_comp = const_mgr->GetConstant(ele_type, {});
      }

      const analysis::Constant* input2_comp = nullptr;
      if (const analysis::VectorConstant* input2_vector =
              input2->AsVectorConstant()) {
        input2_comp = input2_vector->GetComponents()[i];
      } else {
        assert(input2->AsNullConstant());
        input2_comp = const_mgr->GetConstant(ele_type, {});
      }

      assert(ele_type->AsInteger());
      Dispatch(input1_comp, input2_comp);
    }

  } else {
    assert(type->AsInteger());
    Dispatch(input1, input2);
  }
}

// Folds redundant xor and or ops that are part of an and.
// Cases handled:
// 0b1110 & (a | 0b0001) = a & 0b1110
// 0b1110 & (a ^ 0b0001) = a & 0b1110
// 0b0110 & (a | 0b1110) = 0b0110
FoldingRule RedundantAndOrXor() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpBitwiseAnd && "Wrong opcode.");
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    uint32_t width = ElementWidth(type);
    if ((width != 32) && (width != 64)) return false;

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);

    if (other_inst->opcode() == spv::Op::OpBitwiseOr ||
        other_inst->opcode() == spv::Op::OpBitwiseXor) {
      std::vector<const analysis::Constant*> other_constants =
          const_mgr->GetOperandConstants(other_inst);
      const analysis::Constant* const_input2 = ConstInput(other_constants);
      if (!const_input2) return false;

      bool can_convert_to_const = other_inst->opcode() == spv::Op::OpBitwiseOr;
      bool can_remove_inner = true;

      ForEachIntegerConstantPair(
          const_mgr, const_input1, const_input2,
          [&can_remove_inner, &can_convert_to_const](auto lhs, auto rhs) {
            // Only convert to const if 'and' is a subset of 'or'
            can_convert_to_const = can_convert_to_const && ((lhs & rhs) == lhs);
            // Only remove 'xor'/'or' if no bits intersect with 'and'
            can_remove_inner = can_remove_inner && ((lhs & rhs) == 0);
          });

      if (can_convert_to_const) {
        Instruction* const_inst =
            const_mgr->GetDefiningInstruction(const_input1);
        inst->SetOpcode(spv::Op::OpCopyObject);
        inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {const_inst->result_id()}}});
        return true;
      } else if (can_remove_inner) {
        Instruction* non_const_input =
            NonConstInput(context, other_constants[0], other_inst);
        Instruction* const_inst =
            const_mgr->GetDefiningInstruction(const_input1);
        inst->SetInOperands(
            {{SPV_OPERAND_TYPE_ID, {non_const_input->result_id()}},
             {SPV_OPERAND_TYPE_ID, {const_inst->result_id()}}});
        return true;
      }
    }
    return false;
  };
}

// Folds redundant add and sub ops that are part of an and.
// Cases handled:
// 1 & (b + 2) = b & 1
// 1 & (b - 2) = b & 1
FoldingRule RedundantAndAddSub() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpBitwiseAnd && "Wrong opcode.");
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    uint32_t width = ElementWidth(type);
    if ((width != 32) && (width != 64)) return false;

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);

    if (other_inst->opcode() != spv::Op::OpIAdd &&
        other_inst->opcode() != spv::Op::OpISub) {
      return false;
    }
    std::vector<const analysis::Constant*> other_constants =
        const_mgr->GetOperandConstants(other_inst);
    const analysis::Constant* const_input2 = ConstInput(other_constants);
    if (!const_input2) return false;

    // Only valid for subtraction if const is on the right
    if ((other_inst->opcode() == spv::Op::OpISub) && other_constants[0]) {
      return false;
    }

    bool can_remove_inner = true;
    ForEachIntegerConstantPair(const_mgr, const_input1, const_input2,
                               [&can_remove_inner](auto and_op, auto add_op) {
                                 if (can_remove_inner) {
                                   // Only valid if no bits from the +/- could
                                   // affect bits from the & operation.
                                   can_remove_inner =
                                       utils::LSB(add_op) > and_op;
                                 }
                               });

    if (can_remove_inner) {
      Instruction* non_const_input =
          NonConstInput(context, other_constants[0], other_inst);
      Instruction* const_inst = const_mgr->GetDefiningInstruction(const_input1);
      inst->SetInOperands(
          {{SPV_OPERAND_TYPE_ID, {non_const_input->result_id()}},
           {SPV_OPERAND_TYPE_ID, {const_inst->result_id()}}});
      return true;
    }
    return false;
  };
}

// Folds redundant shift ops that are part of an and.
// Cases handled:
// 1 & (b << 1) = 0
// 0x80000000 & (b >> 1) = 0
FoldingRule RedundantAndShift() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpBitwiseAnd && "Wrong opcode.");
    const analysis::Type* type =
        context->get_type_mgr()->GetType(inst->type_id());
    uint32_t width = ElementWidth(type);
    if (width != 8 && width != 16 && width != 32 && width != 64) return false;
    const uint64_t width_mask =
        (width == 64) ? ~0ull : ((1ull << width) - 1ull);

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();
    const analysis::Constant* const_input1 = ConstInput(constants);
    if (!const_input1) return false;
    Instruction* other_inst = NonConstInput(context, constants[0], inst);

    spv::Op other_op = other_inst->opcode();
    if (other_op != spv::Op::OpShiftLeftLogical &&
        other_op != spv::Op::OpShiftRightLogical) {
      return false;
    }

    std::vector<const analysis::Constant*> other_constants =
        const_mgr->GetOperandConstants(other_inst);

    // Only valid if const is on the right.
    if (other_constants[0]) return false;
    const analysis::Constant* const_input2 = other_constants[1];
    if (!const_input2) return false;

    auto get_value_u64 =
        [](const analysis::Constant* c) -> std::optional<uint64_t> {
      if (!c) return std::nullopt;
      const analysis::Integer* int_t = c->type()->AsInteger();
      if (!int_t) return std::nullopt;
      return c->GetZeroExtendedValue();
    };

    auto can_fold_component =
        [&](const analysis::Constant* mask_const,
            const analysis::Constant* shift_const) -> std::optional<bool> {
      auto lhs = get_value_u64(mask_const);
      auto rhs = get_value_u64(shift_const);
      if (!lhs || !rhs) return std::nullopt;
      if (*rhs >= width) return false;
      uint64_t lhs_masked = *lhs & width_mask;
      if (other_op == spv::Op::OpShiftRightLogical) {
        return ((lhs_masked << *rhs) & width_mask) == 0;
      }
      return ((lhs_masked >> *rhs) & width_mask) == 0;
    };

    if (const analysis::Vector* mask_vec = type->AsVector()) {
      const analysis::Vector* shift_vec = const_input2->type()->AsVector();
      if (!shift_vec ||
          shift_vec->element_count() != mask_vec->element_count()) {
        return false;
      }
      const auto mask_components = const_input1->GetVectorComponents(const_mgr);
      const auto shift_components =
          const_input2->GetVectorComponents(const_mgr);
      for (uint32_t i = 0; i != mask_vec->element_count(); ++i) {
        auto result =
            can_fold_component(mask_components[i], shift_components[i]);
        if (!result || !*result) return false;
      }
    } else {
      if (const_input2->type()->AsVector()) return false;
      auto result = can_fold_component(const_input1, const_input2);
      if (!result || !*result) return false;
    }

    auto zero_id = context->get_constant_mgr()->GetNullConstId(type);
    inst->SetOpcode(spv::Op::OpCopyObject);
    inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {zero_id}}});
    return true;
  };
}

// This rule look for a dot with a constant vector containing a single 1 and
// the rest 0s.  This is the same as doing an extract.
FoldingRule DotProductDoingExtract() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    assert(inst->opcode() == spv::Op::OpDot &&
           "Wrong opcode.  Should be OpDot.");

    analysis::ConstantManager* const_mgr = context->get_constant_mgr();

    if (!inst->IsFloatingPointFoldingAllowed()) {
      return false;
    }

    for (int i = 0; i < 2; ++i) {
      if (!constants[i]) {
        continue;
      }

      const analysis::Vector* vector_type = constants[i]->type()->AsVector();
      assert(vector_type && "Inputs to OpDot must be vectors.");
      const analysis::Float* element_type =
          vector_type->element_type()->AsFloat();
      assert(element_type && "Inputs to OpDot must be vectors of floats.");
      uint32_t element_width = element_type->width();
      if (element_width != 32 && element_width != 64) {
        return false;
      }

      std::vector<const analysis::Constant*> components;
      components = constants[i]->GetVectorComponents(const_mgr);

      constexpr uint32_t kNotFound = std::numeric_limits<uint32_t>::max();

      uint32_t component_with_one = kNotFound;
      bool all_others_zero = true;
      for (uint32_t j = 0; j < components.size(); ++j) {
        const analysis::Constant* element = components[j];
        double value =
            (element_width == 32 ? element->GetFloat() : element->GetDouble());
        if (value == 0.0) {
          continue;
        } else if (value == 1.0) {
          if (component_with_one == kNotFound) {
            component_with_one = j;
          } else {
            component_with_one = kNotFound;
            break;
          }
        } else {
          all_others_zero = false;
          break;
        }
      }

      if (!all_others_zero || component_with_one == kNotFound) {
        continue;
      }

      std::vector<Operand> operands;
      operands.push_back(
          {SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(1u - i)}});
      operands.push_back(
          {SPV_OPERAND_TYPE_LITERAL_INTEGER, {component_with_one}});

      inst->SetOpcode(spv::Op::OpCompositeExtract);
      inst->SetInOperands(std::move(operands));
      return true;
    }
    return false;
  };
}

// If we are storing an undef, then we can remove the store.
//
// TODO: We can do something similar for OpImageWrite, but checking for volatile
// is complicated.  Waiting to see if it is needed.
FoldingRule StoringUndef() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpStore &&
           "Wrong opcode.  Should be OpStore.");

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();

    // If this is a volatile store, the store cannot be removed.
    if (inst->NumInOperands() == 3) {
      if (inst->GetSingleWordInOperand(2) &
          uint32_t(spv::MemoryAccessMask::Volatile)) {
        return false;
      }
    }

    uint32_t object_id = inst->GetSingleWordInOperand(kStoreObjectInIdx);
    Instruction* object_inst = def_use_mgr->GetDef(object_id);
    if (object_inst->opcode() == spv::Op::OpUndef) {
      inst->ToNop();
      return true;
    }
    return false;
  };
}

FoldingRule VectorShuffleFeedingShuffle() {
  return [](IRContext* context, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpVectorShuffle &&
           "Wrong opcode.  Should be OpVectorShuffle.");

    analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
    analysis::TypeManager* type_mgr = context->get_type_mgr();

    Instruction* feeding_shuffle_inst =
        def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
    analysis::Vector* op0_type =
        type_mgr->GetType(feeding_shuffle_inst->type_id())->AsVector();
    uint32_t op0_length = op0_type->element_count();

    bool feeder_is_op0 = true;
    if (feeding_shuffle_inst->opcode() != spv::Op::OpVectorShuffle) {
      feeding_shuffle_inst =
          def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));
      feeder_is_op0 = false;
    }

    if (feeding_shuffle_inst->opcode() != spv::Op::OpVectorShuffle) {
      return false;
    }

    Instruction* feeder2 =
        def_use_mgr->GetDef(feeding_shuffle_inst->GetSingleWordInOperand(0));
    analysis::Vector* feeder_op0_type =
        type_mgr->GetType(feeder2->type_id())->AsVector();
    uint32_t feeder_op0_length = feeder_op0_type->element_count();

    uint32_t new_feeder_id = 0;
    std::vector<Operand> new_operands;
    new_operands.resize(
        2, {SPV_OPERAND_TYPE_ID, {0}});  // Place holders for vector operands.
    const uint32_t undef_literal = 0xffffffff;
    for (uint32_t op = 2; op < inst->NumInOperands(); ++op) {
      uint32_t component_index = inst->GetSingleWordInOperand(op);

      // Do not interpret the undefined value literal as coming from operand 1.
      if (component_index != undef_literal &&
          feeder_is_op0 == (component_index < op0_length)) {
        // This component comes from the feeding_shuffle_inst.  Update
        // |component_index| to be the index into the operand of the feeder.

        // Adjust component_index to get the index into the operands of the
        // feeding_shuffle_inst.
        if (component_index >= op0_length) {
          component_index -= op0_length;
        }
        component_index =
            feeding_shuffle_inst->GetSingleWordInOperand(component_index + 2);

        // Check if we are using a component from the first or second operand of
        // the feeding instruction.
        if (component_index < feeder_op0_length) {
          if (new_feeder_id == 0) {
            // First time through, save the id of the operand the element comes
            // from.
            new_feeder_id = feeding_shuffle_inst->GetSingleWordInOperand(0);
          } else if (new_feeder_id !=
                     feeding_shuffle_inst->GetSingleWordInOperand(0)) {
            // We need both elements of the feeding_shuffle_inst, so we cannot
            // fold.
            return false;
          }
        } else if (component_index != undef_literal) {
          if (new_feeder_id == 0) {
            // First time through, save the id of the operand the element comes
            // from.
            new_feeder_id = feeding_shuffle_inst->GetSingleWordInOperand(1);
          } else if (new_feeder_id !=
                     feeding_shuffle_inst->GetSingleWordInOperand(1)) {
            // We need both elements of the feeding_shuffle_inst, so we cannot
            // fold.
            return false;
          }
          component_index -= feeder_op0_length;
        }

        if (!feeder_is_op0 && component_index != undef_literal) {
          component_index += op0_length;
        }
      }
      new_operands.push_back(
          {SPV_OPERAND_TYPE_LITERAL_INTEGER, {component_index}});
    }

    if (new_feeder_id == 0) {
      analysis::ConstantManager* const_mgr = context->get_constant_mgr();
      const analysis::Type* type =
          type_mgr->GetType(feeding_shuffle_inst->type_id());
      const analysis::Constant* null_const = const_mgr->GetConstant(type, {});
      new_feeder_id =
          const_mgr->GetDefiningInstruction(null_const, 0)->result_id();
    }

    if (feeder_is_op0) {
      // If the size of the first vector operand changed then the indices
      // referring to the second operand need to be adjusted.
      Instruction* new_feeder_inst = def_use_mgr->GetDef(new_feeder_id);
      analysis::Type* new_feeder_type =
          type_mgr->GetType(new_feeder_inst->type_id());
      uint32_t new_op0_size = new_feeder_type->AsVector()->element_count();
      int32_t adjustment = op0_length - new_op0_size;

      if (adjustment != 0) {
        for (uint32_t i = 2; i < new_operands.size(); i++) {
          uint32_t operand = inst->GetSingleWordInOperand(i);
          if (operand >= op0_length && operand != undef_literal) {
            new_operands[i].words[0] -= adjustment;
          }
        }
      }

      new_operands[0].words[0] = new_feeder_id;
      new_operands[1] = inst->GetInOperand(1);
    } else {
      new_operands[1].words[0] = new_feeder_id;
      new_operands[0] = inst->GetInOperand(0);
    }

    inst->SetInOperands(std::move(new_operands));
    return true;
  };
}

// Removes duplicate ids from the interface list of an OpEntryPoint
// instruction.
FoldingRule RemoveRedundantOperands() {
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>&) {
    assert(inst->opcode() == spv::Op::OpEntryPoint &&
           "Wrong opcode.  Should be OpEntryPoint.");
    bool has_redundant_operand = false;
    std::unordered_set<uint32_t> seen_operands;
    std::vector<Operand> new_operands;

    new_operands.emplace_back(inst->GetOperand(0));
    new_operands.emplace_back(inst->GetOperand(1));
    new_operands.emplace_back(inst->GetOperand(2));
    for (uint32_t i = 3; i < inst->NumOperands(); ++i) {
      if (seen_operands.insert(inst->GetSingleWordOperand(i)).second) {
        new_operands.emplace_back(inst->GetOperand(i));
      } else {
        has_redundant_operand = true;
      }
    }

    if (!has_redundant_operand) {
      return false;
    }

    inst->SetInOperands(std::move(new_operands));
    return true;
  };
}

// If an image instruction's operand is a constant, updates the image operand
// flag from Offset to ConstOffset.
FoldingRule UpdateImageOperands() {
  return [](IRContext*, Instruction* inst,
            const std::vector<const analysis::Constant*>& constants) {
    const auto opcode = inst->opcode();
    (void)opcode;
    assert((opcode == spv::Op::OpImageSampleImplicitLod ||
            opcode == spv::Op::OpImageSampleExplicitLod ||
            opcode == spv::Op::OpImageSampleDrefImplicitLod ||
            opcode == spv::Op::OpImageSampleDrefExplicitLod ||
            opcode == spv::Op::OpImageSampleProjImplicitLod ||
            opcode == spv::Op::OpImageSampleProjExplicitLod ||
            opcode == spv::Op::OpImageSampleProjDrefImplicitLod ||
            opcode == spv::Op::OpImageSampleProjDrefExplicitLod ||
            opcode == spv::Op::OpImageFetch ||
            opcode == spv::Op::OpImageGather ||
            opcode == spv::Op::OpImageDrefGather ||
            opcode == spv::Op::OpImageRead || opcode == spv::Op::OpImageWrite ||
            opcode == spv::Op::OpImageSparseSampleImplicitLod ||
            opcode == spv::Op::OpImageSparseSampleExplicitLod ||
            opcode == spv::Op::OpImageSparseSampleDrefImplicitLod ||
            opcode == spv::Op::OpImageSparseSampleDrefExplicitLod ||
            opcode == spv::Op::OpImageSparseSampleProjImplicitLod ||
            opcode == spv::Op::OpImageSparseSampleProjExplicitLod ||
            opcode == spv::Op::OpImageSparseSampleProjDrefImplicitLod ||
            opcode == spv::Op::OpImageSparseSampleProjDrefExplicitLod ||
            opcode == spv::Op::OpImageSparseFetch ||
            opcode == spv::Op::OpImageSparseGather ||
            opcode == spv::Op::OpImageSparseDrefGather ||
            opcode == spv::Op::OpImageSparseRead) &&
           "Wrong opcode.  Should be an image instruction.");

    int32_t operand_index = ImageOperandsMaskInOperandIndex(inst);
    if (operand_index >= 0) {
      auto image_operands = inst->GetSingleWordInOperand(operand_index);
      if (image_operands & uint32_t(spv::ImageOperandsMask::Offset)) {
        uint32_t offset_operand_index = operand_index + 1;
        if (image_operands & uint32_t(spv::ImageOperandsMask::Bias))
          offset_operand_index++;
        if (image_operands & uint32_t(spv::ImageOperandsMask::Lod))
          offset_operand_index++;
        if (image_operands & uint32_t(spv::ImageOperandsMask::Grad))
          offset_operand_index += 2;
        assert(((image_operands &
                 uint32_t(spv::ImageOperandsMask::ConstOffset)) == 0) &&
               "Offset and ConstOffset may not be used together");
        if (offset_operand_index < inst->NumOperands()) {
          if (constants[offset_operand_index]) {
            if (constants[offset_operand_index]->IsZero()) {
              inst->RemoveInOperand(offset_operand_index);
            } else {
              image_operands = image_operands |
                               uint32_t(spv::ImageOperandsMask::ConstOffset);
            }
            image_operands =
                image_operands & ~uint32_t(spv::ImageOperandsMask::Offset);
            inst->SetInOperand(operand_index, {image_operands});
            return true;
          }
        }
      }
    }

    return false;
  };
}

}  // namespace

void FoldingRules::AddFoldingRules() {
  // Add all folding rules to the list for the opcodes to which they apply.
  // Note that the order in which rules are added to the list matters. If a rule
  // applies to the instruction, the rest of the rules will not be attempted.
  // Take that into consideration.
  for (auto op : RedundantBinaryRhs0Ops)
    rules_[op].push_back(RedundantBinaryRhs0(op));
  for (auto op : RedundantBinaryLhs0Ops)
    rules_[op].push_back(RedundantBinaryLhs0(op));
  for (auto op : RedundantBinaryLhs0To0Ops)
    rules_[op].push_back(RedundantBinaryLhs0To0(op));
  for (auto op : ReassociateCommutiveBitwiseOps)
    rules_[op].push_back(ReassociateCommutiveBitwise(op));
  for (auto op : ReassociateNestedGenericIntOps)
    rules_[op].push_back(ReassociateNestedGenericInt(op));
  for (auto op : MergeBinaryOpSelectOps)
    rules_[op].push_back(MergeBinaryOpSelect(op));
  rules_[spv::Op::OpSDiv].push_back(RedundantSUDiv());
  rules_[spv::Op::OpUDiv].push_back(RedundantSUDiv());
  rules_[spv::Op::OpSMod].push_back(RedundantSUMod());
  rules_[spv::Op::OpUMod].push_back(RedundantSUMod());

  rules_[spv::Op::OpBitcast].push_back(BitCastScalarOrVector());
  rules_[spv::Op::OpBitcast].push_back(RedundantBitcast());

  rules_[spv::Op::OpBitReverse].push_back(BitReverseScalarOrVector());

  rules_[spv::Op::OpCompositeConstruct].push_back(
      CompositeExtractFeedingConstruct);

  rules_[spv::Op::OpCompositeExtract].push_back(InsertFeedingExtract());
  rules_[spv::Op::OpCompositeExtract].push_back(
      CompositeConstructFeedingExtract);
  rules_[spv::Op::OpCompositeExtract].push_back(VectorShuffleFeedingExtract());
  rules_[spv::Op::OpCompositeExtract].push_back(FMixFeedingExtract());

  rules_[spv::Op::OpCompositeInsert].push_back(
      CompositeInsertToCompositeConstruct);

  rules_[spv::Op::OpDot].push_back(DotProductDoingExtract());

  rules_[spv::Op::OpEntryPoint].push_back(RemoveRedundantOperands());

  rules_[spv::Op::OpFAdd].push_back(RedundantFAdd());
  rules_[spv::Op::OpFAdd].push_back(MergeAddNegateArithmetic());
  rules_[spv::Op::OpFAdd].push_back(MergeAddAddArithmetic());
  rules_[spv::Op::OpFAdd].push_back(MergeAddSubArithmetic());
  rules_[spv::Op::OpFAdd].push_back(MergeGenericAddSubArithmetic());
  rules_[spv::Op::OpFAdd].push_back(ReassociateNestedAddSub());
  rules_[spv::Op::OpFAdd].push_back(FactorAddSubMuls());

  rules_[spv::Op::OpFDiv].push_back(RedundantFDiv());
  rules_[spv::Op::OpFDiv].push_back(ReciprocalFDiv());
  rules_[spv::Op::OpFDiv].push_back(MergeDivDivArithmetic());
  rules_[spv::Op::OpFDiv].push_back(MergeDivMulArithmetic());
  rules_[spv::Op::OpFDiv].push_back(MergeDivNegateArithmetic());
  rules_[spv::Op::OpFDiv].push_back(MergeDivMulDoubleNegative());
  rules_[spv::Op::OpFDiv].push_back(ReassociateNestedMulDivFloat());

  rules_[spv::Op::OpFMod].push_back(RedundantFMod());

  rules_[spv::Op::OpFMul].push_back(RedundantFMul());
  rules_[spv::Op::OpFMul].push_back(MergeMulMulArithmetic());
  rules_[spv::Op::OpFMul].push_back(MergeMulDivArithmetic());
  rules_[spv::Op::OpFMul].push_back(MergeMulNegateArithmetic());
  rules_[spv::Op::OpFMul].push_back(MergeDivMulDoubleNegative());
  rules_[spv::Op::OpFMul].push_back(ReassociateNestedMulDivFloat());

  rules_[spv::Op::OpVectorTimesScalar].push_back(MergeDivMulDoubleNegative());

  rules_[spv::Op::OpFNegate].push_back(MergeNegateArithmetic());
  rules_[spv::Op::OpFNegate].push_back(MergeNegateAddSubArithmetic());
  rules_[spv::Op::OpFNegate].push_back(MergeNegateMulDivArithmetic());

  rules_[spv::Op::OpFSub].push_back(RedundantFSub());
  rules_[spv::Op::OpFSub].push_back(MergeSubNegateArithmetic());
  rules_[spv::Op::OpFSub].push_back(MergeSubAddArithmetic());
  rules_[spv::Op::OpFSub].push_back(MergeSubSubArithmetic());
  rules_[spv::Op::OpFSub].push_back(ReassociateNestedAddSub());
  rules_[spv::Op::OpFSub].push_back(FactorAddSubMuls());

  rules_[spv::Op::OpIAdd].push_back(MergeAddNegateArithmetic());
  rules_[spv::Op::OpIAdd].push_back(MergeAddAddArithmetic());
  rules_[spv::Op::OpIAdd].push_back(MergeAddSubArithmetic());
  rules_[spv::Op::OpIAdd].push_back(MergeGenericAddSubArithmetic());
  rules_[spv::Op::OpIAdd].push_back(ReassociateNestedAddSub());
  rules_[spv::Op::OpIAdd].push_back(FactorAddSubMuls());

  rules_[spv::Op::OpSDiv].push_back(MergeDivMulDoubleNegative());

  rules_[spv::Op::OpIMul].push_back(IntMultipleBy1());
  rules_[spv::Op::OpIMul].push_back(MergeMulMulArithmetic());
  rules_[spv::Op::OpIMul].push_back(MergeMulNegateArithmetic());
  rules_[spv::Op::OpIMul].push_back(MergeDivMulDoubleNegative());

  rules_[spv::Op::OpISub].push_back(MergeSubNegateArithmetic());
  rules_[spv::Op::OpISub].push_back(MergeSubAddArithmetic());
  rules_[spv::Op::OpISub].push_back(MergeSubSubArithmetic());
  rules_[spv::Op::OpISub].push_back(ReassociateNestedAddSub());
  rules_[spv::Op::OpISub].push_back(FactorAddSubMuls());

  rules_[spv::Op::OpBitwiseAnd].push_back(RedundantAndOrXor());
  rules_[spv::Op::OpBitwiseAnd].push_back(RedundantAndAddSub());
  rules_[spv::Op::OpBitwiseAnd].push_back(RedundantAndShift());

  rules_[spv::Op::OpPhi].push_back(RedundantPhi());

  rules_[spv::Op::OpSNegate].push_back(MergeNegateArithmetic());
  rules_[spv::Op::OpSNegate].push_back(MergeNegateMulDivArithmetic());
  rules_[spv::Op::OpSNegate].push_back(MergeNegateAddSubArithmetic());

  rules_[spv::Op::OpSelect].push_back(RedundantSelect());
  rules_[spv::Op::OpSelect].push_back(FoldConstantBooleanSelect());

  rules_[spv::Op::OpLogicalAnd].push_back(RedundantLogicalAnd());

  rules_[spv::Op::OpLogicalOr].push_back(RedundantLogicalOr());

  rules_[spv::Op::OpLogicalNot].push_back(RedundantLogicalNot());
  rules_[spv::Op::OpLogicalNot].push_back(FoldLogicalNotComparison());

  rules_[spv::Op::OpLogicalEqual].push_back(RedundantLogicalEqual());
  rules_[spv::Op::OpLogicalNotEqual].push_back(RedundantLogicalEqual());

  rules_[spv::Op::OpStore].push_back(StoringUndef());

  rules_[spv::Op::OpVectorShuffle].push_back(VectorShuffleFeedingShuffle());

  rules_[spv::Op::OpImageSampleImplicitLod].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageSampleExplicitLod].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageSampleDrefImplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSampleDrefExplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSampleProjImplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSampleProjExplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSampleProjDrefImplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSampleProjDrefExplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageFetch].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageGather].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageDrefGather].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageRead].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageWrite].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageSparseSampleImplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSparseSampleExplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSparseSampleDrefImplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSparseSampleDrefExplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSparseSampleProjImplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSparseSampleProjExplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSparseSampleProjDrefImplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSparseSampleProjDrefExplicitLod].push_back(
      UpdateImageOperands());
  rules_[spv::Op::OpImageSparseFetch].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageSparseGather].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageSparseDrefGather].push_back(UpdateImageOperands());
  rules_[spv::Op::OpImageSparseRead].push_back(UpdateImageOperands());

  FeatureManager* feature_manager = context_->get_feature_mgr();
  // Add rules for GLSLstd450
  uint32_t ext_inst_glslstd450_id =
      feature_manager->GetExtInstImportId_GLSLstd450();
  if (ext_inst_glslstd450_id != 0) {
    ext_rules_[{ext_inst_glslstd450_id, GLSLstd450FMix}].push_back(
        RedundantFMix());
  }
}
}  // namespace opt
}  // namespace spvtools
