Skip to content

Commit 437b3f9

Browse files
mnaczkgfxbot
authored andcommitted
Add pass which removes unnecessary operations on local memory
Change-Id: Ib546b804ce389af29d75c14719077cddbc4142f3
1 parent 1217df9 commit 437b3f9

File tree

4 files changed

+187
-0
lines changed

4 files changed

+187
-0
lines changed

IGC/Compiler/CISACodeGen/ShaderCodeGen.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,7 @@ void OptimizeIR(CodeGenContext* pContext)
13761376
}
13771377
mpm.add(llvm::createCFGSimplificationPass());
13781378
mpm.add(llvm::createEarlyCSEPass());
1379+
13791380
if(pContext->m_instrTypes.hasNonPrimitiveAlloca)
13801381
{
13811382
mpm.add(createSROAPass());
@@ -1461,6 +1462,9 @@ void OptimizeIR(CodeGenContext* pContext)
14611462
mpm.add(createSROAPass());
14621463
}
14631464
}
1465+
#if LLVM_VERSION_MAJOR >= 7
1466+
mpm.add(new TrivialLocalMemoryOpsElimination());
1467+
#endif
14641468
mpm.add(createGenSimplificationPass());
14651469

14661470
if (pContext->m_instrTypes.hasLoadStore)

IGC/Compiler/CustomSafeOptPass.cpp

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,146 @@ void CustomSafeOptPass::visitExtractElementInst(ExtractElementInst &I)
924924
}
925925
}
926926

