// Copyright (c) 2017 The Khronos Group Inc.
// Copyright (c) 2017 Valve Corporation
// Copyright (c) 2017 LunarG Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "source/opt/local_single_store_elim_pass.h"

#include "source/cfa.h"
#include "source/util/string_utils.h"

namespace spvtools {
namespace opt {
namespace {
constexpr uint32_t kStoreValIdInIdx = 1;
constexpr uint32_t kVariableInitIdInIdx = 1;
}  // namespace

bool LocalSingleStoreElimPass::LocalSingleStoreElim(Function* func) {
  bool modified = false;

  // Check all function scope variables in |func|.
  BasicBlock* entry_block = &*func->begin();
  for (Instruction& inst : *entry_block) {
    if (inst.opcode() != spv::Op::OpVariable) {
      break;
    }

    modified |= ProcessVariable(&inst);
  }
  return modified;
}

bool LocalSingleStoreElimPass::AllExtensionsSupported() const {
  // If any extension not in allowlist, return false
  for (auto& ei : get_module()->extensions()) {
    const std::string extName = ei.GetInOperand(0).AsString();
    if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
      return false;
  }
  // only allow NonSemantic.Shader.DebugInfo.100, we cannot safely optimise
  // around unknown extended
  // instruction sets even if they are non-semantic
  for (auto& inst : context()->module()->ext_inst_imports()) {
    assert(inst.opcode() == spv::Op::OpExtInstImport &&
           "Expecting an import of an extension's instruction set.");
    const std::string extension_name = inst.GetInOperand(0).AsString();
    if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
        extension_name != "NonSemantic.Shader.DebugInfo.100") {
      return false;
    }
  }
  return true;
}

Pass::Status LocalSingleStoreElimPass::ProcessImpl() {
  // Assumes relaxed logical addressing only (see instruction.h)
  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
    return Status::SuccessWithoutChange;

  // Do not process if any disallowed extensions are enabled
  if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
  // Process all entry point functions
  ProcessFunction pfn = [this](Function* fp) {
    return LocalSingleStoreElim(fp);
  };
  bool modified = context()->ProcessReachableCallTree(pfn);
  return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
}

LocalSingleStoreElimPass::LocalSingleStoreElimPass() = default;

Pass::Status LocalSingleStoreElimPass::Process() {
  InitExtensionAllowList();
  return ProcessImpl();
}

void LocalSingleStoreElimPass::InitExtensionAllowList() {
  extensions_allowlist_.insert({"SPV_AMD_shader_explicit_vertex_parameter",
                                "SPV_AMD_shader_trinary_minmax",
                                "SPV_AMD_gcn_shader",
                                "SPV_KHR_shader_ballot",
                                "SPV_AMD_shader_ballot",
                                "SPV_AMD_gpu_shader_half_float",
                                "SPV_KHR_shader_draw_parameters",
                                "SPV_KHR_subgroup_vote",
                                "SPV_KHR_8bit_storage",
                                "SPV_KHR_16bit_storage",
                                "SPV_KHR_device_group",
                                "SPV_KHR_multiview",
                                "SPV_NVX_multiview_per_view_attributes",
                                "SPV_NV_viewport_array2",
                                "SPV_NV_stereo_view_rendering",
                                "SPV_NV_sample_mask_override_coverage",
                                "SPV_NV_geometry_shader_passthrough",
                                "SPV_AMD_texture_gather_bias_lod",
                                "SPV_KHR_storage_buffer_storage_class",
                                "SPV_KHR_variable_pointers",
                                "SPV_AMD_gpu_shader_int16",
                                "SPV_KHR_post_depth_coverage",
                                "SPV_KHR_shader_atomic_counter_ops",
                                "SPV_EXT_shader_stencil_export",
                                "SPV_EXT_shader_viewport_index_layer",
                                "SPV_AMD_shader_image_load_store_lod",
                                "SPV_AMD_shader_fragment_mask",
                                "SPV_EXT_fragment_fully_covered",
                                "SPV_AMD_gpu_shader_half_float_fetch",
                                "SPV_GOOGLE_decorate_string",
                                "SPV_GOOGLE_hlsl_functionality1",
                                "SPV_NV_shader_subgroup_partitioned",
                                "SPV_EXT_descriptor_indexing",
                                "SPV_NV_fragment_shader_barycentric",
                                "SPV_NV_compute_shader_derivatives",
                                "SPV_NV_shader_image_footprint",
                                "SPV_NV_shading_rate",
                                "SPV_NV_mesh_shader",
                                "SPV_EXT_mesh_shader",
                                "SPV_NV_ray_tracing",
                                "SPV_KHR_ray_query",
                                "SPV_EXT_fragment_invocation_density",
                                "SPV_EXT_physical_storage_buffer",
                                "SPV_KHR_physical_storage_buffer",
                                "SPV_KHR_terminate_invocation",
                                "SPV_KHR_subgroup_uniform_control_flow",
                                "SPV_KHR_integer_dot_product",
                                "SPV_EXT_shader_image_int64",
                                "SPV_KHR_non_semantic_info",
                                "SPV_KHR_uniform_group_instructions",
                                "SPV_KHR_fragment_shader_barycentric",
                                "SPV_KHR_vulkan_memory_model",
                                "SPV_NV_bindless_texture",
                                "SPV_EXT_shader_atomic_float_add",
                                "SPV_EXT_fragment_shader_interlock",
                                "SPV_NV_compute_shader_derivatives"});
}
bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) {
  std::vector<Instruction*> users;
  FindUses(var_inst, &users);

  Instruction* store_inst = FindSingleStoreAndCheckUses(var_inst, users);

  if (store_inst == nullptr) {
    return false;
  }

  bool all_rewritten;
  bool modified = RewriteLoads(store_inst, users, &all_rewritten);

  // If all uses are rewritten and the variable has a DebugDeclare and the
  // variable is not an aggregate, add a DebugValue after the store and remove
  // the DebugDeclare.
  uint32_t var_id = var_inst->result_id();
  if (all_rewritten &&
      context()->get_debug_info_mgr()->IsVariableDebugDeclared(var_id)) {
    const analysis::Type* var_type =
        context()->get_type_mgr()->GetType(var_inst->type_id());
    const analysis::Type* store_type = var_type->AsPointer()->pointee_type();
    if (!(store_type->AsStruct() || store_type->AsArray())) {
      modified |= RewriteDebugDeclares(store_inst, var_id);
    }
  }

  return modified;
}

