summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-deduplicate.cpp
blob: 4579ae42bfdd5b2d94469c010df3cd4bf5bc7f62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "slang-ir-insts.h"

namespace Slang
{
    void IRDeduplicationContext::init(IRModule* module)
    {
        m_module = module;
        m_session = module->getSession();

        m_globalValueNumberingMap.clear();
        m_constantMap.clear();
    }

    void IRDeduplicationContext::removeHoistableInstFromGlobalNumberingMap(IRInst* instToRemove)
    {
        InstHashSet userWorkListSet(instToRemove->getModule());
        InstWorkList userWorkList(instToRemove->getModule());
        auto addToWorkList = [&](IRInst* i)
        {
            if (userWorkListSet.add(i))
                userWorkList.add(i);
        };
        addToWorkList(instToRemove);
        for (Index i = 0; i < userWorkList.getCount(); i++)
        {
            auto inst = userWorkList[i];
            if (getIROpInfo(inst->getOp()).isHoistable())
            {
                _removeGlobalNumberingEntry(inst);
                for (auto use = inst->firstUse; use; use = use->nextUse)
                {
                    addToWorkList(use->getUser());
                }
            }
        }
    }

    void IRDeduplicationContext::tryHoistInst(IRInst* inst)
    {
        InstWorkList workList(inst->getModule());
        InstHashSet workListSet(inst->getModule());
        workList.add(inst);
        workListSet.add(inst);
        IRBuilder builder(inst->getModule());

        for (Index i = 0; i < workList.getCount(); i++)
        {
            auto item = workList[i];

            // Does inst no longer depend on anything defined locally?
            // If so we should hoist it.
            bool shouldHoist = false;
            for (UInt a = 0; a < item->getOperandCount(); a++)
            {
                auto opParent = item->getOperand(a)->getParent();
                if (opParent != item->getParent())
                {
                    shouldHoist = true;
                    break;
                }
            }

            // Hoisting this inst 
            if (shouldHoist)
            {
                item->removeFromParent();
                addHoistableInst(&builder, item);

                // Continue to consider all users for hoisting.
                for (auto use = item->firstUse; use; use = use->nextUse)
                {
                    if (getIROpInfo(use->getUser()->getOp()).isHoistable())
                    {
                        if (workListSet.add(use->getUser()))
                            workList.add(use->getUser());
                    }
                }
            }
        }
    }
}