Skip to content

Commit d2c9fb2

Browse files
aparshin-inteligcbot
authored andcommitted
added verifier to FunctionGroupAnalysis
Current FGA implementation may produce erroneous results. Added verification and debugging facilities to detect errors.
1 parent 1f63e32 commit d2c9fb2

File tree

3 files changed

+107
-25
lines changed

3 files changed

+107
-25
lines changed

IGC/VectorCompiler/lib/GenXCodeGen/FunctionGroup.cpp

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,55 @@ SPDX-License-Identifier: MIT
3131
#include "llvm/Support/raw_ostream.h"
3232
#include "llvm/Transforms/Utils/Cloning.h"
3333
#include "llvm/Transforms/Utils/ValueMapper.h"
34-
using namespace llvm;
34+
35+
#include "GenXUtil.h"
3536

3637
#include "llvmWrapper/IR/LegacyPassManagers.h"
3738
#include "llvmWrapper/IR/PassTimingInfo.h"
38-
#include "Probe/Assertion.h"
3939

40+
#include "Probe/Assertion.h"
4041

4142
#define DEBUG_TYPE "functiongroup-passmgr"
4243

44+
using namespace llvm;
45+
46+
bool FunctionGroup::verify() const {
47+
for (auto I = Functions.begin(), E = Functions.end(); I != E; ++I) {
48+
Function *F = &(**I);
49+
for (auto *U : F->users()) {
50+
auto *CI = genx::checkFunctionCall(U, F);
51+
if (!CI)
52+
continue;
53+
54+
// Note: it is expected that all users of any function from
55+
// Functions array belong to the same FG
56+
Function *Caller = CI->getFunction();
57+
auto *OtherGroup = FGA->getAnyGroup(Caller);
58+
IGC_ASSERT_MESSAGE(OtherGroup == this,
59+
"inconsisten function group detected!");
60+
if (OtherGroup != this)
61+
return false;
62+
}
63+
}
64+
return true;
65+
}
66+
67+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
68+
void FunctionGroup::print(raw_ostream &OS) const {
69+
OS << "{{{" << getName() << "}}}\n";
70+
for (const Function *F : Functions) {
71+
OS << " " << F->getName() << "\n";
72+
}
73+
74+
for (const auto &EnItem : enumerate(Subgroups)) {
75+
OS << "--SGR[" << EnItem.index() << "]: ";
76+
OS << "<" << EnItem.value()->getHead()->getName() << ">]\n";
77+
}
78+
}
79+
80+
void FunctionGroup::dump() const { print(dbgs()); }
81+
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
82+
4383
/***********************************************************************
4484
* FunctionGroupAnalysis implementation
4585
*/
@@ -57,13 +97,9 @@ void FunctionGroupAnalysis::clear() {
5797
for (auto T : TypesToProcess)
5898
GroupMap[T].clear();
5999

60-
for (auto i = begin(), e = end(); i != e; ++i)
61-
delete *i;
62-
for (auto i = NonMainGroups.begin(), e = NonMainGroups.end(); i != e; ++i)
63-
delete *i;
64-
65100
Groups.clear();
66101
NonMainGroups.clear();
102+
Visited.clear();
67103
M = nullptr;
68104
}
69105

