Skip to content

Commit ac8f9d5

Browse files
mnaczkgfxbot
authored andcommitted
Add pass which removes unnecessary operations on local memory
Change-Id: I2e368633230ead722741552f4aa72212ad4c6a67
1 parent 491d9a7 commit ac8f9d5

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
@@ -1473,6 +1473,9 @@ void OptimizeIR(CodeGenContext* pContext)
14731473
mpm.add(createSROAPass());
14741474
}
14751475
}
1476+
#if LLVM_VERSION_MAJOR >= 7
1477+
mpm.add(new TrivialLocalMemoryOpsElimination());
1478+
#endif
14761479
mpm.add(createGenSimplificationPass());
14771480

14781481
if (pContext->m_instrTypes.hasLoadStore)

IGC/Compiler/CustomSafeOptPass.cpp

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,148 @@ void CustomSafeOptPass::visitExtractElementInst(ExtractElementInst &I)
10281028
}
10291029
}
10301030

1031+
#if LLVM_VERSION_MAJOR >= 7
1032+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1033+
// This pass removes dead local memory loads and stores. If we remove all such loads and stores, we also
1034+
// remove all local memory fences together with barriers that follow.
1035+
//
1036+
IGC_INITIALIZE_PASS_BEGIN(TrivialLocalMemoryOpsElimination, "TrivialLocalMemoryOpsElimination", "TrivialLocalMemoryOpsElimination", false, false)
1037+
IGC_INITIALIZE_PASS_END(TrivialLocalMemoryOpsElimination, "TrivialLocalMemoryOpsElimination", "TrivialLocalMemoryOpsElimination", false, false)
1038+
1039+
char TrivialLocalMemoryOpsElimination::ID = 0;
1040+
1041+
TrivialLocalMemoryOpsElimination::TrivialLocalMemoryOpsElimination() : FunctionPass(ID)
1042+
{
1043+
initializeTrivialLocalMemoryOpsEliminationPass(*PassRegistry::getPassRegistry());
1044+
}
1045+
1046+
bool TrivialLocalMemoryOpsElimination::runOnFunction(Function &F)
1047+
{
1048+
bool change = false;
1049+
visit(F);
1050+
if (!abortPass && (m_LocalLoadsToRemove.empty() || m_LocalStoresToRemove.empty()))
1051+
{
1052+
for (StoreInst *Inst : m_LocalStoresToRemove)
1053+
{
1054+
Inst->eraseFromParent();
1055+
change = true;
1056+
}
1057+
1058+
for (LoadInst *Inst : m_LocalLoadsToRemove)
1059+
{
1060+
if (Inst->use_empty())
1061+
{
1062+
Inst->eraseFromParent();
1063+
change = true;
1064+
}
1065+
}
1066+
1067+
for (CallInst *Inst : m_LocalFencesBariersToRemove)
1068+
{
1069+
Inst->eraseFromParent();
1070+
change = true;
1071+
}
1072+
}
1073+
m_LocalStoresToRemove.clear();
1074+
m_LocalLoadsToRemove.clear();
1075+
m_LocalFencesBariersToRemove.clear();
1076+
1077+
1078+
return change;
1079+
}
1080+
1081+
/*
1082+
OCL instruction barrier(CLK_LOCAL_MEM_FENCE); is translate to two instructions
1083+
call void @llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
1084+
call void @llvm.genx.GenISA.threadgroupbarrier()
1085+
1086+
if we remove call void @llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
1087+
we must remove next instruction if it is call void @llvm.genx.GenISA.threadgroupbarrier()
1088+
*/
1089+
void TrivialLocalMemoryOpsElimination::findNextThreadGroupBarrierInst(Instruction &I)
1090+
{
1091+
auto nextInst = I.getNextNonDebugInstruction();
1092+
if (isa<GenIntrinsicInst>(nextInst))
1093+
{
1094+
GenIntrinsicInst *II = dyn_cast<GenIntrinsicInst>(nextInst);
1095+
if (II->getIntrinsicID() == GenISAIntrinsic::GenISA_threadgroupbarrier)
1096+
{
1097+
m_LocalFencesBariersToRemove.push_back(dyn_cast<CallInst>(nextInst));
1098+
}
1099+
}
1100+
}
1101+
1102+
void TrivialLocalMemoryOpsElimination::visitLoadInst(LoadInst &I)
1103+
{
1104+
if (I.getPointerAddressSpace() == ADDRESS_SPACE_LOCAL)
1105+
{
1106+
m_LocalLoadsToRemove.push_back(&I);
1107+
}
1108+
}
1109+
1110+
void TrivialLocalMemoryOpsElimination::visitStoreInst(StoreInst &I)
1111+
{
1112+
if (I.getPointerAddressSpace() == ADDRESS_SPACE_LOCAL)
1113+
{
1114+
m_LocalStoresToRemove.push_back(&I);
1115+
}
1116+
}
1117+
1118+
bool TrivialLocalMemoryOpsElimination::isLocalBarrier(CallInst &I)
1119+
{
1120+
//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
1121+
// (i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true) it is local barrier
1122+
std::vector<bool> argumentsOfMemoryBarrier;
1123+
1124+
for (auto arg = I.arg_begin(); arg != I.arg_end(); ++arg)
1125+
{
1126+
ConstantInt* ci = dyn_cast<ConstantInt>(arg);
1127+
argumentsOfMemoryBarrier.push_back(ci->getValue().getBoolValue());
1128+
}
1129+
1130+
return argumentsOfMemoryBarrier == m_argumentsOfLocalMemoryBarrier;
1131+
}
1132+
1133+
// If any call instruction use pointer to local memory abort pass execution
1134+
void TrivialLocalMemoryOpsElimination::anyCallInstUseLocalMemory(CallInst &I)
1135+
{
1136+
Function* fn = I.getCalledFunction();
1137+
1138+
if (fn != NULL)
1139+
{
1140+
for (auto arg = fn->arg_begin(); arg != fn->arg_end(); ++arg)
1141+
{
1142+
if (arg->getType()->isPointerTy())
1143+
{
1144+
if (arg->getType()->getPointerAddressSpace() == ADDRESS_SPACE_LOCAL || arg->getType()->getPointerAddressSpace() == ADDRESS_SPACE_GENERIC) abortPass = true;
1145+
}
1146+
}
1147+
}
1148+
}
1149+
1150+
void TrivialLocalMemoryOpsElimination::visitCallInst(CallInst &I)
1151+
{
1152+
// detect only: llvm.genx.GenISA.memoryfence(i1 true, i1 false, i1 false, i1 false, i1 false, i1 false, i1 true)
1153+
// (note: the first and last arguments are true)
1154+
// and add them with immediately following barriers to m_LocalFencesBariersToRemove
1155+
anyCallInstUseLocalMemory(I);
1156+
1157+
if (isa<GenIntrinsicInst>(I))
1158+
{
1159+
GenIntrinsicInst *II = dyn_cast<GenIntrinsicInst>(&I);
1160+
if (II->getIntrinsicID() == GenISAIntrinsic::GenISA_memoryfence)
1161+
{
1162+
if (isLocalBarrier(I))
1163+
{
1164+
m_LocalFencesBariersToRemove.push_back(&I);
1165+
findNextThreadGroupBarrierInst(I);
1166+
}
1167+
}
1168+
}
1169+
1170+
}
1171+
#endif
1172+
10311173
// Register pass to igc-opt
10321174
#define PASS_FLAG2 "igc-gen-specific-pattern"
10331175
#define PASS_DESCRIPTION2 "LastPatternMatch Pass"

