@@ -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)
34713611IGC_INITIALIZE_PASS_BEGIN (FlattenSmallSwitch, " flattenSmallSwitch" , " flattenSmallSwitch" , false , false )
34723612IGC_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
0 commit comments