Skip to content

Commit 061f114

Browse files
Krebrov001igcbot
authored andcommitted
Added extra functionality to InlineLocalsResolution for identification and removal of unused global variables and all their successive recursive user nodes in the def-use tree.
1 parent 765ac0f commit 061f114

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

IGC/Compiler/Optimizer/OpenCLPasses/LocalBuffers/InlineLocalsResolution.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ IN THE SOFTWARE.
3535
#include "common/LLVMWarningsPop.hpp"
3636
#include "Probe/Assertion.h"
3737

38+
#include <unordered_set>
39+
3840
using namespace llvm;
3941
using namespace IGC;
4042
using namespace IGC::IGCMD;
@@ -112,6 +114,8 @@ bool InlineLocalsResolution::runOnModule(Module& M)
112114
{
113115
MetaDataUtils* pMdUtils = getAnalysis<MetaDataUtilsWrapper>().getMetaDataUtils();
114116
ModuleMetaData* modMD = getAnalysis<MetaDataUtilsWrapper>().getModuleMetaData();
117+
if (!modMD->compOpt.OptDisable)
118+
filterGlobals(M);
115119
// Compute the offset of each inline local in the kernel,
116120
// and their total size.
117121
std::map<Function*, unsigned int> sizeMap;
@@ -214,6 +218,100 @@ bool InlineLocalsResolution::runOnModule(Module& M)
214218
return true;
215219
}
216220

221+
void InlineLocalsResolution::filterGlobals(Module& M)
222+
{
223+
// This data structure saves all the unused nodes,
224+
// including the global variable definition itself, as well as all successive recursive user nodes,
225+
// in all the def-use trees corresponding to all the global variables in the entire Module.
226+
std::unordered_set<Value*> unusedNodes_forModule;
227+
228+
// let's loop all global variables
229+
for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
230+
{
231+
// We only care about global variables, not other globals.
232+
GlobalVariable* globalVar = dyn_cast<GlobalVariable>(&*I);
233+
if (!globalVar)
234+
{
235+
continue;
236+
}
237+
238+
PointerType* ptrType = cast<PointerType>(globalVar->getType());
239+
// We only care about local address space here.
240+
if (ptrType->getAddressSpace() != ADDRESS_SPACE_LOCAL)
241+
{
242+
continue;
243+
}
244+
245+
// If the globalVar is determined to be unused,
246+
// this data structure saves the globalVar,
247+
// as well as all successive recursive user nodes in that def-use tree.
248+
std::unordered_set<Value*> unusedNodes_forOne;
249+
if (unusedGlobal(globalVar, unusedNodes_forOne))
250+
unusedNodes_forModule.insert(unusedNodes_forOne.begin(), unusedNodes_forOne.end());
251+
}
252+
253+
// We only remove all the unused nodes for this Module,
254+
// after we are done processing all the global variables for the entire Module,
255+
// to prevent iterators becoming invalidated when elements get removed from the ilist.
256+
for (auto& element : unusedNodes_forModule) {
257+
// for all unused Values,
258+
// replace all uses with undefs
259+
// delete the values
260+
if (Instruction* node = dyn_cast<Instruction>(element)) {
261+
Type* Ty = node->getType();
262+
if (!Ty->isVoidTy())
263+
node->replaceAllUsesWith(UndefValue::get(Ty));
264+
node->eraseFromParent();
265+
}
266+
else if (GlobalVariable* node = dyn_cast<GlobalVariable>(element)) {
267+
Type* Ty = node->getType();
268+
if (!Ty->isVoidTy())
269+
node->replaceAllUsesWith(UndefValue::get(Ty));
270+
node->eraseFromParent();
271+
}
272+
// All other types of nodes are ignored.
273+
}
274+
}
275+
276+
bool InlineLocalsResolution::unusedGlobal(Value* V, std::unordered_set<Value*>& unusedNodes)
277+
{
278+
for (Value::user_iterator U = V->user_begin(), UE = V->user_end(); U != UE; ++U)
279+
{
280+
if (GlobalVariable* globalVar = dyn_cast<GlobalVariable>(*U)) {
281+
if (!unusedGlobal(*U, unusedNodes))
282+
return false;
283+
}
284+
else if (GetElementPtrInst* gep = dyn_cast<GetElementPtrInst>(*U)) {
285+
if (!unusedGlobal(*U, unusedNodes))
286+
return false;
287+
}
288+
else if (BitCastInst* bitcast = dyn_cast<BitCastInst>(*U)) {
289+
if (!unusedGlobal(*U, unusedNodes))
290+
return false;
291+
}
292+
else if (StoreInst* store = dyn_cast<StoreInst>(*U)) {
293+
if (store->isUnordered()) {
294+
if (store->getPointerOperand() == V) {
295+
if (!unusedGlobal(*U, unusedNodes))
296+
return false;
297+
}
298+
else if (store->getValueOperand() == V) {
299+
return false;
300+
}
301+
}
302+
else {
303+
return false;
304+
}
305+
}
306+
else { // some other instruction
307+
return false;
308+
}
309+
}
310+
// add an unused node to the data structure
311+
unusedNodes.insert(V);
312+
return true;
313+
}
314+
217315
void InlineLocalsResolution::collectInfoOnSharedLocalMem(Module& M)
218316
{
219317

IGC/Compiler/Optimizer/OpenCLPasses/LocalBuffers/InlineLocalsResolution.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ IN THE SOFTWARE.
3737

3838
#include <map>
3939
#include <set>
40+
#include <unordered_set>
4041

4142
namespace IGC
4243
{
@@ -83,6 +84,8 @@ namespace IGC
8384

8485
protected:
8586

87+
void filterGlobals(llvm::Module&);
88+
bool unusedGlobal(llvm::Value* V, std::unordered_set<llvm::Value*>& unusedNodes);
8689
void collectInfoOnSharedLocalMem(llvm::Module&);
8790
void computeOffsetList(llvm::Module&, std::map<llvm::Function*, unsigned int>&);
8891
void traveseCGN(llvm::CallGraphNode&);

0 commit comments

Comments
 (0)