#include "DCE.h"            // 包含DCE遍的头文件
#include "IR.h"             // 包含IR相关的定义
#include "SysYIROptUtils.h" // 包含SysY IR优化工具类的定义
#include <cassert>          // 用于断言
#include <iostream>         // 用于调试输出
#include <set>              // 包含set，虽然DCEContext内部用unordered_set，但这里保留

namespace sysy {

// DCE 遍的静态 ID
void *DCE::ID = (void *)&DCE::ID;

// ======================================================================
// DCEContext 类的实现
// 封装了 DCE 遍的核心逻辑和状态，确保每次函数优化运行时状态独立
// ======================================================================

// DCEContext 的 run 方法实现
void DCEContext::run(Function *func, AnalysisManager *AM, bool &changed) {
  // 清空活跃指令集合，确保每次运行都是新的状态
  alive_insts.clear();

  // 第一次遍历：扫描所有指令，识别“天然活跃”的指令并将其及其依赖标记为活跃
  // 使用 func->getBasicBlocks() 获取基本块列表，保留用户风格
  auto basicBlocks = func->getBasicBlocks();
  for (auto &basicBlock : basicBlocks) {
    // 确保基本块有效
    if (!basicBlock)
      continue;
    // 使用 basicBlock->getInstructions() 获取指令列表，保留用户风格
    for (auto &inst : basicBlock->getInstructions()) {
      // 确保指令有效
      if (!inst)
        continue;
      // 调用 DCEContext 自身的 isAlive 和 addAlive 方法
      if (isAlive(inst.get())) {
        addAlive(inst.get());
      }
    }
  }

  // 第二次遍历：删除所有未被标记为活跃的指令。
  for (auto &basicBlock : basicBlocks) {
    if (!basicBlock)
      continue;
    // 使用传统的迭代器循环，并手动管理迭代器，
    // 以便在删除元素后正确前进。保留用户风格
    for (auto instIter = basicBlock->getInstructions().begin(); instIter != basicBlock->getInstructions().end();) {
      auto &inst = *instIter;
      Instruction *currentInst = inst.get();
      // 如果指令不在活跃集合中，则删除它。
      // 分支和返回指令由 isAlive 处理，并会被保留。
      if (alive_insts.count(currentInst) == 0) {
        // 删除指令，保留用户风格的 SysYIROptUtils::usedelete 和 erase
        changed = true; // 标记 IR 已被修改
        SysYIROptUtils::usedelete(currentInst);
        instIter = basicBlock->getInstructions().erase(instIter); // 删除后返回下一个迭代器
      } else {
        ++instIter; // 指令活跃，移动到下一个
      }
    }
  }
}

// 判断指令是否是“天然活跃”的实现
// 只有具有副作用的指令（如存储、函数调用、原子操作）
// 和控制流指令（如分支、返回）是天然活跃的。
bool DCEContext::isAlive(Instruction *inst) {
  // TODO: 后续程序并发考虑原子操作
  // 其结果不被其他指令使用的指令（例如 StoreInst, BranchInst, ReturnInst）。
  // dynamic_cast<ir::CallInst>(inst) 检查是否是函数调用指令，
  // 函数调用通常有副作用。
  // 终止指令 (BranchInst, ReturnInst) 必须是活跃的，因为它控制了程序的执行流程。
  // 保留用户提供的 isAlive 逻辑
  bool isBranchOrReturn = inst->isBranch() || inst->isReturn();
  bool isCall = inst->isCall();
  bool isStoreOrMemset = inst->isStore() || inst->isMemset(); 
  return isBranchOrReturn || isCall || isStoreOrMemset;
}

// 递归地将活跃指令及其依赖加入到 alive_insts 集合中
void DCEContext::addAlive(Instruction *inst) {
  // 如果指令已经存在于活跃集合中，则无需重复处理
  if (alive_insts.count(inst) > 0) {
    return;
  }
  // 将当前指令标记为活跃
  alive_insts.insert(inst);
  // 遍历当前指令的所有操作数
  // 保留用户提供的 getOperands() 和 getValue()
  for (auto operand : inst->getOperands()) {
    // 如果操作数是一个指令（即它是一个值的定义），
    // 并且它还没有被标记为活跃
    if (auto opInst = dynamic_cast<Instruction *>(operand->getValue())) {
      addAlive(opInst); // 递归地将操作数指令标记为活跃
    }
  }
}

// ======================================================================
// DCE Pass 类的实现
// 主要负责与 PassManager 交互，创建 DCEContext 实例并运行优化
// ======================================================================

// DCE 遍的 runOnFunction 方法实现
bool DCE::runOnFunction(Function *func, AnalysisManager &AM) {

  DCEContext ctx;
  bool changed = false;
  ctx.run(func, &AM, changed); // 运行 DCE 优化

  // 如果 IR 被修改，则使相关的分析结果失效
  if (changed) {
    // DCE 会删除指令，这会影响数据流分析，尤其是活跃性分析。
    // 如果删除导致基本块变空，也可能间接影响 CFG 和支配树。
    // AM.invalidateAnalysis(&LivenessAnalysisPass::ID, func); // 活跃性分析失效
    // AM.invalidateAnalysis(&DominatorTreeAnalysisPass::ID, func); // 支配树分析可能失效
    // 其他所有依赖于数据流或 IR 结构的分析都可能失效。
  }
  return changed;
}

// 声明DCE遍的分析依赖和失效信息
void DCE::getAnalysisUsage(std::set<void *> &analysisDependencies, std::set<void *> &analysisInvalidations) const {
  // DCE不依赖特定的分析结果，它通过遍历和副作用判断来工作。

  // DCE会删除指令，这会影响许多分析结果。
  // 至少，它会影响活跃性分析、支配树、控制流图（如果删除导致基本块为空并被合并）。
  // 假设存在LivenessAnalysisPass和DominatorTreeAnalysisPass
  // analysisInvalidations.insert(&LivenessAnalysisPass::ID);
  // analysisInvalidations.insert(&DominatorTreeAnalysisPass::ID);
  // 任何改变IR结构的优化，都可能导致通用分析（如活跃性、支配树、循环信息）失效。
  // 最保守的做法是使所有函数粒度的分析失效，或者只声明你明确知道会受影响的分析。
  // 考虑到这个DCE仅删除指令，如果它不删除基本块，CFG可能不变，但数据流分析会失效。
  // 对于更激进的DCE（如ADCE），CFG也会改变。
  // 这里我们假设它主要影响数据流分析，并且可能间接影响CFG相关分析。
  // 如果有SideEffectInfo，它也可能被修改，但通常SideEffectInfo是静态的，不因DCE而变。
}

} // namespace sysy
