File: LiveVars.hpp

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 (256 lines) | stat: -rw-r--r-- 10,520 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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*========================== begin_copyright_notice ============================

Copyright (C) 2017-2021 Intel Corporation

SPDX-License-Identifier: MIT

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

/*========================== begin_copyright_notice ============================

This file is distributed under the University of Illinois Open Source License.
See LICENSE.TXT for details.

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

//===------------ LiveVars.h - Live Variable Analysis -----------*- C++ -*-===//
//
// Intel extension to LLVM core
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveVariables analysis pass. It originates from
// the same function in llvm3.0/codegen, however works on llvm-ir instead of
// the code-gen-level ir.
//
// This class computes live variables using a sparse implementation based on
// the llvm-ir SSA form.  This class uses the dominance properties of SSA form
// to efficiently compute live variables for virtual registers. Also Note that
// there is no physical register at llvm-ir level.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_IEXT_LIVEVARS_H
#define LLVM_IEXT_LIVEVARS_H

#include "Compiler/CISACodeGen/WIAnalysis.hpp"

#include "common/LLVMWarningsPush.hpp"
#include <llvm/Pass.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instruction.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/CFG.h>
#include <llvm/ADT/DenseMap.h>
#include <llvm/ADT/SmallSet.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/Support/Allocator.h>
#include "common/LLVMWarningsPop.hpp"

#include <map>

namespace IGC
{

    class LiveVars {
    public:
        // forward declaration
        struct LVInfo;

        typedef llvm::DenseMap<llvm::Value*, LVInfo*>  LVInfoMap;
        typedef LVInfoMap::iterator        iterator;
        typedef LVInfoMap::const_iterator  const_iterator;

        LiveVars() {}
        ~LiveVars();

        /// LVInfo - This represents the regions where a virtual register is live in
        /// the program.  We represent this with three different pieces of
        /// information: the set of blocks in which the instruction is live
        /// throughout, the set of blocks in which the instruction is actually used,
        /// and the set of non-phi instructions that are the last users of the value.
        ///
        /// In the common case where a value is defined and killed in the same block,
        /// There is one killing instruction, and AliveBlocks is empty.
        ///
        /// Otherwise, the value is live out of the block.  If the value is live
        /// throughout any blocks, these blocks are listed in AliveBlocks.  Blocks
        /// where the liveness range ends are not included in AliveBlocks, instead
        /// being captured by the Kills set.  In these blocks, the value is live into
        /// the block (unless the value is defined and killed in the same block) and
        /// lives until the specified instruction.  Note that there cannot ever be a
        /// value whose Kills set contains two instructions from the same basic block.
        ///
        /// PHI nodes complicate things a bit.  If a PHI node is the last user of a
        /// value in one of its predecessor blocks, it is not listed in the kills set,
        /// but does include the predecessor block in the AliveBlocks set (unless that
        /// block also defines the value).  This leads to the (perfectly sensical)
        /// situation where a value is defined in a block, and the last use is a phi
        /// node in the successor.  In this case, AliveBlocks is empty (the value is
        /// not live across any  blocks) and Kills is empty (phi nodes are not
        /// included). This is sensical because the value must be live to the end of
        /// the block, but is not live in any successor blocks.
        struct LVInfo {
            /// AliveBlocks - Set of blocks in which this value is alive completely
            /// through.
            llvm::SmallPtrSet<llvm::BasicBlock*, 16> AliveBlocks;
            ///std::set<llvm::BasicBlock*> AliveBlocks;

            /// NumUses - Number of uses of this register across the entire function.
            ///
            unsigned NumUses;

            /// Kills - List of llvm::Instruction's which are the last use of this
            /// virtual register (kill it) in their basic block.
            ///
            std::vector<llvm::Instruction*> Kills;

            bool uniform;

            LVInfo() : NumUses(0), uniform(false) {}

            /// removeKill - Delete a kill corresponding to the specified
            /// instruction. Returns true if there was a kill
            /// corresponding to this instruction, false otherwise.
            bool removeKill(llvm::Instruction* MI) {
                std::vector<llvm::Instruction*>::iterator
                    I = std::find(Kills.begin(), Kills.end(), MI);
                if (I == Kills.end())
                    return false;
                Kills.erase(I);
                return true;
            }

            /// findKill - Find a kill instruction in basic block. Return NULL if none is found.
            llvm::Instruction* findKill(const llvm::BasicBlock* MBB) const;

            /// isLiveIn - Is Reg live in to MBB? This means that Reg is live through
            /// MBB, or it is killed in BB. If Reg is only used by PHI instructions in
            /// MBB, it is not considered live in.
            bool isLiveIn(const llvm::BasicBlock& MBB, llvm::Value* LV);

            void print(llvm::raw_ostream& OS) const;
        }; // end of LVInfo

    private:
        /// VirtRegInfo - This list is a mapping from a llvm::value to
        /// its liveness information.
        ///
        LVInfoMap VirtRegInfo;

    private:   // Intermediate data structures
        llvm::Function* MF;
        WIAnalysis* WIA;
        llvm::SpecificBumpPtrAllocator<LVInfo> Allocator;

        // For each basic-block, we have a vector of phi-uses if there are phi-insts
        // in a successor-block
        llvm::DenseMap<llvm::BasicBlock*, llvm::SmallVector<llvm::Value*, 4>> PHIVarInfo;

        // DistanceMap - Keep track the distance of an Instr from the start of the
        // current basic block.
        llvm::DenseMap<llvm::Instruction*, unsigned> DistanceMap;

        /// analyzePHINodes - Gather information about the PHI nodes in here. In
        /// particular, we want to map the variable information of a virtual
        /// register which is used in a PHI node. We map that to the BB the vreg
        /// is coming from.
        void analyzePHINodes(const llvm::Function& MF);

        /// Initialize DistanceMap
        void initDistance(llvm::Function& F);

    public:

        /// Can be called to release memory when the object won't be used anymore.
        void releaseMemory();

        /// Pre-allocate memory for llvm::DenseMap to avoid many small allocations
        void preAllocMemory(llvm::Function& F);

        /// getLVInfo - Return the LVInfo structure for the specified VIRTUAL
        /// register.
        LVInfo& getLVInfo(llvm::Value* LV);

        /// Get the relative location of an instruction within a basic block
        unsigned getDistance(const llvm::Instruction* MI) {
            return DistanceMap[(llvm::Instruction*)MI];
        }

        void MarkVirtRegAliveInBlock(LVInfo& VRInfo, llvm::BasicBlock* DefBlock,
            llvm::BasicBlock* BB);
        void MarkVirtRegAliveInBlock(LVInfo& VRInfo, llvm::BasicBlock* DefBlock,
            llvm::BasicBlock* BB,
            std::vector<llvm::BasicBlock*>& WorkList);

        // ScanBBTopDown: true if instructions of a BB is scanned top-down
        void HandleVirtRegUse(llvm::Value* LV, llvm::BasicBlock* MBB, llvm::Instruction* MI,
            bool ScanAllUses = false, bool ScanBBTopDown = false);
        void HandleVirtRegDef(llvm::Instruction* MI);

        void ComputeLiveness(llvm::Function*, WIAnalysis*);

        // Calculate liveness info for all live variables
        // (same as runOnMachineFunction() of llvm LiveVariables pass
        void Calculate(llvm::Function* F, WIAnalysis* WIA = nullptr);

        iterator begin() { return VirtRegInfo.begin(); }
        const_iterator begin() const { return VirtRegInfo.begin(); }
        iterator end() { return VirtRegInfo.end(); }
        const_iterator end() const { return VirtRegInfo.end(); }

        bool isLiveIn(llvm::Value* LV, const llvm::BasicBlock& MBB) {
            return getLVInfo(LV).isLiveIn(MBB, LV);
        }
        bool isLiveAt(llvm::Value* LV, llvm::Instruction* MI);

        /// isLiveOut - Determine if Reg is live out from MBB, when not considering
        /// PHI nodes. This means that Reg is either killed by a successor block or
        /// passed through one.
        bool isLiveOut(llvm::Value* LV, const llvm::BasicBlock& MBB);

        /// Merge LVInfo of "fromV" into V's LVInfo (ignore the def of "fromV")
        /// Note that this is used after LVInfo has been constructed already.
        void mergeUseFrom(llvm::Value* V, llvm::Value* fromV);

        /// If two values' live ranges overlap, return true.
        bool hasInterference(llvm::Value* V0, llvm::Value* V1);

        /// print - Convert to human readable form
        void print(llvm::raw_ostream& OS, const llvm::Module* = nullptr) const;

        /// dump - Dump the LVInfo to dbgs().
        void dump() const;

#if defined( _DEBUG )
        // for debugging
        llvm::DenseMap<llvm::BasicBlock*, int> BBIds;
        llvm::DenseMap<int, llvm::BasicBlock*> IdToBBs;

        void setupBBIds(llvm::Function* F);
        void dump(llvm::Function* F);
        void dump(int BBId);
#endif

    };

    /// \brief Analysis pass which computes a LiveVars.
    class LiveVarsAnalysis : public llvm::FunctionPass {
        LiveVars LV;

    public:
        static char ID;
        LiveVarsAnalysis();
        LiveVars& getLiveVars() { return LV; }
        const LiveVars& getLiveVars() const { return LV; }
        bool runOnFunction(llvm::Function& F) override;
        void getAnalysisUsage(llvm::AnalysisUsage& AU) const override {
            AU.addRequired<MetaDataUtilsWrapper>();
            AU.setPreservesAll();
        }
        void releaseMemory() override { LV.releaseMemory(); }
    };

} // End CISA namespace

#endif