@@ -140,11 +176,12 @@ void FunctionGroupAnalysis::addToFunctionGroup(FunctionGroup *FG, Function *F,
140176
// createFunctionGroup : create new FunctionGroup for which F is the head
141177
FunctionGroup *FunctionGroupAnalysis::createFunctionGroup(Function *F,
142178
FGType Type) {
143-
auto FG = new FunctionGroup(this);
179+
auto *FG = new FunctionGroup(this);
180+
auto FGOwner = std::unique_ptr<FunctionGroup>(FG);
144181
if (Type == FGType::GROUP)
145-
Groups.push_back(FG);
182+
Groups.push_back(std::move(FGOwner));
146183
else
147-
NonMainGroups.push_back(FG);
184+
NonMainGroups.push_back(std::move(FGOwner));
148185
addToFunctionGroup(FG, F, Type);
149186
return FG;
150187
}
@@ -211,7 +248,7 @@ bool FunctionGroupAnalysis::buildGroup(CallGraph &Callees, Function *F,
211248
}
212249
}
213250
} else if (!Visited.count(F)) {
214-
Visited[F] = true;
251+
Visited.insert(F);
215252
// group is created either on a function with a corresponding attribute
216253
// or on a root of a whole function tree that is kernel (genx_main)
217254
if (F->hasFnAttribute(TypeToAttr(Type)) ||
@@ -240,6 +277,30 @@ bool FunctionGroupAnalysis::buildGroup(CallGraph &Callees, Function *F,
240277
return result;
241278
}
242279

280+
bool FunctionGroupAnalysis::verify() const {
281+
return std::all_of(Groups.begin(), Groups.end(),
282+
[](const auto &GR) { return GR->verify(); });
283+
}
284+
285+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
286+
void FunctionGroupAnalysis::print(raw_ostream &OS) const {
287+
OS << "Number of Groups = " << Groups.size() << "\n";
288+
for (const auto &X : enumerate(Groups)) {
289+
OS << "GR[" << X.index() << "] = <\n";
290+
X.value()->print(OS);
291+
OS << ">\n";
292+
}
293+
OS << "Number of SubGroups = " << NonMainGroups.size() << "\n";
294+
for (const auto &X : enumerate(NonMainGroups)) {
295+
OS << "SGR[" << X.index() << "] = <\n";
296+
X.value()->print(OS);
297+
OS << ">\n";
298+
}
299+
}
300+
301+
void FunctionGroupAnalysis::dump() const { print(dbgs()); }
302+
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
303+
243304
//===----------------------------------------------------------------------===//
244305
// FGPassManager
245306
//

IGC/VectorCompiler/lib/GenXCodeGen/FunctionGroup.h

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,20 @@ SPDX-License-Identifier: MIT
2424
/// is used. It could be moved somewhere more general.
2525
///
2626
//===----------------------------------------------------------------------===//
27-
#ifndef FUNCTIONGROUP_H
28-
#define FUNCTIONGROUP_H
27+
#ifndef LIB_GENXCODEGEN_FUNCTIONGROUP_H
28+
#define LIB_GENXCODEGEN_FUNCTIONGROUP_H
2929

3030
#include "vc/GenXOpts/Utils/KernelInfo.h"
31-
#include "llvm/ADT/SetVector.h"
32-
#include "llvm/ADT/SmallVector.h"
33-
#include "llvm/IR/Module.h"
34-
#include "llvm/IR/ValueHandle.h"
35-
#include "llvm/Pass.h"
31+
32+
#include <llvm/ADT/SetVector.h>
33+
#include <llvm/ADT/SmallVector.h>
34+
#include <llvm/IR/Module.h>
35+
#include <llvm/IR/ValueHandle.h>
36+
#include <llvm/Pass.h>
3637

3738
#include <list>
39+
#include <unordered_set>
40+
3841
#include "Probe/Assertion.h"
3942

4043
namespace llvm {
@@ -70,7 +73,7 @@ class FunctionGroup {
7073

7174
public:
7275
FunctionGroup(FunctionGroupAnalysis *FGA) : FGA(FGA) {}
73-
FunctionGroupAnalysis *getParent() { return FGA; }
76+
FunctionGroupAnalysis *getParent() const { return FGA; }
7477
// push_back : push a Function into the group. The first time this is done,
7578
// the Function is the head Function.
7679
void push_back(Function *F) { Functions.push_back(AssertingVH<Function>(F)); }
@@ -97,7 +100,7 @@ class FunctionGroup {
97100
IGC_ASSERT(size());
98101
return *begin();
99102
}
100-
StringRef getName() { return getHead()->getName(); }
103+
StringRef getName() const { return getHead()->getName(); }
101104
LLVMContext &getContext() { return getHead()->getContext(); }
102105
Module *getModule() { return getHead()->getParent(); }
103106
void addSubgroup(FunctionGroup *FG) {
@@ -119,6 +122,13 @@ class FunctionGroup {
119122
iterator_range<const_subgroup_iterator> subgroups() const {
120123
return make_range(begin_subgroup(), end_subgroup());
121124
}
125+
126+
bool verify() const;
127+
128+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
129+
void print(raw_ostream &OS) const;
130+
void dump() const;
131+
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
122132
};
123133

124134
//----------------------------------------------------------------------
@@ -140,12 +150,12 @@ class FunctionGroupAnalysis : public ModulePass {
140150

141151
private:
142152
Module *M = nullptr;
143-
SmallVector<FunctionGroup *, 8> Groups;
153+
SmallVector<std::unique_ptr<FunctionGroup>, 8> Groups;
144154

145155
// storage for FunctionGroups that aren't of type GROUP,
146156
// i.e. not necessarily GENX_MAIN headed
147157
// TODO: mb increase 8 as there can be many stack funcs hence may subgroups
148-
SmallVector<FunctionGroup *, 8> NonMainGroups;
158+
SmallVector<std::unique_ptr<FunctionGroup>, 8> NonMainGroups;
149159

150160
class FGMap {
151161
using ElementType = std::map<const Function *, FunctionGroup *>;
@@ -164,7 +174,9 @@ class FunctionGroupAnalysis : public ModulePass {
164174
};
165175

166176
FGMap GroupMap;
167-
std::map<Function *, bool> Visited;
177+
// TODO: "Visited" should not be part of FGA state - it should be an external
178+
// entity
179+
std::unordered_set<Function *> Visited;
168180
using CallGraph = std::map<Function *, std::list<Function *>>;
169181

170182
public:
@@ -244,7 +256,12 @@ class FunctionGroupAnalysis : public ModulePass {
244256
bool buildGroup(CallGraph &callees, Function *F,
245257
FunctionGroup *curGr = nullptr, FGType Type = FGType::GROUP);
246258

247-
void clearVisited() { Visited.clear(); }
259+
bool verify() const;
260+
261+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
262+
void print(raw_ostream &OS) const;
263+
void dump() const;
264+
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
248265
};
249266

250267
ModulePass *createFunctionGroupAnalysisPass();
@@ -381,6 +398,9 @@ class LoopInfoGroupWrapperPass : public FunctionGroupPass {
381398

382399
void print(raw_ostream &OS, const Module *M = nullptr) const override;
383400
};
401+
384402
void initializeLoopInfoGroupWrapperPassPass(PassRegistry &);
403+
385404
} // end namespace llvm
386-
#endif // ndef FUNCTIONGROUP_H
405+
406+
#endif // LIB_GENXCODEGEN_FUNCTIONGROUP_H

IGC/VectorCompiler/lib/GenXCodeGen/GenXModule.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ bool GenXModule::runOnModule(Module &M) {
159159
}
160160
}
161161

162+
IGC_ASSERT(FGA->verify());
162163
return ModuleModified;
163164
}
164165
void GenXModule::updateVisaMapping(const Function *K, const Instruction *Inst,

0 commit comments

Comments
 (0)