Skip to content

Commit 793e799

Browse files
mnaczkgfxbot
authored andcommitted
Add pass which removes unnecessary operations on local memory.
Change-Id: I96dd63463fa1388ce01582f89287843c6bbefcd9
1 parent bcab9bd commit 793e799

File tree

4 files changed

+183
-0
lines changed

4 files changed

+183
-0
lines changed

IGC/Compiler/CISACodeGen/ShaderCodeGen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,9 @@ void OptimizeIR(CodeGenContext* pContext)
13801380
}
13811381
mpm.add(llvm::createCFGSimplificationPass());
13821382
mpm.add(llvm::createEarlyCSEPass());
1383+
#if LLVM_VERSION_MAJOR >= 7
1384+
mpm.add(new TrivialLocalMemoryOpsElimination());
1385+
#endif
13831386
if(pContext->m_instrTypes.hasNonPrimitiveAlloca)
13841387
{
13851388
mpm.add(createSROAPass());

IGC/Compiler/CustomSafeOptPass.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,143 @@ 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+
Inst->eraseFromParent();
959+
change = true;
960+
}
961+
962+
for (CallInst *Inst : m_LocalFencesBariersToRemove)
963+
{
964+
Inst->eraseFromParent();
965+
change = true;
966+
}
967+
}
968+
969+
return change;
970+
}
971+
972+
/*
973+
OCL instruction barrier(CLK_LOCAL_MEM_FENCE); is translate to two instructions
974+
call void @llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
975+
call void @llvm.genx.GenISA.threadgroupbarrier()
976+
977+
if we remove call void @llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
978+
we must remove next instruction if it is call void @llvm.genx.GenISA.threadgroupbarrier()
979+
*/
980+
void TrivialLocalMemoryOpsElimination::findNextThreadGroupBarrierInst(Instruction &I)
981+
{
982+
auto nextInst = I.getNextNonDebugInstruction();
983+
if (isa<GenIntrinsicInst>(nextInst))
984+
{
985+
GenIntrinsicInst *II = dyn_cast<GenIntrinsicInst>(nextInst);
986+
if (II->getIntrinsicID() == GenISAIntrinsic::GenISA_threadgroupbarrier)
987+
{
988+
m_LocalFencesBariersToRemove.push_back(dyn_cast<CallInst>(nextInst));
989+
}
990+
}
991+
}
992+
993+
void TrivialLocalMemoryOpsElimination::visitLoadInst(LoadInst &I)
994+
{
995+
if (I.getPointerAddressSpace() == ADDRESS_SPACE_LOCAL)
996+
{
997+
m_LocalLoadsToRemove.push_back(&I);
998+
}
999+
}
1000+
1001+
void TrivialLocalMemoryOpsElimination::visitStoreInst(StoreInst &I)
1002+
{
1003+
if (I.getPointerAddressSpace() == ADDRESS_SPACE_LOCAL)
1004+
{
1005+
m_LocalStoresToRemove.push_back(&I);
1006+
}
1007+
}
1008+
1009+
bool TrivialLocalMemoryOpsElimination::isLocalBarrier(CallInst &I)
1010+
{
1011+
//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
1012+
// (i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true) it is local barrier
1013+
std::vector<bool> argumentsOfMemoryBarrier;
1014+
1015+
for (auto arg = I.arg_begin(); arg != I.arg_end(); ++arg)
1016+
{
1017+
ConstantInt* ci = dyn_cast<ConstantInt>(arg);
1018+
argumentsOfMemoryBarrier.push_back(ci->getValue().getBoolValue());
1019+
}
1020+
1021+
return argumentsOfMemoryBarrier == m_argumentsOfLocalMemoryBarrier;
1022+
}
1023+
1024+
// If any call instruction use pointer to local memory abort pass execution
1025+
void TrivialLocalMemoryOpsElimination::anyCallInstUseLocalMemory(CallInst &I)
1026+
{
1027+
Function* fn = I.getCalledFunction();
1028+
1029+
if (fn != NULL)
1030+
{
1031+
for (auto arg = fn->arg_begin(); arg != fn->arg_end(); ++arg)
1032+
{
1033+
if (arg->getType()->isPointerTy())
1034+
{
1035+
if (arg->getType()->getPointerAddressSpace() == ADDRESS_SPACE_LOCAL || arg->getType()->getPointerAddressSpace() == ADDRESS_SPACE_GENERIC) abortPass = true;
1036+
}
1037+
}
1038+
}
1039+
}
1040+
1041+
void TrivialLocalMemoryOpsElimination::visitCallInst(CallInst &I)
1042+
{
1043+
// detect only: llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
1044+
// (note: the first and last arguments are true)
1045+
// and add them with immediately following barriers to m_LocalFencesBariersToRemove
1046+
anyCallInstUseLocalMemory(I);
1047+
1048+
if (isa<GenIntrinsicInst>(I))
1049+
{
1050+
GenIntrinsicInst *II = dyn_cast<GenIntrinsicInst>(&I);
1051+
if (II->getIntrinsicID() == GenISAIntrinsic::GenISA_memoryfence)
1052+
{
1053+
if (isLocalBarrier(I))
1054+
{
1055+
m_LocalFencesBariersToRemove.push_back(&I);
1056+
findNextThreadGroupBarrierInst(I);
1057+
}
1058+
}
1059+
}
1060+
1061+
}
1062+
#endif
1063+
9271064
// Register pass to igc-opt
9281065
#define PASS_FLAG2 "igc-gen-specific-pattern"
9291066
#define PASS_DESCRIPTION2 "LastPatternMatch Pass"
@@ -3471,6 +3608,8 @@ bool FlattenSmallSwitch::runOnFunction(Function &F)
34713608
IGC_INITIALIZE_PASS_BEGIN(FlattenSmallSwitch, "flattenSmallSwitch", "flattenSmallSwitch", false, false)
34723609
IGC_INITIALIZE_PASS_END(FlattenSmallSwitch, "flattenSmallSwitch", "flattenSmallSwitch", false, false)
34733610

3611+
3612+
34743613
////////////////////////////////////////////////////////////////////////
34753614
// LogicalAndToBranch trying to find logical AND like below:
34763615
// 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)