927+
#if LLVM_VERSION_MAJOR >= 7
928+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
929+
// This pass removes dead local memory loads and stores. If we remove all such loads and stores, we also
930+
// remove all local memory fences together with barriers that follow.
931+
//
932+
IGC_INITIALIZE_PASS_BEGIN(TrivialLocalMemoryOpsElimination, "TrivialLocalMemoryOpsElimination", "TrivialLocalMemoryOpsElimination", false, false)
933+
IGC_INITIALIZE_PASS_END(TrivialLocalMemoryOpsElimination, "TrivialLocalMemoryOpsElimination", "TrivialLocalMemoryOpsElimination", false, false)
934+
935+
char TrivialLocalMemoryOpsElimination::ID = 0;
936+
937+
TrivialLocalMemoryOpsElimination::TrivialLocalMemoryOpsElimination() : FunctionPass(ID)
938+
{
939+
initializeTrivialLocalMemoryOpsEliminationPass(*PassRegistry::getPassRegistry());
940+
}
941+
942+
943+
944+
bool TrivialLocalMemoryOpsElimination::runOnFunction(Function &F)
945+
{
946+
bool change = false;
947+
visit(F);
948+
if (!abortPass && (m_LocalLoadsToRemove.empty() || m_LocalStoresToRemove.empty()))
949+
{
950+
for (StoreInst *Inst : m_LocalStoresToRemove)
951+
{
952+
Inst->eraseFromParent();
953+
change = true;
954+
}
955+
956+
for (LoadInst *Inst : m_LocalLoadsToRemove)
957+
{
958+
if (Inst->use_empty())
959+
{
960+
Inst->eraseFromParent();
961+
change = true;
962+
}
963+
}
964+
965+
for (CallInst *Inst : m_LocalFencesBariersToRemove)
966+
{
967+
Inst->eraseFromParent();
968+
change = true;
969+
}
970+
}
971+
972+
return change;
973+
}
974+
975+
/*
976+
OCL instruction barrier(CLK_LOCAL_MEM_FENCE); is translate to two instructions
977+
call void @llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
978+
call void @llvm.genx.GenISA.threadgroupbarrier()
979+
980+
if we remove call void @llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
981+
we must remove next instruction if it is call void @llvm.genx.GenISA.threadgroupbarrier()
982+
*/
983+
void TrivialLocalMemoryOpsElimination::findNextThreadGroupBarrierInst(Instruction &I)
984+
{
985+
auto nextInst = I.getNextNonDebugInstruction();
986+
if (isa<GenIntrinsicInst>(nextInst))
987+
{
988+
GenIntrinsicInst *II = dyn_cast<GenIntrinsicInst>(nextInst);
989+
if (II->getIntrinsicID() == GenISAIntrinsic::GenISA_threadgroupbarrier)
990+
{
991+
m_LocalFencesBariersToRemove.push_back(dyn_cast<CallInst>(nextInst));
992+
}
993+
}
994+
}
995+
996+
void TrivialLocalMemoryOpsElimination::visitLoadInst(LoadInst &I)
997+
{
998+
if (I.getPointerAddressSpace() == ADDRESS_SPACE_LOCAL)
999+
{
1000+
m_LocalLoadsToRemove.push_back(&I);
1001+
}
1002+
}
1003+
1004+
void TrivialLocalMemoryOpsElimination::visitStoreInst(StoreInst &I)
1005+
{
1006+
if (I.getPointerAddressSpace() == ADDRESS_SPACE_LOCAL)
1007+
{
1008+
m_LocalStoresToRemove.push_back(&I);
1009+
}
1010+
}
1011+
1012+
bool TrivialLocalMemoryOpsElimination::isLocalBarrier(CallInst &I)
1013+
{
1014+
//check arguments in call void @llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true) if match to
1015+
// (i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true) it is local barrier
1016+
std::vector<bool> argumentsOfMemoryBarrier;
1017+
1018+
for (auto arg = I.arg_begin(); arg != I.arg_end(); ++arg)
1019+
{
1020+
ConstantInt* ci = dyn_cast<ConstantInt>(arg);
1021+
argumentsOfMemoryBarrier.push_back(ci->getValue().getBoolValue());
1022+
}
1023+
1024+
return argumentsOfMemoryBarrier == m_argumentsOfLocalMemoryBarrier;
1025+
}
1026+
1027+
// If any call instruction use pointer to local memory abort pass execution
1028+
void TrivialLocalMemoryOpsElimination::anyCallInstUseLocalMemory(CallInst &I)
1029+
{
1030+
Function* fn = I.getCalledFunction();
1031+
1032+
if (fn != NULL)
1033+
{
1034+
for (auto arg = fn->arg_begin(); arg != fn->arg_end(); ++arg)
1035+
{
1036+
if (arg->getType()->isPointerTy())
1037+
{
1038+
if (arg->getType()->getPointerAddressSpace() == ADDRESS_SPACE_LOCAL || arg->getType()->getPointerAddressSpace() == ADDRESS_SPACE_GENERIC) abortPass = true;
1039+
}
1040+
}
1041+
}
1042+
}
1043+
1044+
void TrivialLocalMemoryOpsElimination::visitCallInst(CallInst &I)
1045+
{
1046+
// detect only: llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
1047+
// (note: the first and last arguments are true)
1048+
// and add them with immediately following barriers to m_LocalFencesBariersToRemove
1049+
anyCallInstUseLocalMemory(I);
1050+
1051+
if (isa<GenIntrinsicInst>(I))
1052+
{
1053+
GenIntrinsicInst *II = dyn_cast<GenIntrinsicInst>(&I);
1054+
if (II->getIntrinsicID() == GenISAIntrinsic::GenISA_memoryfence)
1055+
{
1056+
if (isLocalBarrier(I))
1057+
{
1058+
m_LocalFencesBariersToRemove.push_back(&I);
1059+
findNextThreadGroupBarrierInst(I);
1060+
}
1061+
}
1062+
}
1063+
1064+
}
1065+
#endif
1066+
9271067
// Register pass to igc-opt
9281068
#define PASS_FLAG2 "igc-gen-specific-pattern"
9291069
#define PASS_DESCRIPTION2 "LastPatternMatch Pass"
@@ -3471,6 +3611,8 @@ bool FlattenSmallSwitch::runOnFunction(Function &F)
34713611
IGC_INITIALIZE_PASS_BEGIN(FlattenSmallSwitch, "flattenSmallSwitch", "flattenSmallSwitch", false, false)
34723612
IGC_INITIALIZE_PASS_END(FlattenSmallSwitch, "flattenSmallSwitch", "flattenSmallSwitch", false, false)
34733613

