summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-deduplicate.cpp
blob: 74efc3cb307102dafd7f820ffe8a27b2b1e4e88b (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
82
83
84
85
#include "slang-ir-insts.h"

namespace Slang
{
    void SharedIRBuilder::deduplicateAndRebuildGlobalNumberingMap()
    {
    }

    void SharedIRBuilder::replaceGlobalInst(IRInst* oldInst, IRInst* newInst)
    {
        oldInst->replaceUsesWith(newInst);
    }

    void SharedIRBuilder::removeHoistableInstFromGlobalNumberingMap(IRInst* instToRemove)
    {
        HashSet<IRInst*> userWorkListSet;
        List<IRInst*> userWorkList;
        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 addHoistableInst(
        IRBuilder* builder,
        IRInst* inst);

    void SharedIRBuilder::tryHoistInst(IRInst* inst)
    {
        List<IRInst*> workList;
        HashSet<IRInst*> workListSet;
        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());
                    }
                }
            }
        }
    }
}