@@ -184,6 +184,7 @@ class InferAddressSpaces : public FunctionPass {
184184
185185class InferAddressSpacesImpl {
186186 AssumptionCache ∾
187+ Function *F = nullptr ;
187188 const DominatorTree *DT = nullptr ;
188189 const TargetTransformInfo *TTI = nullptr ;
189190 const DataLayout *DL = nullptr ;
@@ -212,14 +213,17 @@ class InferAddressSpacesImpl {
212213 const PredicatedAddrSpaceMapTy &PredicatedAS,
213214 SmallVectorImpl<const Use *> *PoisonUsesToFix) const ;
214215
216+ void performPointerReplacement (
217+ Value *V, Value *NewV, Use &U, ValueToValueMapTy &ValueWithNewAddrSpace,
218+ SmallVectorImpl<Instruction *> &DeadInstructions) const ;
219+
215220 // Changes the flat address expressions in function F to point to specific
216221 // address spaces if InferredAddrSpace says so. Postorder is the postorder of
217222 // all flat expressions in the use-def graph of function F.
218- bool
219- rewriteWithNewAddressSpaces (ArrayRef<WeakTrackingVH> Postorder,
220- const ValueToAddrSpaceMapTy &InferredAddrSpace,
221- const PredicatedAddrSpaceMapTy &PredicatedAS,
222- Function *F) const ;
223+ bool rewriteWithNewAddressSpaces (
224+ ArrayRef<WeakTrackingVH> Postorder,
225+ const ValueToAddrSpaceMapTy &InferredAddrSpace,
226+ const PredicatedAddrSpaceMapTy &PredicatedAS) const ;
223227
224228 void appendsFlatAddressExpressionToPostorderStack (
225229 Value *V, PostorderStackTy &PostorderStack,
@@ -842,8 +846,9 @@ unsigned InferAddressSpacesImpl::joinAddressSpaces(unsigned AS1,
842846 return (AS1 == AS2) ? AS1 : FlatAddrSpace;
843847}
844848
845- bool InferAddressSpacesImpl::run (Function &F) {
846- DL = &F.getDataLayout ();
849+ bool InferAddressSpacesImpl::run (Function &CurFn) {
850+ F = &CurFn;
851+ DL = &F->getDataLayout ();
847852
848853 if (AssumeDefaultIsFlatAddressSpace)
849854 FlatAddrSpace = 0 ;
@@ -855,7 +860,7 @@ bool InferAddressSpacesImpl::run(Function &F) {
855860 }
856861
857862 // Collects all flat address expressions in postorder.
858- std::vector<WeakTrackingVH> Postorder = collectFlatAddressExpressions (F);
863+ std::vector<WeakTrackingVH> Postorder = collectFlatAddressExpressions (* F);
859864
860865 // Runs a data-flow analysis to refine the address spaces of every expression
861866 // in Postorder.
@@ -865,8 +870,8 @@ bool InferAddressSpacesImpl::run(Function &F) {
865870
866871 // Changes the address spaces of the flat address expressions who are inferred
867872 // to point to a specific address space.
868- return rewriteWithNewAddressSpaces (Postorder, InferredAddrSpace, PredicatedAS,
869- &F );
873+ return rewriteWithNewAddressSpaces (Postorder, InferredAddrSpace,
874+ PredicatedAS );
870875}
871876
872877// Constants need to be tracked through RAUW to handle cases with nested
@@ -1168,10 +1173,103 @@ static Value::use_iterator skipToNextUser(Value::use_iterator I,
11681173 return I;
11691174}
11701175
1176+ void InferAddressSpacesImpl::performPointerReplacement (
1177+ Value *V, Value *NewV, Use &U, ValueToValueMapTy &ValueWithNewAddrSpace,
1178+ SmallVectorImpl<Instruction *> &DeadInstructions) const {
1179+
1180+ User *CurUser = U.getUser ();
1181+
1182+ unsigned AddrSpace = V->getType ()->getPointerAddressSpace ();
1183+ if (replaceIfSimplePointerUse (*TTI, CurUser, AddrSpace, V, NewV))
1184+ return ;
1185+
1186+ // Skip if the current user is the new value itself.
1187+ if (CurUser == NewV)
1188+ return ;
1189+
1190+ auto *CurUserI = dyn_cast<Instruction>(CurUser);
1191+ if (!CurUserI || CurUserI->getFunction () != F)
1192+ return ;
1193+
1194+ // Handle more complex cases like intrinsic that need to be remangled.
1195+ if (auto *MI = dyn_cast<MemIntrinsic>(CurUser)) {
1196+ if (!MI->isVolatile () && handleMemIntrinsicPtrUse (MI, V, NewV))
1197+ return ;
1198+ }
1199+
1200+ if (auto *II = dyn_cast<IntrinsicInst>(CurUser)) {
1201+ if (rewriteIntrinsicOperands (II, V, NewV))
1202+ return ;
1203+ }
1204+
1205+ if (ICmpInst *Cmp = dyn_cast<ICmpInst>(CurUserI)) {
1206+ // If we can infer that both pointers are in the same addrspace,
1207+ // transform e.g.
1208+ // %cmp = icmp eq float* %p, %q
1209+ // into
1210+ // %cmp = icmp eq float addrspace(3)* %new_p, %new_q
1211+
1212+ unsigned NewAS = NewV->getType ()->getPointerAddressSpace ();
1213+ int SrcIdx = U.getOperandNo ();
1214+ int OtherIdx = (SrcIdx == 0 ) ? 1 : 0 ;
1215+ Value *OtherSrc = Cmp->getOperand (OtherIdx);
1216+
1217+ if (Value *OtherNewV = ValueWithNewAddrSpace.lookup (OtherSrc)) {
1218+ if (OtherNewV->getType ()->getPointerAddressSpace () == NewAS) {
1219+ Cmp->setOperand (OtherIdx, OtherNewV);
1220+ Cmp->setOperand (SrcIdx, NewV);
1221+ return ;
1222+ }
1223+ }
1224+
1225+ // Even if the type mismatches, we can cast the constant.
1226+ if (auto *KOtherSrc = dyn_cast<Constant>(OtherSrc)) {
1227+ if (isSafeToCastConstAddrSpace (KOtherSrc, NewAS)) {
1228+ Cmp->setOperand (SrcIdx, NewV);
1229+ Cmp->setOperand (OtherIdx, ConstantExpr::getAddrSpaceCast (
1230+ KOtherSrc, NewV->getType ()));
1231+ return ;
1232+ }
1233+ }
1234+ }
1235+
1236+ if (AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(CurUserI)) {
1237+ unsigned NewAS = NewV->getType ()->getPointerAddressSpace ();
1238+ if (ASC->getDestAddressSpace () == NewAS) {
1239+ ASC->replaceAllUsesWith (NewV);
1240+ DeadInstructions.push_back (ASC);
1241+ return ;
1242+ }
1243+ }
1244+
1245+ // Otherwise, replaces the use with flat(NewV).
1246+ if (Instruction *VInst = dyn_cast<Instruction>(V)) {
1247+ // Don't create a copy of the original addrspacecast.
1248+ if (U == V && isa<AddrSpaceCastInst>(V))
1249+ return ;
1250+
1251+ // Insert the addrspacecast after NewV.
1252+ BasicBlock::iterator InsertPos;
1253+ if (Instruction *NewVInst = dyn_cast<Instruction>(NewV))
1254+ InsertPos = std::next (NewVInst->getIterator ());
1255+ else
1256+ InsertPos = std::next (VInst->getIterator ());
1257+
1258+ while (isa<PHINode>(InsertPos))
1259+ ++InsertPos;
1260+ // This instruction may contain multiple uses of V, update them all.
1261+ CurUser->replaceUsesOfWith (
1262+ V, new AddrSpaceCastInst (NewV, V->getType (), " " , InsertPos));
1263+ } else {
1264+ CurUserI->replaceUsesOfWith (
1265+ V, ConstantExpr::getAddrSpaceCast (cast<Constant>(NewV), V->getType ()));
1266+ }
1267+ }
1268+
11711269bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces (
11721270 ArrayRef<WeakTrackingVH> Postorder,
11731271 const ValueToAddrSpaceMapTy &InferredAddrSpace,
1174- const PredicatedAddrSpaceMapTy &PredicatedAS, Function *F ) const {
1272+ const PredicatedAddrSpaceMapTy &PredicatedAS) const {
11751273 // For each address expression to be modified, creates a clone of it with its
11761274 // pointer operands converted to the new address space. Since the pointer
11771275 // operands are converted, the clone is naturally in the new address space by
@@ -1262,100 +1360,13 @@ bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(
12621360 Value::use_iterator I, E, Next;
12631361 for (I = V->use_begin (), E = V->use_end (); I != E;) {
12641362 Use &U = *I;
1265- User *CurUser = U.getUser ();
12661363
12671364 // Some users may see the same pointer operand in multiple operands. Skip
12681365 // to the next instruction.
12691366 I = skipToNextUser (I, E);
12701367
1271- unsigned AddrSpace = V->getType ()->getPointerAddressSpace ();
1272- if (replaceIfSimplePointerUse (*TTI, CurUser, AddrSpace, V, NewV))
1273- continue ;
1274-
1275- // Skip if the current user is the new value itself.
1276- if (CurUser == NewV)
1277- continue ;
1278-
1279- if (auto *CurUserI = dyn_cast<Instruction>(CurUser);
1280- CurUserI && CurUserI->getFunction () != F)
1281- continue ;
1282-
1283- // Handle more complex cases like intrinsic that need to be remangled.
1284- if (auto *MI = dyn_cast<MemIntrinsic>(CurUser)) {
1285- if (!MI->isVolatile () && handleMemIntrinsicPtrUse (MI, V, NewV))
1286- continue ;
1287- }
1288-
1289- if (auto *II = dyn_cast<IntrinsicInst>(CurUser)) {
1290- if (rewriteIntrinsicOperands (II, V, NewV))
1291- continue ;
1292- }
1293-
1294- if (isa<Instruction>(CurUser)) {
1295- if (ICmpInst *Cmp = dyn_cast<ICmpInst>(CurUser)) {
1296- // If we can infer that both pointers are in the same addrspace,
1297- // transform e.g.
1298- // %cmp = icmp eq float* %p, %q
1299- // into
1300- // %cmp = icmp eq float addrspace(3)* %new_p, %new_q
1301-
1302- unsigned NewAS = NewV->getType ()->getPointerAddressSpace ();
1303- int SrcIdx = U.getOperandNo ();
1304- int OtherIdx = (SrcIdx == 0 ) ? 1 : 0 ;
1305- Value *OtherSrc = Cmp->getOperand (OtherIdx);
1306-
1307- if (Value *OtherNewV = ValueWithNewAddrSpace.lookup (OtherSrc)) {
1308- if (OtherNewV->getType ()->getPointerAddressSpace () == NewAS) {
1309- Cmp->setOperand (OtherIdx, OtherNewV);
1310- Cmp->setOperand (SrcIdx, NewV);
1311- continue ;
1312- }
1313- }
1314-
1315- // Even if the type mismatches, we can cast the constant.
1316- if (auto *KOtherSrc = dyn_cast<Constant>(OtherSrc)) {
1317- if (isSafeToCastConstAddrSpace (KOtherSrc, NewAS)) {
1318- Cmp->setOperand (SrcIdx, NewV);
1319- Cmp->setOperand (OtherIdx, ConstantExpr::getAddrSpaceCast (
1320- KOtherSrc, NewV->getType ()));
1321- continue ;
1322- }
1323- }
1324- }
1325-
1326- if (AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(CurUser)) {
1327- unsigned NewAS = NewV->getType ()->getPointerAddressSpace ();
1328- if (ASC->getDestAddressSpace () == NewAS) {
1329- ASC->replaceAllUsesWith (NewV);
1330- DeadInstructions.push_back (ASC);
1331- continue ;
1332- }
1333- }
1334-
1335- // Otherwise, replaces the use with flat(NewV).
1336- if (Instruction *VInst = dyn_cast<Instruction>(V)) {
1337- // Don't create a copy of the original addrspacecast.
1338- if (U == V && isa<AddrSpaceCastInst>(V))
1339- continue ;
1340-
1341- // Insert the addrspacecast after NewV.
1342- BasicBlock::iterator InsertPos;
1343- if (Instruction *NewVInst = dyn_cast<Instruction>(NewV))
1344- InsertPos = std::next (NewVInst->getIterator ());
1345- else
1346- InsertPos = std::next (VInst->getIterator ());
1347-
1348- while (isa<PHINode>(InsertPos))
1349- ++InsertPos;
1350- // This instruction may contain multiple uses of V, update them all.
1351- CurUser->replaceUsesOfWith (
1352- V, new AddrSpaceCastInst (NewV, V->getType (), " " , InsertPos));
1353- } else {
1354- CurUser->replaceUsesOfWith (
1355- V, ConstantExpr::getAddrSpaceCast (cast<Constant>(NewV),
1356- V->getType ()));
1357- }
1358- }
1368+ performPointerReplacement (V, NewV, U, ValueWithNewAddrSpace,
1369+ DeadInstructions);
13591370 }
13601371
13611372 if (V->use_empty ()) {
0 commit comments