3614+
3615+
34743616
////////////////////////////////////////////////////////////////////////
34753617
// LogicalAndToBranch trying to find logical AND like below:
34763618
// res = simpleCond0 && complexCond1

IGC/Compiler/CustomSafeOptPass.hpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3131
#include <llvm/IR/InstVisitor.h>
3232
#include <llvm/Analysis/TargetLibraryInfo.h>
3333
#include <llvm/Analysis/LoopPass.h>
34+
#include <llvm/IR/Instructions.h>
3435
#include "common/LLVMWarningsPop.hpp"
3536

37+
3638
namespace llvm
3739
{
3840
// Forward declare:
@@ -97,6 +99,40 @@ namespace IGC
9799
private:
98100
bool psHasSideEffect;
99101
};
102+
#if LLVM_VERSION_MAJOR >= 7
103+
class TrivialLocalMemoryOpsElimination : public llvm::FunctionPass, public llvm::InstVisitor<TrivialLocalMemoryOpsElimination>
104+
{
105+
public:
106+
static char ID;
107+
108+
TrivialLocalMemoryOpsElimination();
109+
110+
~TrivialLocalMemoryOpsElimination() {}
111+
112+
virtual bool runOnFunction(llvm::Function &F) override;
113+
114+
virtual llvm::StringRef getPassName() const override
115+
{
116+
return "TrivialLocalMemoryOpsElimination";
117+
}
118+
119+
void visitLoadInst(llvm::LoadInst &I);
120+
void visitStoreInst(llvm::StoreInst &I);
121+
void visitCallInst(llvm::CallInst &I);
122+
bool isLocalBarrier(llvm::CallInst &I);
123+
void findNextThreadGroupBarrierInst(llvm::Instruction &I);
124+
void anyCallInstUseLocalMemory(llvm::CallInst &I);
125+
126+
private:
127+
llvm::SmallVector<llvm::LoadInst*, 16> m_LocalLoadsToRemove;
128+
llvm::SmallVector<llvm::StoreInst*, 16> m_LocalStoresToRemove;
129+
llvm::SmallVector<llvm::CallInst*, 16> m_LocalFencesBariersToRemove;
130+
131+
bool abortPass = false;
132+
const std::vector<bool> m_argumentsOfLocalMemoryBarrier{ true, false, false, false, false, false, true };
133+
};
134+
135+
#endif
100136

101137
class GenSpecificPattern : public llvm::FunctionPass, public llvm::InstVisitor<GenSpecificPattern>
102138
{
@@ -180,5 +216,7 @@ namespace IGC
180216
llvm::FunctionPass *createBlendToDiscardPass();
181217
llvm::FunctionPass *createMarkReadOnlyLoadPass();
182218
llvm::FunctionPass *createLogicalAndToBranchPass();
219+
220+
183221

184222
} // namespace IGC

IGC/Compiler/InitializePasses.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ void initializeRegisterEstimatorPass(llvm::PassRegistry&);
132132
void initializeVariableReuseAnalysisPass(llvm::PassRegistry&);
133133
void initializeTransformBlocksPass(llvm::PassRegistry&);
134134
void initializeTranslationTablePass(llvm::PassRegistry&);
135+
#if LLVM_VERSION_MAJOR >= 7
136+
void initializeTrivialLocalMemoryOpsEliminationPass(llvm::PassRegistry&);
137+
#endif
135138
void initializeSLMConstPropPass(llvm::PassRegistry&);
136139
void initializeBlendToDiscardPass(llvm::PassRegistry&);
137140
void initializeCheckInstrTypesPass(llvm::PassRegistry&);

0 commit comments

Comments
 (0)