138#define DEBUG_TYPE "infer-address-spaces"
144 std::numeric_limits<unsigned>::max();
155using PredicatedAddrSpaceMapTy =
160 unsigned FlatAddrSpace = 0;
169 InferAddressSpaces(
unsigned AS) : FunctionPass(ID), FlatAddrSpace(AS) {
173 void getAnalysisUsage(AnalysisUsage &AU)
const override {
182class InferAddressSpacesImpl {
185 const DominatorTree *DT =
nullptr;
186 const TargetTransformInfo *TTI =
nullptr;
187 const DataLayout *DL =
nullptr;
191 unsigned FlatAddrSpace = 0;
195 const bool AssumeDefaultIsFlatAddressSpace =
false;
197 DenseMap<const Value *, Value *> PtrIntCastPairs;
202 Value *getIntToPtrPointerOperand(
const Operator *I2P)
const;
207 void collectIntToPtrPointerOperand();
211 bool isSafeToCastIntToPtrAddrSpace(
const Operator *I2P)
const {
212 return PtrIntCastPairs.contains(I2P);
214 bool isAddressExpression(
const Value &V,
const DataLayout &DL,
215 const TargetTransformInfo *TTI)
const;
216 Value *cloneConstantExprWithNewAddressSpace(
217 ConstantExpr *CE,
unsigned NewAddrSpace,
219 const TargetTransformInfo *TTI)
const;
221 SmallVector<Value *, 2>
222 getPointerOperands(
const Value &V,
const DataLayout &DL,
223 const TargetTransformInfo *TTI)
const;
227 bool updateAddressSpace(
const Value &V,
228 ValueToAddrSpaceMapTy &InferredAddrSpace,
229 PredicatedAddrSpaceMapTy &PredicatedAS)
const;
232 void enqueueUsers(
Value &V,
const ValueToAddrSpaceMapTy &InferredAddrSpace,
233 SetVector<Value *> &Worklist)
const;
236 void runToFixPoint(SetVector<Value *> &Worklist,
237 ValueToAddrSpaceMapTy &InferredAddrSpace,
238 PredicatedAddrSpaceMapTy &PredicatedAS)
const;
243 ValueToAddrSpaceMapTy &InferredAddrSpace,
244 PredicatedAddrSpaceMapTy &PredicatedAS)
const;
246 bool isSafeToCastConstAddrSpace(Constant *
C,
unsigned NewAS)
const;
248 Value *clonePtrMaskWithNewAddressSpace(
249 IntrinsicInst *
I,
unsigned NewAddrSpace,
251 const PredicatedAddrSpaceMapTy &PredicatedAS,
252 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const;
254 Value *cloneInstructionWithNewAddressSpace(
255 Instruction *
I,
unsigned NewAddrSpace,
257 const PredicatedAddrSpaceMapTy &PredicatedAS,
258 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const;
260 void performPointerReplacement(
262 SmallVectorImpl<Instruction *> &DeadInstructions)
const;
267 bool rewriteWithNewAddressSpaces(
269 const ValueToAddrSpaceMapTy &InferredAddrSpace,
270 const PredicatedAddrSpaceMapTy &PredicatedAS)
const;
272 void appendsFlatAddressExpressionToPostorderStack(
273 Value *V, PostorderStackTy &PostorderStack,
274 DenseSet<Value *> &Visited)
const;
276 bool rewriteIntrinsicOperands(IntrinsicInst *
II,
Value *OldV,
278 void collectRewritableIntrinsicOperands(IntrinsicInst *
II,
279 PostorderStackTy &PostorderStack,
280 DenseSet<Value *> &Visited)
const;
282 std::vector<WeakTrackingVH> collectFlatAddressExpressions(
Function &F)
const;
284 Value *cloneValueWithNewAddressSpace(
285 Value *V,
unsigned NewAddrSpace,
287 const PredicatedAddrSpaceMapTy &PredicatedAS,
288 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const;
289 unsigned joinAddressSpaces(
unsigned AS1,
unsigned AS2)
const;
291 unsigned getPredicatedAddrSpace(
const Value &PtrV,
292 const Value *UserCtx)
const;
295 InferAddressSpacesImpl(AssumptionCache &AC,
const DominatorTree *DT,
296 const TargetTransformInfo *TTI,
unsigned FlatAddrSpace,
297 bool AssumeDefaultIsFlatAddressSpace)
298 : AC(AC), DT(DT), TTI(TTI), FlatAddrSpace(FlatAddrSpace),
299 AssumeDefaultIsFlatAddressSpace(AssumeDefaultIsFlatAddressSpace) {}
305char InferAddressSpaces::ID = 0;
315 assert(Ty->isPtrOrPtrVectorTy());
317 return Ty->getWithNewType(NPT);
327 if (!P2I || P2I->getOpcode() != Instruction::PtrToInt)
343 unsigned P2IOp0AS = P2I->getOperand(0)->getType()->getPointerAddressSpace();
349 P2I->getOperand(0)->getType(), P2I->getType(),
351 (P2IOp0AS == I2PAS ||
TTI->isNoopAddrSpaceCast(P2IOp0AS, I2PAS));
358bool InferAddressSpacesImpl::isAddressExpression(
363 return Arg->getType()->isPointerTy() &&
370 switch (
Op->getOpcode()) {
371 case Instruction::PHI:
372 assert(
Op->getType()->isPtrOrPtrVectorTy());
374 case Instruction::BitCast:
375 case Instruction::AddrSpaceCast:
376 case Instruction::GetElementPtr:
378 case Instruction::Select:
379 return Op->getType()->isPtrOrPtrVectorTy();
380 case Instruction::Call: {
382 return II &&
II->getIntrinsicID() == Intrinsic::ptrmask;
384 case Instruction::IntToPtr:
386 isSafeToCastIntToPtrAddrSpace(
Op);
396SmallVector<Value *, 2> InferAddressSpacesImpl::getPointerOperands(
397 const Value &V,
const DataLayout &
DL,
398 const TargetTransformInfo *
TTI)
const {
403 switch (
Op.getOpcode()) {
404 case Instruction::PHI: {
406 return {IncomingValues.begin(), IncomingValues.end()};
408 case Instruction::BitCast:
409 case Instruction::AddrSpaceCast:
410 case Instruction::GetElementPtr:
411 return {
Op.getOperand(0)};
412 case Instruction::Select:
413 return {
Op.getOperand(1),
Op.getOperand(2)};
414 case Instruction::Call: {
416 assert(
II.getIntrinsicID() == Intrinsic::ptrmask &&
417 "unexpected intrinsic call");
418 return {
II.getArgOperand(0)};
420 case Instruction::IntToPtr: {
423 return {P2I->getOperand(0)};
425 assert(isSafeToCastIntToPtrAddrSpace(&
Op));
426 return {getIntToPtrPointerOperand(&
Op)};
440 switch (
Op->getOpcode()) {
441 case Instruction::Xor:
442 case Instruction::Or:
444 case Instruction::And:
452InferAddressSpacesImpl::getIntToPtrPointerOperand(
const Operator *I2P)
const {
459 if (
auto *OldPtr = PtrIntCastPairs.
lookup(I2P))
464 if (!
match(LogicalOp,
475 if (PreservedPtrMask.
isZero())
477 APInt ChangedPtrBits =
486 if (ChangedPtrBits.
isSubsetOf(PreservedPtrMask))
492void InferAddressSpacesImpl::collectIntToPtrPointerOperand() {
499 PtrIntCastPairs.
insert({&
I, OldPtr});
503bool InferAddressSpacesImpl::rewriteIntrinsicOperands(IntrinsicInst *
II,
506 Module *
M =
II->getParent()->getParent()->getParent();
509 case Intrinsic::objectsize:
510 case Intrinsic::masked_load: {
511 Type *DestTy =
II->getType();
515 II->setArgOperand(0, NewV);
516 II->setCalledFunction(NewDecl);
519 case Intrinsic::ptrmask:
522 case Intrinsic::masked_gather: {
523 Type *RetTy =
II->getType();
527 II->setArgOperand(0, NewV);
528 II->setCalledFunction(NewDecl);
531 case Intrinsic::masked_store:
532 case Intrinsic::masked_scatter: {
533 Type *ValueTy =
II->getOperand(0)->getType();
536 M,
II->getIntrinsicID(), {ValueTy, NewPtrTy});
537 II->setArgOperand(1, NewV);
538 II->setCalledFunction(NewDecl);
541 case Intrinsic::prefetch:
542 case Intrinsic::is_constant: {
544 M,
II->getIntrinsicID(), {NewV->getType()});
545 II->setArgOperand(0, NewV);
546 II->setCalledFunction(NewDecl);
549 case Intrinsic::fake_use: {
550 II->replaceUsesOfWith(OldV, NewV);
553 case Intrinsic::lifetime_start:
554 case Intrinsic::lifetime_end: {
558 M,
II->getIntrinsicID(), {NewV->getType()});
559 II->setArgOperand(0, NewV);
560 II->setCalledFunction(NewDecl);
568 II->replaceAllUsesWith(Rewrite);
574void InferAddressSpacesImpl::collectRewritableIntrinsicOperands(
575 IntrinsicInst *
II, PostorderStackTy &PostorderStack,
576 DenseSet<Value *> &Visited)
const {
577 auto IID =
II->getIntrinsicID();
579 case Intrinsic::ptrmask:
580 case Intrinsic::objectsize:
581 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(0),
582 PostorderStack, Visited);
584 case Intrinsic::is_constant: {
585 Value *Ptr =
II->getArgOperand(0);
587 appendsFlatAddressExpressionToPostorderStack(Ptr, PostorderStack,
593 case Intrinsic::masked_load:
594 case Intrinsic::masked_gather:
595 case Intrinsic::prefetch:
596 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(0),
597 PostorderStack, Visited);
599 case Intrinsic::masked_store:
600 case Intrinsic::masked_scatter:
601 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(1),
602 PostorderStack, Visited);
604 case Intrinsic::fake_use: {
606 if (
Op->getType()->isPtrOrPtrVectorTy()) {
607 appendsFlatAddressExpressionToPostorderStack(
Op, PostorderStack,
614 case Intrinsic::lifetime_start:
615 case Intrinsic::lifetime_end: {
616 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(0),
617 PostorderStack, Visited);
621 SmallVector<int, 2> OpIndexes;
623 for (
int Idx : OpIndexes) {
624 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(Idx),
625 PostorderStack, Visited);
635void InferAddressSpacesImpl::appendsFlatAddressExpressionToPostorderStack(
636 Value *V, PostorderStackTy &PostorderStack,
637 DenseSet<Value *> &Visited)
const {
638 assert(
V->getType()->isPtrOrPtrVectorTy());
644 if (isAddressExpression(*CE, *
DL,
TTI) && Visited.
insert(CE).second)
645 PostorderStack.emplace_back(CE,
false);
650 if (
V->getType()->getPointerAddressSpace() == FlatAddrSpace &&
651 isAddressExpression(*V, *
DL,
TTI)) {
652 if (Visited.
insert(V).second) {
653 PostorderStack.emplace_back(V,
false);
656 for (
auto &O :
Op->operands())
658 if (isAddressExpression(*CE, *
DL,
TTI) && Visited.
insert(CE).second)
659 PostorderStack.emplace_back(CE,
false);
666std::vector<WeakTrackingVH>
667InferAddressSpacesImpl::collectFlatAddressExpressions(
Function &
F)
const {
670 PostorderStackTy PostorderStack;
672 DenseSet<Value *> Visited;
674 auto PushPtrOperand = [&](
Value *Ptr) {
675 appendsFlatAddressExpressionToPostorderStack(Ptr, PostorderStack, Visited);
683 PushPtrOperand(
GEP->getPointerOperand());
685 PushPtrOperand(LI->getPointerOperand());
687 PushPtrOperand(
SI->getPointerOperand());
689 PushPtrOperand(RMW->getPointerOperand());
691 PushPtrOperand(CmpX->getPointerOperand());
694 PushPtrOperand(
MI->getRawDest());
698 PushPtrOperand(MTI->getRawSource());
700 collectRewritableIntrinsicOperands(
II, PostorderStack, Visited);
702 if (
Cmp->getOperand(0)->getType()->isPtrOrPtrVectorTy()) {
703 PushPtrOperand(
Cmp->getOperand(0));
704 PushPtrOperand(
Cmp->getOperand(1));
707 PushPtrOperand(ASC->getPointerOperand());
714 if (
auto *RV = RI->getReturnValue();
715 RV && RV->getType()->isPtrOrPtrVectorTy())
720 std::vector<WeakTrackingVH> Postorder;
721 while (!PostorderStack.empty()) {
722 Value *TopVal = PostorderStack.back().getPointer();
725 if (PostorderStack.back().getInt()) {
727 Postorder.push_back(TopVal);
728 PostorderStack.pop_back();
732 PostorderStack.back().setInt(
true);
735 for (
Value *PtrOperand : getPointerOperands(*TopVal, *
DL,
TTI)) {
736 appendsFlatAddressExpressionToPostorderStack(PtrOperand, PostorderStack,
748 auto InsertBefore = [NewI](
auto It) {
758 auto InsertI =
F->getEntryBlock().getFirstNonPHIIt();
759 return InsertBefore(InsertI);
769 auto InsertI = OpInst->
getParent()->getFirstNonPHIIt();
770 return InsertBefore(InsertI);
783 const Use &OperandUse,
unsigned NewAddrSpace,
785 const PredicatedAddrSpaceMapTy &PredicatedAS,
795 if (
Value *NewOperand = ValueWithNewAddrSpace.
lookup(Operand)) {
796 Operand = NewOperand;
797 }
else if (!PredicatedAS.contains(std::make_pair(Inst, Operand))) {
798 assert(PoisonUsesToFix &&
"missing inferred operand replacement");
803 if (Operand->
getType() == NewPtrTy)
817Value *InferAddressSpacesImpl::clonePtrMaskWithNewAddressSpace(
818 IntrinsicInst *
I,
unsigned NewAddrSpace,
820 const PredicatedAddrSpaceMapTy &PredicatedAS,
821 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const {
822 const Use &PtrOpUse =
I->getArgOperandUse(0);
824 Value *MaskOp =
I->getArgOperand(1);
827 KnownBits OldPtrBits{
DL->getPointerSizeInBits(OldAddrSpace)};
828 KnownBits NewPtrBits{
DL->getPointerSizeInBits(NewAddrSpace)};
830 std::tie(OldPtrBits, NewPtrBits) =
845 OldPtrBits.
One |= ~OldPtrBits.Zero;
847 KnownBits ClearedBits =
KnownBits::sub(OldPtrBits, OldPtrBits & MaskBits);
852 std::optional<BasicBlock::iterator> InsertPoint =
853 I->getInsertionPointAfterDef();
854 assert(InsertPoint &&
"insertion after ptrmask should be possible");
857 new AddrSpaceCastInst(
I, NewPtrType,
"", *InsertPoint);
859 return AddrSpaceCast;
866 MaskOp =
B.CreateTrunc(MaskOp, MaskTy);
869 PtrOpUse, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS,
871 return B.CreateIntrinsic(Intrinsic::ptrmask, {NewPtr->
getType(), MaskTy},
884Value *InferAddressSpacesImpl::cloneInstructionWithNewAddressSpace(
885 Instruction *
I,
unsigned NewAddrSpace,
887 const PredicatedAddrSpaceMapTy &PredicatedAS,
888 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const {
891 if (
I->getOpcode() == Instruction::AddrSpaceCast) {
892 Value *Src =
I->getOperand(0);
896 assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace);
903 assert(
II->getIntrinsicID() == Intrinsic::ptrmask);
904 return clonePtrMaskWithNewAddressSpace(
905 II, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, PoisonUsesToFix);
913 auto *NewI =
new AddrSpaceCastInst(
I, NewPtrTy);
914 NewI->insertAfter(
I->getIterator());
915 NewI->setDebugLoc(
I->getDebugLoc());
920 SmallVector<Value *, 4> NewPointerOperands;
921 for (
const Use &OperandUse :
I->operands()) {
922 if (!OperandUse.get()->getType()->isPtrOrPtrVectorTy())
926 OperandUse, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS,
930 switch (
I->getOpcode()) {
931 case Instruction::BitCast:
932 return new BitCastInst(NewPointerOperands[0], NewPtrType);
933 case Instruction::PHI: {
934 assert(
I->getType()->isPtrOrPtrVectorTy());
937 for (
unsigned Index = 0;
Index <
PHI->getNumIncomingValues(); ++
Index) {
940 PHI->getIncomingBlock(Index));
944 case Instruction::GetElementPtr: {
947 GEP->getSourceElementType(), NewPointerOperands[0],
948 SmallVector<Value *, 4>(
GEP->indices()));
952 case Instruction::Select:
953 assert(
I->getType()->isPtrOrPtrVectorTy());
955 NewPointerOperands[2],
"",
nullptr,
I);
956 case Instruction::IntToPtr: {
959 if (Src->getType() == NewPtrType)
965 return new AddrSpaceCastInst(Src, NewPtrType);
968 AddrSpaceCastInst *AsCast =
new AddrSpaceCastInst(
I, NewPtrType);
980Value *InferAddressSpacesImpl::cloneConstantExprWithNewAddressSpace(
981 ConstantExpr *CE,
unsigned NewAddrSpace,
983 const TargetTransformInfo *
TTI)
const {
985 CE->getType()->isPtrOrPtrVectorTy()
989 if (
CE->getOpcode() == Instruction::AddrSpaceCast) {
993 assert(CE->getOperand(0)->getType()->getPointerAddressSpace() ==
995 return CE->getOperand(0);
998 if (
CE->getOpcode() == Instruction::BitCast) {
999 if (Value *NewOperand = ValueWithNewAddrSpace.lookup(CE->getOperand(0)))
1000 return ConstantExpr::getBitCast(cast<Constant>(NewOperand), TargetType);
1001 return ConstantExpr::getAddrSpaceCast(CE, TargetType);
1004 if (
CE->getOpcode() == Instruction::IntToPtr) {
1005 if (isNoopPtrIntCastPair(cast<Operator>(CE), *DL, TTI)) {
1006 Constant *Src = cast<ConstantExpr>(CE->getOperand(0))->getOperand(0);
1007 assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace);
1016 SmallVector<Constant *, 4> NewOperands;
1017 for (
unsigned Index = 0;
Index <
CE->getNumOperands(); ++
Index) {
1024 if (
Value *NewOperand = ValueWithNewAddrSpace.
lookup(Operand)) {
1030 if (
Value *NewOperand = cloneConstantExprWithNewAddressSpace(
1031 CExpr, NewAddrSpace, ValueWithNewAddrSpace,
DL,
TTI)) {
1045 if (
CE->getOpcode() == Instruction::GetElementPtr) {
1048 return CE->getWithOperands(NewOperands, TargetType,
false,
1052 return CE->getWithOperands(NewOperands, TargetType);
1060Value *InferAddressSpacesImpl::cloneValueWithNewAddressSpace(
1061 Value *V,
unsigned NewAddrSpace,
1063 const PredicatedAddrSpaceMapTy &PredicatedAS,
1064 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const {
1066 assert(
V->getType()->getPointerAddressSpace() == FlatAddrSpace &&
1067 isAddressExpression(*V, *
DL,
TTI));
1075 Type *NewPtrTy = PointerType::get(Arg->getContext(), NewAddrSpace);
1076 auto *NewI =
new AddrSpaceCastInst(Arg, NewPtrTy);
1077 NewI->insertBefore(Insert);
1082 Value *NewV = cloneInstructionWithNewAddressSpace(
1083 I, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, PoisonUsesToFix);
1085 if (NewI->getParent() ==
nullptr) {
1086 NewI->insertBefore(
I->getIterator());
1088 NewI->setDebugLoc(
I->getDebugLoc());
1094 return cloneConstantExprWithNewAddressSpace(
1100unsigned InferAddressSpacesImpl::joinAddressSpaces(
unsigned AS1,
1101 unsigned AS2)
const {
1105 if (AS1 == FlatAddrSpace || AS2 == FlatAddrSpace)
1116bool InferAddressSpacesImpl::run(
Function &CurFn) {
1118 DL = &
F->getDataLayout();
1119 PtrIntCastPairs.
clear();
1121 if (AssumeDefaultIsFlatAddressSpace)
1130 collectIntToPtrPointerOperand();
1132 std::vector<WeakTrackingVH> Postorder = collectFlatAddressExpressions(*
F);
1136 ValueToAddrSpaceMapTy InferredAddrSpace;
1137 PredicatedAddrSpaceMapTy PredicatedAS;
1138 inferAddressSpaces(Postorder, InferredAddrSpace, PredicatedAS);
1142 return rewriteWithNewAddressSpaces(Postorder, InferredAddrSpace,
1146void InferAddressSpacesImpl::enqueueUsers(
1147 Value &V,
const ValueToAddrSpaceMapTy &InferredAddrSpace,
1148 SetVector<Value *> &Worklist)
const {
1149 for (
Value *User :
V.users()) {
1151 if (Worklist.
count(User))
1154 ValueToAddrSpaceMapTy::const_iterator Pos = InferredAddrSpace.find(User);
1157 if (Pos == InferredAddrSpace.end())
1163 if (Pos->second == FlatAddrSpace)
1170void InferAddressSpacesImpl::runToFixPoint(
1171 SetVector<Value *> &Worklist, ValueToAddrSpaceMapTy &InferredAddrSpace,
1172 PredicatedAddrSpaceMapTy &PredicatedAS)
const {
1173 while (!Worklist.
empty()) {
1178 if (!updateAddressSpace(*V, InferredAddrSpace, PredicatedAS))
1181 enqueueUsers(*V, InferredAddrSpace, Worklist);
1187void InferAddressSpacesImpl::inferAddressSpaces(
1189 ValueToAddrSpaceMapTy &InferredAddrSpace,
1190 PredicatedAddrSpaceMapTy &PredicatedAS)
const {
1193 for (
Value *V : Postorder)
1196 runToFixPoint(Worklist, InferredAddrSpace, PredicatedAS);
1202 SmallVector<Value *, 4> Lowered;
1203 for (
Value *V : Postorder) {
1204 ValueToAddrSpaceMapTy::iterator
I = InferredAddrSpace.find(V);
1211 for (
Value *V : Lowered)
1212 enqueueUsers(*V, InferredAddrSpace, Worklist);
1214 runToFixPoint(Worklist, InferredAddrSpace, PredicatedAS);
1218InferAddressSpacesImpl::getPredicatedAddrSpace(
const Value &Ptr,
1219 const Value *UserCtx)
const {
1242bool InferAddressSpacesImpl::updateAddressSpace(
1243 const Value &V, ValueToAddrSpaceMapTy &InferredAddrSpace,
1244 PredicatedAddrSpaceMapTy &PredicatedAS)
const {
1245 assert(InferredAddrSpace.count(&V));
1247 LLVM_DEBUG(
dbgs() <<
"Updating the address space of\n " << V <<
'\n');
1263 SmallVector<Value *, 2> PtrOps = getPointerOperands(V, *
DL,
TTI);
1264 for (
Value *PtrOperand : PtrOps) {
1265 auto I = InferredAddrSpace.find(PtrOperand);
1267 if (
I == InferredAddrSpace.end()) {
1268 OperandAS = PtrOperand->getType()->getPointerAddressSpace();
1275 if (OperandAS == FlatAddrSpace) {
1277 unsigned AS = getPredicatedAddrSpace(*PtrOperand, &V);
1280 <<
" deduce operand AS from the predicate addrspace "
1284 PredicatedAS[std::make_pair(&V, PtrOperand)] = OperandAS;
1288 OperandAS =
I->second;
1291 NewAS = joinAddressSpaces(NewAS, OperandAS);
1292 if (NewAS == FlatAddrSpace)
1297 if (
any_of(ConstantPtrOps, [=](Constant *
C) {
1298 return !isSafeToCastConstAddrSpace(
C, NewAS);
1300 NewAS = FlatAddrSpace;
1305 PtrOps.size() == ConstantPtrOps.
size())
1309 unsigned OldAS = InferredAddrSpace.lookup(&V);
1310 assert(OldAS != FlatAddrSpace);
1317 InferredAddrSpace[&
V] = NewAS;
1326 if (U.get() == OldVal) {
1334template <
typename InstrType>
1336 InstrType *MemInstr,
unsigned AddrSpace,
1338 if (!MemInstr->isVolatile() ||
TTI.hasVolatileVariant(MemInstr, AddrSpace)) {
1354 User *Inst,
unsigned AddrSpace,
1378 B.CreateMemSet(NewV, MSI->getValue(), MSI->getLength(), MSI->getDestAlign(),
1380 MI->getAAMetadata());
1382 Value *Src = MTI->getRawSource();
1383 Value *Dest = MTI->getRawDest();
1393 if (MCI->isForceInlined())
1394 B.CreateMemCpyInline(Dest, MTI->getDestAlign(), Src,
1395 MTI->getSourceAlign(), MTI->getLength(),
1397 MI->getAAMetadata());
1399 B.CreateMemCpy(Dest, MTI->getDestAlign(), Src, MTI->getSourceAlign(),
1402 MI->getAAMetadata());
1405 B.CreateMemMove(Dest, MTI->getDestAlign(), Src, MTI->getSourceAlign(),
1408 MI->getAAMetadata());
1413 MI->eraseFromParent();
1419bool InferAddressSpacesImpl::isSafeToCastConstAddrSpace(Constant *
C,
1420 unsigned NewAS)
const {
1423 unsigned SrcAS =
C->getType()->getPointerAddressSpace();
1428 if (SrcAS != FlatAddrSpace && NewAS != FlatAddrSpace)
1437 if (
Op->getOpcode() == Instruction::AddrSpaceCast)
1441 if (
Op->getOpcode() == Instruction::IntToPtr &&
1442 Op->getType()->getPointerAddressSpace() == FlatAddrSpace)
1451 User *CurUser =
I->getUser();
1454 while (
I != End &&
I->getUser() == CurUser)
1460void InferAddressSpacesImpl::performPointerReplacement(
1462 SmallVectorImpl<Instruction *> &DeadInstructions)
const {
1464 User *CurUser =
U.getUser();
1466 unsigned AddrSpace =
V->getType()->getPointerAddressSpace();
1471 if (CurUser == NewV)
1475 if (!CurUserI || CurUserI->getFunction() !=
F)
1485 if (rewriteIntrinsicOperands(
II, V, NewV))
1497 int SrcIdx =
U.getOperandNo();
1498 int OtherIdx = (SrcIdx == 0) ? 1 : 0;
1499 Value *OtherSrc =
Cmp->getOperand(OtherIdx);
1501 if (
Value *OtherNewV = ValueWithNewAddrSpace.
lookup(OtherSrc)) {
1502 if (OtherNewV->getType()->getPointerAddressSpace() == NewAS) {
1503 Cmp->setOperand(OtherIdx, OtherNewV);
1504 Cmp->setOperand(SrcIdx, NewV);
1511 if (isSafeToCastConstAddrSpace(KOtherSrc, NewAS)) {
1512 Cmp->setOperand(SrcIdx, NewV);
1522 if (ASC->getDestAddressSpace() == NewAS) {
1523 ASC->replaceAllUsesWith(NewV);
1538 InsertPos = std::next(NewVInst->getIterator());
1546 V,
new AddrSpaceCastInst(NewV,
V->getType(),
"", InsertPos));
1548 CurUserI->replaceUsesOfWith(
1553bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(
1555 const ValueToAddrSpaceMapTy &InferredAddrSpace,
1556 const PredicatedAddrSpaceMapTy &PredicatedAS)
const {
1563 for (
Value *V : Postorder) {
1564 unsigned NewAddrSpace = InferredAddrSpace.lookup(V);
1571 if (
V->getType()->getPointerAddressSpace() != NewAddrSpace) {
1573 cloneValueWithNewAddressSpace(V, NewAddrSpace, ValueWithNewAddrSpace,
1574 PredicatedAS, &PoisonUsesToFix);
1576 ValueWithNewAddrSpace[
V] =
New;
1580 if (ValueWithNewAddrSpace.
empty())
1584 for (
const Use *PoisonUse : PoisonUsesToFix) {
1585 User *
V = PoisonUse->getUser();
1590 unsigned OperandNo = PoisonUse->getOperandNo();
1595 *PoisonUse, NewAS, ValueWithNewAddrSpace, PredicatedAS,
nullptr);
1599 SmallVector<Instruction *, 16> DeadInstructions;
1604 for (
const WeakTrackingVH &WVH : Postorder) {
1605 assert(WVH &&
"value was unexpectedly deleted");
1608 if (NewV ==
nullptr)
1611 LLVM_DEBUG(
dbgs() <<
"Replacing the uses of " << *V <<
"\n with\n "
1623 if (
I->getFunction() ==
F)
1626 WorkList.
append(
U->user_begin(),
U->user_end());
1629 if (!WorkList.
empty()) {
1631 DenseSet<User *> Visited{WorkList.
begin(), WorkList.
end()};
1632 while (!WorkList.
empty()) {
1635 if (
I->getFunction() ==
F)
1636 VMapper.remapInstruction(*
I);
1639 for (User *U2 :
U->users())
1640 if (Visited.
insert(U2).second)
1648 Value::use_iterator
I,
E,
Next;
1649 for (
I =
V->use_begin(),
E =
V->use_end();
I !=
E;) {
1656 performPointerReplacement(V, NewV, U, ValueWithNewAddrSpace,
1660 if (
V->use_empty()) {
1669 auto DeadInstructionHandles =
1676bool InferAddressSpaces::runOnFunction(
Function &
F) {
1677 if (skipFunction(
F))
1680 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
1681 DominatorTree *DT = DTWP ? &DTWP->getDomTree() :
nullptr;
1682 return InferAddressSpacesImpl(
1683 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F), DT,
1684 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F),
1685 FlatAddrSpace,
false)
1694 bool AssumeDefaultIsFlatAddressSpace)
1696 AssumeDefaultIsFlatAddressSpace(AssumeDefaultIsFlatAddressSpace) {}
1698 unsigned AddressSpace,
bool AssumeDefaultIsFlatAddressSpace)
1700 AssumeDefaultIsFlatAddressSpace(AssumeDefaultIsFlatAddressSpace) {}
1708 AssumeDefaultIsFlatAddressSpace)
1720 static_cast<PassInfoMixin<InferAddressSpacesPass> *
>(
this)->
printPipeline(
1721 OS, MapClassName2PassName);
1722 if (AssumeDefaultIsFlatAddressSpace)
1723 OS <<
"<assume-default-is-flat-addrspace>";
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_UNLIKELY(EXPR)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static bool runOnFunction(Function &F, bool PostInlining)
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
static bool replaceIfSimplePointerUse(const TargetTransformInfo &TTI, User *Inst, unsigned AddrSpace, Value *OldV, Value *NewV)
If OldV is used as the pointer operand of a compatible memory operation Inst, replaces the pointer op...
static bool replaceOperandIfSame(Instruction *Inst, unsigned OpIdx, Value *OldVal, Value *NewVal)
Replace operand OpIdx in Inst, if the value is the same as OldVal with NewVal.
static bool isNoopPtrIntCastPair(const Operator *I2P, const DataLayout &DL, const TargetTransformInfo *TTI)
static Value * phiNodeOperandWithNewAddressSpace(AddrSpaceCastInst *NewI, Value *Operand)
static bool handleMemIntrinsicPtrUse(MemIntrinsic *MI, Value *OldV, Value *NewV)
Update memory intrinsic uses that require more complex processing than simple memory instructions.
static Value * operandWithNewAddressSpaceOrCreatePoison(const Use &OperandUse, unsigned NewAddrSpace, const ValueToValueMapTy &ValueWithNewAddrSpace, const PredicatedAddrSpaceMapTy &PredicatedAS, SmallVectorImpl< const Use * > *PoisonUsesToFix)
static Value::use_iterator skipToNextUser(Value::use_iterator I, Value::use_iterator End)
Infer address static false Type * getPtrOrVecOfPtrsWithNewAS(Type *Ty, unsigned NewAddrSpace)
static APInt computeMaxChangedPtrBits(const Operator *Op, const Value *Mask, const DataLayout &DL, AssumptionCache *AC, const DominatorTree *DT)
static bool replaceSimplePointerUse(const TargetTransformInfo &TTI, InstrType *MemInstr, unsigned AddrSpace, Value *OldV, Value *NewV)
static const unsigned UninitializedAddressSpace
Machine Check Debug Module
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
This class represents a conversion between pointers from one address space to another.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
A cache of @llvm.assume calls within a function.
MutableArrayRef< ResultElem > assumptionsFor(const Value *V)
Access the list of assumptions which affect this value.
InstListType::iterator iterator
Instruction iterators...
Represents analyses that only rely on functions' control flow.
Value * getArgOperand(unsigned i) const
static LLVM_ABI bool isNoopCast(Instruction::CastOps Opcode, Type *SrcTy, Type *DstTy, const DataLayout &DL)
A no-op cast is one that can be effected without changing any bits.
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
LLVM_ABI void setIsInBounds(bool b=true)
Set or clear the inbounds flag on this GEP instruction.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InferAddressSpacesPass(bool AssumeDefaultIsFlatAddressSpace=false)
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
This is the common base class for memset/memcpy/memmove.
This is a utility class that provides an abstraction for the common functionality between Instruction...
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static unsigned getOperandNumForIncomingValue(unsigned i)
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetTransformInfo.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
LLVM_ABI Type * getWithNewBitWidth(unsigned NewBitWidth) const
Given an integer or vector type, change the lane bitwidth to NewBitwidth, whilst keeping the old numb...
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
const Use & getOperandUse(unsigned i) const
void setOperand(unsigned i, Value *Val)
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * getOperand(unsigned i) const
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
use_iterator_impl< Use > use_iterator
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
std::pair< iterator, bool > insert(const ValueT &V)
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
BinOpPred_match< LHS, RHS, is_bitwiselogic_op, true > m_c_BitwiseLogic(const LHS &L, const RHS &R)
Matches bitwise logic operations in either order.
CastOperator_match< OpTy, Instruction::PtrToInt > m_PtrToInt(const OpTy &Op)
Matches PtrToInt.
@ CE
Windows NT (Windows on ARM)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, const DominatorTree *DT=nullptr, bool AllowEphemerals=false)
Return true if it is valid to use the assumptions provided by an assume intrinsic,...
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
@ Known
Known to have no common set bits.
LLVM_ABI void initializeInferAddressSpacesPass(PassRegistry &)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr from_range_t from_range
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto cast_or_null(const Y &Val)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
@ RF_IgnoreMissingLocals
If this flag is set, the remapper ignores missing function-local entries (Argument,...
@ RF_NoModuleLevelChanges
If this flag is set, the remapper knows that only local values within a function (such as an instruct...
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI FunctionPass * createInferAddressSpacesPass(unsigned AddressSpace=~0u)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
SmallVector< Out, Size > to_vector_of(R &&Range)
unsigned getBitWidth() const
Get the bit width of this value.
unsigned countMaxActiveBits() const
Returns the maximum number of bits needed to represent all possible unsigned values with these known ...
static KnownBits sub(const KnownBits &LHS, const KnownBits &RHS, bool NSW=false, bool NUW=false)
Compute knownbits resulting from subtraction of LHS and RHS.