Skip to content

Commit 091890f

Browse files
committed
InferAddressSpaces: Factor replacement loop into function
1 parent 100c9c0 commit 091890f

File tree

1 file changed

+113
-100
lines changed

1 file changed

+113
-100
lines changed

llvm/lib/Transforms/Scalar/InferAddressSpaces.cpp

Lines changed: 113 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ class InferAddressSpaces : public FunctionPass {
184184

185185
class 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 &F_) {
850+
F = &F_;
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
@@ -1164,10 +1169,105 @@ static Value::use_iterator skipToNextUser(Value::use_iterator I,
11641169
return I;
11651170
}
11661171

1172+
void InferAddressSpacesImpl::performPointerReplacement(
1173+
Value *V, Value *NewV, Use &U, ValueToValueMapTy &ValueWithNewAddrSpace,
1174+
SmallVectorImpl<Instruction *> &DeadInstructions) const {
1175+
1176+
User *CurUser = U.getUser();
1177+
1178+
unsigned AddrSpace = V->getType()->getPointerAddressSpace();
1179+
if (replaceIfSimplePointerUse(*TTI, CurUser, AddrSpace, V, NewV))
1180+
return;
1181+
1182+
// Skip if the current user is the new value itself.
1183+
if (CurUser == NewV)
1184+
return;
1185+
1186+
if (auto *CurUserI = dyn_cast<Instruction>(CurUser);
1187+
CurUserI && CurUserI->getFunction() != F)
1188+
return;
1189+
1190+
// Handle more complex cases like intrinsic that need to be remangled.
1191+
if (auto *MI = dyn_cast<MemIntrinsic>(CurUser)) {
1192+
if (!MI->isVolatile() && handleMemIntrinsicPtrUse(MI, V, NewV))
1193+
return;
1194+
}
1195+
1196+
if (auto *II = dyn_cast<IntrinsicInst>(CurUser)) {
1197+
if (rewriteIntrinsicOperands(II, V, NewV))
1198+
return;
1199+
}
1200+
1201+
if (isa<Instruction>(CurUser)) {
1202+
if (ICmpInst *Cmp = dyn_cast<ICmpInst>(CurUser)) {
1203+
// If we can infer that both pointers are in the same addrspace,
1204+
// transform e.g.
1205+
// %cmp = icmp eq float* %p, %q
1206+
// into
1207+
// %cmp = icmp eq float addrspace(3)* %new_p, %new_q
1208+
1209+
unsigned NewAS = NewV->getType()->getPointerAddressSpace();
1210+
int SrcIdx = U.getOperandNo();
1211+
int OtherIdx = (SrcIdx == 0) ? 1 : 0;
1212+
Value *OtherSrc = Cmp->getOperand(OtherIdx);
1213+
1214+
if (Value *OtherNewV = ValueWithNewAddrSpace.lookup(OtherSrc)) {
1215+
if (OtherNewV->getType()->getPointerAddressSpace() == NewAS) {
1216+
Cmp->setOperand(OtherIdx, OtherNewV);
1217+
Cmp->setOperand(SrcIdx, NewV);
1218+
return;
1219+
}
1220+
}
1221+
1222+
// Even if the type mismatches, we can cast the constant.
1223+
if (auto *KOtherSrc = dyn_cast<Constant>(OtherSrc)) {
1224+
if (isSafeToCastConstAddrSpace(KOtherSrc, NewAS)) {
1225+
Cmp->setOperand(SrcIdx, NewV);
1226+
Cmp->setOperand(OtherIdx, ConstantExpr::getAddrSpaceCast(
1227+
KOtherSrc, NewV->getType()));
1228+
return;
1229+
}
1230+
}
1231+
}
1232+
1233+
if (AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(CurUser)) {
1234+
unsigned NewAS = NewV->getType()->getPointerAddressSpace();
1235+
if (ASC->getDestAddressSpace() == NewAS) {
1236+
ASC->replaceAllUsesWith(NewV);
1237+
DeadInstructions.push_back(ASC);
1238+
return;
1239+
}
1240+
}
1241+
1242+
// Otherwise, replaces the use with flat(NewV).
1243+
if (Instruction *VInst = dyn_cast<Instruction>(V)) {
1244+
// Don't create a copy of the original addrspacecast.
1245+
if (U == V && isa<AddrSpaceCastInst>(V))
1246+
return;
1247+
1248+
// Insert the addrspacecast after NewV.
1249+
BasicBlock::iterator InsertPos;
1250+
if (Instruction *NewVInst = dyn_cast<Instruction>(NewV))
1251+
InsertPos = std::next(NewVInst->getIterator());
1252+
else
1253+
InsertPos = std::next(VInst->getIterator());
1254+
1255+
while (isa<PHINode>(InsertPos))
1256+
++InsertPos;
1257+
// This instruction may contain multiple uses of V, update them all.
1258+
CurUser->replaceUsesOfWith(
1259+
V, new AddrSpaceCastInst(NewV, V->getType(), "", InsertPos));
1260+
} else {
1261+
CurUser->replaceUsesOfWith(V, ConstantExpr::getAddrSpaceCast(
1262+
cast<Constant>(NewV), V->getType()));
1263+
}
1264+
}
1265+
}
1266+
11671267
bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(
11681268
ArrayRef<WeakTrackingVH> Postorder,
11691269
const ValueToAddrSpaceMapTy &InferredAddrSpace,
1170-
const PredicatedAddrSpaceMapTy &PredicatedAS, Function *F) const {
1270+
const PredicatedAddrSpaceMapTy &PredicatedAS) const {
11711271
// For each address expression to be modified, creates a clone of it with its
11721272
// pointer operands converted to the new address space. Since the pointer
11731273
// operands are converted, the clone is naturally in the new address space by
@@ -1258,100 +1358,13 @@ bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(
12581358
Value::use_iterator I, E, Next;
12591359
for (I = V->use_begin(), E = V->use_end(); I != E;) {
12601360
Use &U = *I;
1261-
User *CurUser = U.getUser();
12621361

12631362
// Some users may see the same pointer operand in multiple operands. Skip
12641363
// to the next instruction.
12651364
I = skipToNextUser(I, E);
12661365

1267-
unsigned AddrSpace = V->getType()->getPointerAddressSpace();
1268-
if (replaceIfSimplePointerUse(*TTI, CurUser, AddrSpace, V, NewV))
1269-
continue;
1270-
1271-
// Skip if the current user is the new value itself.
1272-
if (CurUser == NewV)
1273-
continue;
1274-
1275-
if (auto *CurUserI = dyn_cast<Instruction>(CurUser);
1276-
CurUserI && CurUserI->getFunction() != F)
1277-
continue;
1278-
1279-
// Handle more complex cases like intrinsic that need to be remangled.
1280-
if (auto *MI = dyn_cast<MemIntrinsic>(CurUser)) {
1281-
if (!MI->isVolatile() && handleMemIntrinsicPtrUse(MI, V, NewV))
1282-
continue;
1283-
}
1284-
1285-
if (auto *II = dyn_cast<IntrinsicInst>(CurUser)) {
1286-
if (rewriteIntrinsicOperands(II, V, NewV))
1287-
continue;
1288-
}
1289-
1290-
if (isa<Instruction>(CurUser)) {
1291-
if (ICmpInst *Cmp = dyn_cast<ICmpInst>(CurUser)) {
1292-
// If we can infer that both pointers are in the same addrspace,
1293-
// transform e.g.
1294-
// %cmp = icmp eq float* %p, %q
1295-
// into
1296-
// %cmp = icmp eq float addrspace(3)* %new_p, %new_q
1297-
1298-
unsigned NewAS = NewV->getType()->getPointerAddressSpace();
1299-
int SrcIdx = U.getOperandNo();
1300-
int OtherIdx = (SrcIdx == 0) ? 1 : 0;
1301-
Value *OtherSrc = Cmp->getOperand(OtherIdx);
1302-
1303-
if (Value *OtherNewV = ValueWithNewAddrSpace.lookup(OtherSrc)) {
1304-
if (OtherNewV->getType()->getPointerAddressSpace() == NewAS) {
1305-
Cmp->setOperand(OtherIdx, OtherNewV);
1306-
Cmp->setOperand(SrcIdx, NewV);
1307-
continue;
1308-
}
1309-
}
1310-
1311-
// Even if the type mismatches, we can cast the constant.
1312-
if (auto *KOtherSrc = dyn_cast<Constant>(OtherSrc)) {
1313-
if (isSafeToCastConstAddrSpace(KOtherSrc, NewAS)) {
1314-
Cmp->setOperand(SrcIdx, NewV);
1315-
Cmp->setOperand(OtherIdx, ConstantExpr::getAddrSpaceCast(
1316-
KOtherSrc, NewV->getType()));
1317-
continue;
1318-
}
1319-
}
1320-
}
1321-
1322-
if (AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(CurUser)) {
1323-
unsigned NewAS = NewV->getType()->getPointerAddressSpace();
1324-
if (ASC->getDestAddressSpace() == NewAS) {
1325-
ASC->replaceAllUsesWith(NewV);
1326-
DeadInstructions.push_back(ASC);
1327-
continue;
1328-
}
1329-
}
1330-
1331-
// Otherwise, replaces the use with flat(NewV).
1332-
if (Instruction *VInst = dyn_cast<Instruction>(V)) {
1333-
// Don't create a copy of the original addrspacecast.
1334-
if (U == V && isa<AddrSpaceCastInst>(V))
1335-
continue;
1336-
1337-
// Insert the addrspacecast after NewV.
1338-
BasicBlock::iterator InsertPos;
1339-
if (Instruction *NewVInst = dyn_cast<Instruction>(NewV))
1340-
InsertPos = std::next(NewVInst->getIterator());
1341-
else
1342-
InsertPos = std::next(VInst->getIterator());
1343-
1344-
while (isa<PHINode>(InsertPos))
1345-
++InsertPos;
1346-
// This instruction may contain multiple uses of V, update them all.
1347-
CurUser->replaceUsesOfWith(
1348-
V, new AddrSpaceCastInst(NewV, V->getType(), "", InsertPos));
1349-
} else {
1350-
CurUser->replaceUsesOfWith(
1351-
V, ConstantExpr::getAddrSpaceCast(cast<Constant>(NewV),
1352-
V->getType()));
1353-
}
1354-
}
1366+
performPointerReplacement(V, NewV, U, ValueWithNewAddrSpace,
1367+
DeadInstructions);
13551368
}
13561369

13571370
if (V->use_empty()) {

0 commit comments

Comments
 (0)