@@ -899,8 +899,9 @@ namespace {
899
899
900
900
void getAnalysisUsage (AnalysisUsage& AU) const override ;
901
901
bool runOnSCC (CallGraphSCC& SCC) override ;
902
- void verifyIfGEPIandLoadHasTheSameAS (CallGraphSCC& SCC);
902
+ void verifyAddrSpaceMismatch (CallGraphSCC& SCC);
903
903
void visitGetElementPtrInst (GetElementPtrInst& I);
904
+ void visitMemCpyInst (MemCpyInst& I);
904
905
905
906
using llvm::Pass::doFinalization;
906
907
bool doFinalization (CallGraph& CG) override {
@@ -953,14 +954,43 @@ void SubroutineInliner::visitGetElementPtrInst(GetElementPtrInst& GEPI)
953
954
}
954
955
}
955
956
957
+ void SubroutineInliner::visitMemCpyInst (MemCpyInst& I)
958
+ {
959
+ Value* Src = I.getRawSource ();
960
+ Value* Dst = I.getRawDest ();
961
+ Value* origSrc = I.getSource ();
962
+ Value* origDst = I.getDest ();
963
+ // Copying from alloca to alloca, but has addrspace mismatch due to incorrect bitcast
964
+ if (isa<AllocaInst>(origSrc) && isa<AllocaInst>(origDst))
965
+ {
966
+ if (origSrc->getType ()->getPointerAddressSpace () != Src->getType ()->getPointerAddressSpace ())
967
+ {
968
+ Value* SrcCast = BitCastInst::Create (Instruction::BitCast, origSrc,
969
+ PointerType::get (Src->getType ()->getPointerElementType (), origSrc->getType ()->getPointerAddressSpace ()),
970
+ " " , &I);
971
+ I.replaceUsesOfWith (Src, SrcCast);
972
+ }
973
+ if (origDst->getType ()->getPointerAddressSpace () != Dst->getType ()->getPointerAddressSpace ())
974
+ {
975
+ Value* DstCast = BitCastInst::Create (Instruction::BitCast, origDst,
976
+ PointerType::get (Dst->getType ()->getPointerElementType (), origDst->getType ()->getPointerAddressSpace ()),
977
+ " " , &I);
978
+ I.replaceUsesOfWith (Dst, DstCast);
979
+ }
980
+ }
981
+ }
982
+
956
983
// When this pass encounters a byVal argument, it creates an alloca to then copy the data from global memory to local memory.
957
984
// When creating a new alloca, it replaces all occurrences of the argument in the function with that alloca.
958
- // The problem arises when the pointer operant (or more precisely its address space) is replaced in GetElementPtrInst.
959
- // Because from now on the resulting pointer of this instruction is in a different address space.
960
- // On the other hand, a load instruction that uses the returned GetElementPtrInst pointer still operates on the old address space.
961
- // By which we are referring to the wrong area of memory. The resolution for this problem is to create new load instruction.
985
+ // Problems arises when the pointer operant (or more precisely its address space) is replaced:
986
+ // 1. In GetElementPtrInst, the resulting pointer of this instruction is in a different address space.
987
+ // On the other hand, a load instruction that uses the returned GetElementPtrInst pointer still operates on the old address space.
988
+ // By which we are referring to the wrong area of memory. The resolution for this problem is to create new load instruction.
989
+ // 2. In MemCpyInst, specifically generated for structs used in loops, where two allocas of the same struct type are created used
990
+ // to save and restore struct values. When one is copied to another, this pass incorrectly uses the addrspace of the ByVal argument
991
+ // instead of the local addrspace of the alloca. We fix this by casting the src and dst of the memcpy to the correct addrspace.
962
992
// This is WA for a bug in LLVM 11.
963
- void SubroutineInliner::verifyIfGEPIandLoadHasTheSameAS (CallGraphSCC& SCC)
993
+ void SubroutineInliner::verifyAddrSpaceMismatch (CallGraphSCC& SCC)
964
994
{
965
995
for (CallGraphNode* Node : SCC)
966
996
{
@@ -973,7 +1003,7 @@ bool SubroutineInliner::runOnSCC(CallGraphSCC& SCC)
973
1003
{
974
1004
FSA = &getAnalysis<EstimateFunctionSize>();
975
1005
bool changed = LegacyInlinerBase::runOnSCC (SCC);
976
- if (changed) verifyIfGEPIandLoadHasTheSameAS (SCC);
1006
+ if (changed) verifyAddrSpaceMismatch (SCC);
977
1007
978
1008
return changed;
979
1009
}
0 commit comments