bool LocalSingleStoreElimPass::RewriteDebugDeclares(Instruction* store_inst,
                                                    uint32_t var_id) {
  uint32_t value_id = store_inst->GetSingleWordInOperand(1);
  bool modified = context()->get_debug_info_mgr()->AddDebugValueForVariable(
      store_inst, var_id, value_id, store_inst);
  modified |= context()->get_debug_info_mgr()->KillDebugDeclares(var_id);
  return modified;
}

Instruction* LocalSingleStoreElimPass::FindSingleStoreAndCheckUses(
    Instruction* var_inst, const std::vector<Instruction*>& users) const {
  // Make sure there is exactly 1 store.
  Instruction* store_inst = nullptr;

  // If |var_inst| has an initializer, then that will count as a store.
  if (var_inst->NumInOperands() > 1) {
    store_inst = var_inst;
  }

  for (Instruction* user : users) {
    switch (user->opcode()) {
      case spv::Op::OpStore:
        // Since we are in the relaxed addressing mode, the use has to be the
        // base address of the store, and not the value being store.  Otherwise,
        // we would have a pointer to a pointer to function scope memory, which
        // is not allowed.
        if (store_inst == nullptr) {
          store_inst = user;
        } else {
          // More than 1 store.
          return nullptr;
        }
        break;
      case spv::Op::OpAccessChain:
      case spv::Op::OpInBoundsAccessChain:
        if (FeedsAStore(user)) {
          // Has a partial store.  Cannot propagate that.
          return nullptr;
        }
        break;
      case spv::Op::OpLoad:
      case spv::Op::OpImageTexelPointer:
      case spv::Op::OpName:
      case spv::Op::OpCopyObject:
        break;
      case spv::Op::OpExtInst: {
        auto dbg_op = user->GetCommonDebugOpcode();
        if (dbg_op == CommonDebugInfoDebugDeclare ||
            dbg_op == CommonDebugInfoDebugValue) {
          break;
        }
        return nullptr;
      }
      default:
        if (!user->IsDecoration()) {
          // Don't know if this instruction modifies the variable.
          // Conservatively assume it is a store.
          return nullptr;
        }
        break;
    }
  }
  return store_inst;
}

void LocalSingleStoreElimPass::FindUses(
    const Instruction* var_inst, std::vector<Instruction*>* users) const {
  analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
  def_use_mgr->ForEachUser(var_inst, [users, this](Instruction* user) {
    users->push_back(user);
    if (user->opcode() == spv::Op::OpCopyObject) {
      FindUses(user, users);
    }
  });
}

bool LocalSingleStoreElimPass::FeedsAStore(Instruction* inst) const {
  analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
  return !def_use_mgr->WhileEachUser(inst, [this](Instruction* user) {
    switch (user->opcode()) {
      case spv::Op::OpStore:
        return false;
      case spv::Op::OpAccessChain:
      case spv::Op::OpInBoundsAccessChain:
      case spv::Op::OpCopyObject:
        return !FeedsAStore(user);
      case spv::Op::OpLoad:
      case spv::Op::OpImageTexelPointer:
      case spv::Op::OpName:
        return true;
      default:
        // Don't know if this instruction modifies the variable.
        // Conservatively assume it is a store.
        return user->IsDecoration();
    }
  });
}

bool LocalSingleStoreElimPass::RewriteLoads(
    Instruction* store_inst, const std::vector<Instruction*>& uses,
    bool* all_rewritten) {
  BasicBlock* store_block = context()->get_instr_block(store_inst);
  DominatorAnalysis* dominator_analysis =
      context()->GetDominatorAnalysis(store_block->GetParent());

  uint32_t stored_id;
  if (store_inst->opcode() == spv::Op::OpStore)
    stored_id = store_inst->GetSingleWordInOperand(kStoreValIdInIdx);
  else
    stored_id = store_inst->GetSingleWordInOperand(kVariableInitIdInIdx);

  *all_rewritten = true;
  bool modified = false;
  for (Instruction* use : uses) {
    if (use->opcode() == spv::Op::OpStore) continue;
    auto dbg_op = use->GetCommonDebugOpcode();
    if (dbg_op == CommonDebugInfoDebugDeclare ||
        dbg_op == CommonDebugInfoDebugValue)
      continue;
    if (use->opcode() == spv::Op::OpLoad &&
        dominator_analysis->Dominates(store_inst, use)) {
      modified = true;
      context()->KillNamesAndDecorates(use->result_id());
      context()->ReplaceAllUsesWith(use->result_id(), stored_id);
      context()->KillInst(use);
    } else {
      *all_rewritten = false;
    }
  }

  return modified;
}

}  // namespace opt
}  // namespace spvtools
