#pragma once

#include "IR.h"

namespace sysy {

// 稀疏条件常量传播类
// Sparse Conditional Constant Propagation
/*
伪代码
function SCCP_Optimization(Module):
    for each Function in Module:
        changed = true
        while changed:
            changed = false
            // 阶段1: 常量传播与折叠
            changed |= PropagateConstants(Function)
            // 阶段2: 控制流简化
            changed |= SimplifyControlFlow(Function)
        end while
    end for

function PropagateConstants(Function):
    // 初始化
    executableBlocks = {entryBlock}
    valueState = map<Value, State> // 值->状态映射
    instWorkList = Queue()
    edgeWorkList = Queue()
    
    // 初始化工作列表
    for each inst in entryBlock:
        instWorkList.push(inst)
    
    // 迭代处理
    while !instWorkList.empty() || !edgeWorkList.empty():
        // 处理指令工作列表
        while !instWorkList.empty():
            inst = instWorkList.pop()
            // 如果指令是可执行基本块中的
            if executableBlocks.contains(inst.parent):
                ProcessInstruction(inst)
        
        // 处理边工作列表
        while !edgeWorkList.empty():
            edge = edgeWorkList.pop()
            ProcessEdge(edge)
    
    // 应用常量替换
    for each inst in Function:
        if valueState[inst] == CONSTANT:
            ReplaceWithConstant(inst, valueState[inst].constant)
            changed = true
    
    return changed

function ProcessInstruction(Instruction inst):
    switch inst.type:
        //二元操作
        case BINARY_OP:
            lhs = GetValueState(inst.operands[0])
            rhs = GetValueState(inst.operands[1])
            if lhs == CONSTANT && rhs == CONSTANT:
                newState = ComputeConstant(inst.op, lhs.value, rhs.value)
                UpdateState(inst, newState)
            else if lhs == BOTTOM || rhs == BOTTOM:
                UpdateState(inst, BOTTOM)
        //phi
        case PHI:
            mergedState = ⊤
            for each incoming in inst.incomings:
            // 检查每个输入的状态
                if executableBlocks.contains(incoming.block):
                    incomingState = GetValueState(incoming.value)
                    mergedState = Meet(mergedState, incomingState)
            UpdateState(inst, mergedState)
        // 条件分支
        case COND_BRANCH:
            cond = GetValueState(inst.condition)
            if cond == CONSTANT:
                // 判断条件分支
                if cond.value == true:
                    AddEdgeToWorkList(inst.parent, inst.trueTarget)
                else:
                    AddEdgeToWorkList(inst.parent, inst.falseTarget)
            else if cond == BOTTOM:
                AddEdgeToWorkList(inst.parent, inst.trueTarget)
                AddEdgeToWorkList(inst.parent, inst.falseTarget)
        
        case UNCOND_BRANCH:
            AddEdgeToWorkList(inst.parent, inst.target)
        
        // 其他指令处理...

function ProcessEdge(Edge edge):
    fromBB, toBB = edge
    if !executableBlocks.contains(toBB):
        executableBlocks.add(toBB)
        for each inst in toBB:
            if inst is PHI:
                instWorkList.push(inst)
            else:
                instWorkList.push(inst) // 非PHI指令
    
    // 更新PHI节点的输入
    for each phi in toBB.phis:
        instWorkList.push(phi)

function SimplifyControlFlow(Function):
    changed = false
    // 标记可达基本块
    ReachableBBs = FindReachableBlocks(Function.entry)
    
    // 删除不可达块
    for each bb in Function.blocks:
        if !ReachableBBs.contains(bb):
            RemoveDeadBlock(bb)
            changed = true
    
    // 简化条件分支
    for each bb in Function.blocks:
        terminator = bb.terminator
        if terminator is COND_BRANCH:
            cond = GetValueState(terminator.condition)
            if cond == CONSTANT:
                SimplifyBranch(terminator, cond.value)
                changed = true
    
    return changed

function RemoveDeadBlock(BasicBlock bb):
    // 1. 更新前驱块的分支指令
    for each pred in bb.predecessors:
        UpdateTerminator(pred, bb)
    
    // 2. 更新后继块的PHI节点
    for each succ in bb.successors:
        RemovePhiIncoming(succ, bb)
    
    // 3. 删除块内所有指令
    for each inst in bb.instructions:
        inst.remove()
    
    // 4. 从函数中移除基本块
    Function.removeBlock(bb)

function Meet(State a, State b):
    if a == ⊤: return b
    if b == ⊤: return a
    if a == ⊥ || b == ⊥: return ⊥
    if a.value == b.value: return a
    return ⊥

function UpdateState(Value v, State newState):
    oldState = valueState.get(v, ⊤)
    if newState != oldState:
        valueState[v] = newState
        for each user in v.users:
            if user is Instruction:
                instWorkList.push(user)

*/

enum class LatticeValue {
  Top,       // ⊤ (Unknown)
  Constant,  // c (Constant)
  Bottom     // ⊥ (Undefined / Varying)
};
// LatticeValue: 用于表示值的状态，Top表示未知，Constant表示常量，Bottom表示未定义或变化的值。
// 这里的LatticeValue用于跟踪每个SSA值（变量、指令结果）的状态，
// 以便在SCCP过程中进行常量传播和控制流简化。

//TODO: 下列数据结构考虑集成到类中，避免重命名问题
static std::set<Instruction *> Worklist;
static std::unordered_set<BasicBlock*> Executable_Blocks;
static std::queue<std::pair<BasicBlock *, BasicBlock *> > Executable_Edges;
static std::map<Value*, LatticeValue> valueState;

class SCCP {
private:
  Module *pModule;

public:
  SCCP(Module *pMoudle) : pModule(pMoudle) {}

  void run();
  bool PropagateConstants(Function *function);
  bool SimplifyControlFlow(Function *function);
  void ProcessInstruction(Instruction *inst);
  void ProcessEdge(const std::pair<BasicBlock *, BasicBlock *> &edge);
  void RemoveDeadBlock(BasicBlock *bb);
  void UpdateState(Value *v, LatticeValue newState);
  LatticeValue Meet(LatticeValue a, LatticeValue b);
  LatticeValue GetValueState(Value *v);
};

}  // namespace sysy