IGC/Compiler/CustomSafeOptPass.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ 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

3637
namespace llvm
@@ -99,6 +100,40 @@ namespace IGC
99100
bool psHasSideEffect;
100101
};
101102

103+
#if LLVM_VERSION_MAJOR >= 7
104+
class TrivialLocalMemoryOpsElimination : public llvm::FunctionPass, public llvm::InstVisitor<TrivialLocalMemoryOpsElimination>
105+
{
106+
public:
107+
static char ID;
108+
109+
TrivialLocalMemoryOpsElimination();
110+
111+
~TrivialLocalMemoryOpsElimination() {}
112+
113+
virtual bool runOnFunction(llvm::Function &F) override;
114+
115+
virtual llvm::StringRef getPassName() const override
116+
{
117+
return "TrivialLocalMemoryOpsElimination";
118+
}
119+
120+
void visitLoadInst(llvm::LoadInst &I);
121+
void visitStoreInst(llvm::StoreInst &I);
122+
void visitCallInst(llvm::CallInst &I);
123+
bool isLocalBarrier(llvm::CallInst &I);
124+
void findNextThreadGroupBarrierInst(llvm::Instruction &I);
125+
void anyCallInstUseLocalMemory(llvm::CallInst &I);
126+
127+
private:
128+
llvm::SmallVector<llvm::LoadInst*, 16> m_LocalLoadsToRemove;
129+
llvm::SmallVector<llvm::StoreInst*, 16> m_LocalStoresToRemove;
130+
llvm::SmallVector<llvm::CallInst*, 16> m_LocalFencesBariersToRemove;
131+
132+
bool abortPass = false;
133+
const std::vector<bool> m_argumentsOfLocalMemoryBarrier{ true, false, false, false, false, false, true };
134+
};
135+
#endif
136+
102137
class GenSpecificPattern : public llvm::FunctionPass, public llvm::InstVisitor<GenSpecificPattern>
103138
{
104139
public:

IGC/Compiler/InitializePasses.h

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

0 commit comments

Comments
 (0)