File: RayTracingMemDSEPass.cpp

package info (click to toggle)
intel-graphics-compiler 1.0.12504.6-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 83,912 kB
  • sloc: cpp: 910,147; lisp: 202,655; ansic: 15,197; python: 4,025; yacc: 2,241; lex: 1,570; pascal: 244; sh: 104; makefile: 25
file content (168 lines) | stat: -rw-r--r-- 4,996 bytes parent folder | download
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*========================== begin_copyright_notice ============================

Copyright (C) 2021 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

//===----------------------------------------------------------------------===//
///
/// This pass teaches IGC that raytracing memory like the SWStack is dead
/// if we can guarantee that a Stack ID Release is executed without any
/// intervening loads.
///
/// One example where this can occur is in response to payload sinking: we're
/// able to remove the load but we're left with a dead store that DSE doesn't
/// know is actually dead.
///
/// We may be able to remove this pass once we migrate to LLVM 12 which has
/// an enhanced DSE pass (it uses MemorySSA by default). We may be able to
/// mark the regions with a lifetime.end at release points.
///
//===----------------------------------------------------------------------===//

#include "Compiler/IGCPassSupport.h"
#include "Compiler/CodeGenPublic.h"
#include "MemRegionAnalysis.h"

#include "common/LLVMWarningsPush.hpp"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/IR/InstVisitor.h"
#include "common/LLVMWarningsPop.hpp"

using namespace llvm;
using namespace IGC;

class RayTracingMemDSEPass : public FunctionPass, public InstVisitor<RayTracingMemDSEPass>
{
public:
    RayTracingMemDSEPass() : FunctionPass(ID)
    {
        initializeRayTracingMemDSEPassPass(*PassRegistry::getPassRegistry());
    }

    void getAnalysisUsage(AnalysisUsage& AU) const override
    {
        AU.setPreservesCFG();
        AU.addRequired<CodeGenContextWrapper>();
        AU.addRequired<AAResultsWrapperPass>();
        AU.addRequired<MemorySSAWrapperPass>();
        AU.addPreserved<MemorySSAWrapperPass>();
    }

    bool runOnFunction(Function& M) override;
    StringRef getPassName() const override
    {
        return "RayTracingMemDSEPass";
    }

    void visitStoreInst(StoreInst& SI);

    static char ID;
private:
    bool isDeadStore(const StoreInst& SI) const;
    void eraseStore(StoreInst& SI);
private:
    BatchAAResults* BAA = nullptr;
    MemorySSA* MSSA = nullptr;
    CodeGenContext* Ctx = nullptr;
    bool Changed = false;
};

char RayTracingMemDSEPass::ID = 0;
// Register pass to igc-opt
#define PASS_FLAG2 "rt-mem-dse-pass"
#define PASS_DESCRIPTION2 "StackID Release kills stores to RT Memory"
#define PASS_CFG_ONLY2 false
#define PASS_ANALYSIS2 false
IGC_INITIALIZE_PASS_BEGIN(RayTracingMemDSEPass, PASS_FLAG2, PASS_DESCRIPTION2, PASS_CFG_ONLY2, PASS_ANALYSIS2)
IGC_INITIALIZE_PASS_DEPENDENCY(CodeGenContextWrapper)
IGC_INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
IGC_INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
IGC_INITIALIZE_PASS_END(RayTracingMemDSEPass, PASS_FLAG2, PASS_DESCRIPTION2, PASS_CFG_ONLY2, PASS_ANALYSIS2)

void RayTracingMemDSEPass::eraseStore(StoreInst& SI)
{
    MemorySSAUpdater Updater{ MSSA };
    if (auto* MA = MSSA->getMemoryAccess(&SI))
        Updater.removeMemoryAccess(MA);

    SI.eraseFromParent();
}

bool RayTracingMemDSEPass::isDeadStore(const StoreInst& SI) const
{
    auto* Def = MSSA->getMemoryAccess(&SI);
    if (!Def)
        return false;

    // This is inspired by isWriteAtEndOfFunction() in DeadStoreElimination

    SmallVector<MemoryAccess*, 4> WorkList;
    SmallPtrSet<MemoryAccess*, 8> Visited;
    auto PushMemUses = [&](MemoryAccess* Acc)
    {
        if (!Visited.insert(Acc).second)
            return;
        for (auto *U : Acc->users())
            WorkList.push_back(cast<MemoryAccess>(U));
    };
    PushMemUses(Def);

    for (unsigned i = 0; i < WorkList.size(); i++)
    {
        MemoryAccess* UseAccess = WorkList[i];
        if (isa<MemoryPhi>(UseAccess) || isa<MemoryUse>(UseAccess))
            return false;

        auto* UseInst = cast<MemoryDef>(UseAccess)->getMemoryInst();
        if (isa<StackIDReleaseIntrinsic>(UseInst))
            continue;
        if (isRefSet(BAA->getModRefInfo(UseInst, MemoryLocation::get(&SI))))
            return false;

        PushMemUses(UseAccess);
    }
    return true;
}

void RayTracingMemDSEPass::visitStoreInst(StoreInst& SI)
{
    auto Region = getRTRegion(SI.getPointerOperand(), *Ctx->getModuleMetaData());
    if (!Region)
        return;
    if (*Region != RTMemRegion::SWStack && *Region != RTMemRegion::SWHotZone)
        return;

    if (isDeadStore(SI))
    {
        eraseStore(SI);
        Changed = true;
    }
}

bool RayTracingMemDSEPass::runOnFunction(Function& F)
{
    Ctx = getAnalysis<CodeGenContextWrapper>().getCodeGenContext();
    MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA();
    auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
    BatchAAResults BatchAA{ AA };
    BAA = &BatchAA;
    Changed = false;

    visit(F);

    return Changed;
}

namespace IGC
{

Pass* createRayTracingMemDSEPass(void)
{
    return new RayTracingMemDSEPass();
}

} // namespace IGC