139#define DEBUG_TYPE "infer-address-spaces"
146 cl::desc(
"The default address space is assumed as the flat address space. "
147 "This is mainly for test purpose."));
150 std::numeric_limits<unsigned>::max();
161using PredicatedAddrSpaceMapTy =
166 unsigned FlatAddrSpace = 0;
175 InferAddressSpaces(
unsigned AS) : FunctionPass(ID), FlatAddrSpace(AS) {
179 void getAnalysisUsage(AnalysisUsage &AU)
const override {
188class InferAddressSpacesImpl {
191 const DominatorTree *DT =
nullptr;
192 const TargetTransformInfo *TTI =
nullptr;
193 const DataLayout *DL =
nullptr;
197 unsigned FlatAddrSpace = 0;
198 DenseMap<const Value *, Value *> PtrIntCastPairs;
203 Value *getIntToPtrPointerOperand(
const Operator *I2P)
const;
208 void collectIntToPtrPointerOperand();
212 bool isSafeToCastIntToPtrAddrSpace(
const Operator *I2P)
const {
213 return PtrIntCastPairs.contains(I2P);
215 bool isAddressExpression(
const Value &V,
const DataLayout &DL,
216 const TargetTransformInfo *TTI)
const;
217 Value *cloneConstantExprWithNewAddressSpace(
218 ConstantExpr *CE,
unsigned NewAddrSpace,
220 const TargetTransformInfo *TTI)
const;
222 SmallVector<Value *, 2>
223 getPointerOperands(
const Value &V,
const DataLayout &DL,
224 const TargetTransformInfo *TTI)
const;
228 bool updateAddressSpace(
const Value &V,
229 ValueToAddrSpaceMapTy &InferredAddrSpace,
230 PredicatedAddrSpaceMapTy &PredicatedAS)
const;
235 ValueToAddrSpaceMapTy &InferredAddrSpace,
236 PredicatedAddrSpaceMapTy &PredicatedAS)
const;
238 bool isSafeToCastConstAddrSpace(Constant *
C,
unsigned NewAS)
const;
240 Value *clonePtrMaskWithNewAddressSpace(
241 IntrinsicInst *
I,
unsigned NewAddrSpace,
243 const PredicatedAddrSpaceMapTy &PredicatedAS,
244 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const;
246 Value *cloneInstructionWithNewAddressSpace(
247 Instruction *
I,
unsigned NewAddrSpace,
249 const PredicatedAddrSpaceMapTy &PredicatedAS,
250 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const;
252 void performPointerReplacement(
254 SmallVectorImpl<Instruction *> &DeadInstructions)
const;
259 bool rewriteWithNewAddressSpaces(
261 const ValueToAddrSpaceMapTy &InferredAddrSpace,
262 const PredicatedAddrSpaceMapTy &PredicatedAS)
const;
264 void appendsFlatAddressExpressionToPostorderStack(
265 Value *V, PostorderStackTy &PostorderStack,
266 DenseSet<Value *> &Visited)
const;
268 bool rewriteIntrinsicOperands(IntrinsicInst *
II,
Value *OldV,
270 void collectRewritableIntrinsicOperands(IntrinsicInst *
II,
271 PostorderStackTy &PostorderStack,
272 DenseSet<Value *> &Visited)
const;
274 std::vector<WeakTrackingVH> collectFlatAddressExpressions(Function &F)
const;
276 Value *cloneValueWithNewAddressSpace(
277 Value *V,
unsigned NewAddrSpace,
279 const PredicatedAddrSpaceMapTy &PredicatedAS,
280 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const;
281 unsigned joinAddressSpaces(
unsigned AS1,
unsigned AS2)
const;
283 unsigned getPredicatedAddrSpace(
const Value &PtrV,
284 const Value *UserCtx)
const;
287 InferAddressSpacesImpl(AssumptionCache &AC,
const DominatorTree *DT,
288 const TargetTransformInfo *TTI,
unsigned FlatAddrSpace)
289 : AC(AC), DT(DT), TTI(TTI), FlatAddrSpace(FlatAddrSpace) {}
290 bool run(Function &F);
295char InferAddressSpaces::ID = 0;
305 assert(Ty->isPtrOrPtrVectorTy());
307 return Ty->getWithNewType(NPT);
317 if (!P2I || P2I->getOpcode() != Instruction::PtrToInt)
333 unsigned P2IOp0AS = P2I->getOperand(0)->getType()->getPointerAddressSpace();
339 P2I->getOperand(0)->getType(), P2I->getType(),
341 (P2IOp0AS == I2PAS ||
TTI->isNoopAddrSpaceCast(P2IOp0AS, I2PAS));
348bool InferAddressSpacesImpl::isAddressExpression(
353 return Arg->getType()->isPointerTy() &&
360 switch (
Op->getOpcode()) {
361 case Instruction::PHI:
362 assert(
Op->getType()->isPtrOrPtrVectorTy());
364 case Instruction::BitCast:
365 case Instruction::AddrSpaceCast:
366 case Instruction::GetElementPtr:
368 case Instruction::Select:
369 return Op->getType()->isPtrOrPtrVectorTy();
370 case Instruction::Call: {
372 return II &&
II->getIntrinsicID() == Intrinsic::ptrmask;
374 case Instruction::IntToPtr:
376 isSafeToCastIntToPtrAddrSpace(
Op);
386SmallVector<Value *, 2> InferAddressSpacesImpl::getPointerOperands(
387 const Value &V,
const DataLayout &
DL,
388 const TargetTransformInfo *
TTI)
const {
393 switch (
Op.getOpcode()) {
394 case Instruction::PHI: {
396 return {IncomingValues.begin(), IncomingValues.end()};
398 case Instruction::BitCast:
399 case Instruction::AddrSpaceCast:
400 case Instruction::GetElementPtr:
401 return {
Op.getOperand(0)};
402 case Instruction::Select:
403 return {
Op.getOperand(1),
Op.getOperand(2)};
404 case Instruction::Call: {
406 assert(
II.getIntrinsicID() == Intrinsic::ptrmask &&
407 "unexpected intrinsic call");
408 return {
II.getArgOperand(0)};
410 case Instruction::IntToPtr: {
413 return {P2I->getOperand(0)};
415 assert(isSafeToCastIntToPtrAddrSpace(&
Op));
416 return {getIntToPtrPointerOperand(&
Op)};
430 switch (
Op->getOpcode()) {
431 case Instruction::Xor:
432 case Instruction::Or:
434 case Instruction::And:
442InferAddressSpacesImpl::getIntToPtrPointerOperand(
const Operator *I2P)
const {
449 if (
auto *OldPtr = PtrIntCastPairs.
lookup(I2P))
454 if (!
match(LogicalOp,
465 if (PreservedPtrMask.
isZero())
467 APInt ChangedPtrBits =
476 if (ChangedPtrBits.
isSubsetOf(PreservedPtrMask))
482void InferAddressSpacesImpl::collectIntToPtrPointerOperand() {
489 PtrIntCastPairs.
insert({&
I, OldPtr});
493bool InferAddressSpacesImpl::rewriteIntrinsicOperands(IntrinsicInst *
II,
496 Module *
M =
II->getParent()->getParent()->getParent();
499 case Intrinsic::objectsize:
500 case Intrinsic::masked_load: {
501 Type *DestTy =
II->getType();
505 II->setArgOperand(0, NewV);
506 II->setCalledFunction(NewDecl);
509 case Intrinsic::ptrmask:
512 case Intrinsic::masked_gather: {
513 Type *RetTy =
II->getType();
517 II->setArgOperand(0, NewV);
518 II->setCalledFunction(NewDecl);
521 case Intrinsic::masked_store:
522 case Intrinsic::masked_scatter: {
523 Type *ValueTy =
II->getOperand(0)->getType();
526 M,
II->getIntrinsicID(), {ValueTy, NewPtrTy});
527 II->setArgOperand(1, NewV);
528 II->setCalledFunction(NewDecl);
531 case Intrinsic::prefetch:
532 case Intrinsic::is_constant: {
534 M,
II->getIntrinsicID(), {NewV->getType()});
535 II->setArgOperand(0, NewV);
536 II->setCalledFunction(NewDecl);
539 case Intrinsic::fake_use: {
540 II->replaceUsesOfWith(OldV, NewV);
543 case Intrinsic::lifetime_start:
544 case Intrinsic::lifetime_end: {
548 M,
II->getIntrinsicID(), {NewV->getType()});
549 II->setArgOperand(0, NewV);
550 II->setCalledFunction(NewDecl);
558 II->replaceAllUsesWith(Rewrite);
564void InferAddressSpacesImpl::collectRewritableIntrinsicOperands(
565 IntrinsicInst *
II, PostorderStackTy &PostorderStack,
566 DenseSet<Value *> &Visited)
const {
567 auto IID =
II->getIntrinsicID();
569 case Intrinsic::ptrmask:
570 case Intrinsic::objectsize:
571 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(0),
572 PostorderStack, Visited);
574 case Intrinsic::is_constant: {
575 Value *Ptr =
II->getArgOperand(0);
577 appendsFlatAddressExpressionToPostorderStack(Ptr, PostorderStack,
583 case Intrinsic::masked_load:
584 case Intrinsic::masked_gather:
585 case Intrinsic::prefetch:
586 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(0),
587 PostorderStack, Visited);
589 case Intrinsic::masked_store:
590 case Intrinsic::masked_scatter:
591 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(1),
592 PostorderStack, Visited);
594 case Intrinsic::fake_use: {
596 if (
Op->getType()->isPtrOrPtrVectorTy()) {
597 appendsFlatAddressExpressionToPostorderStack(
Op, PostorderStack,
604 case Intrinsic::lifetime_start:
605 case Intrinsic::lifetime_end: {
606 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(0),
607 PostorderStack, Visited);
611 SmallVector<int, 2> OpIndexes;
613 for (
int Idx : OpIndexes) {
614 appendsFlatAddressExpressionToPostorderStack(
II->getArgOperand(Idx),
615 PostorderStack, Visited);
625void InferAddressSpacesImpl::appendsFlatAddressExpressionToPostorderStack(
626 Value *V, PostorderStackTy &PostorderStack,
627 DenseSet<Value *> &Visited)
const {
628 assert(
V->getType()->isPtrOrPtrVectorTy());
634 if (isAddressExpression(*CE, *
DL,
TTI) && Visited.
insert(CE).second)
635 PostorderStack.emplace_back(CE,
false);
640 if (
V->getType()->getPointerAddressSpace() == FlatAddrSpace &&
641 isAddressExpression(*V, *
DL,
TTI)) {
642 if (Visited.
insert(V).second) {
643 PostorderStack.emplace_back(V,
false);
646 for (
auto &O :
Op->operands())
648 if (isAddressExpression(*CE, *
DL,
TTI) && Visited.
insert(CE).second)
649 PostorderStack.emplace_back(CE,
false);
656std::vector<WeakTrackingVH>
657InferAddressSpacesImpl::collectFlatAddressExpressions(Function &
F)
const {
660 PostorderStackTy PostorderStack;
662 DenseSet<Value *> Visited;
664 auto PushPtrOperand = [&](
Value *Ptr) {
665 appendsFlatAddressExpressionToPostorderStack(Ptr, PostorderStack, Visited);
673 PushPtrOperand(
GEP->getPointerOperand());
675 PushPtrOperand(LI->getPointerOperand());
677 PushPtrOperand(
SI->getPointerOperand());
679 PushPtrOperand(RMW->getPointerOperand());
681 PushPtrOperand(CmpX->getPointerOperand());
684 PushPtrOperand(
MI->getRawDest());
688 PushPtrOperand(MTI->getRawSource());
690 collectRewritableIntrinsicOperands(
II, PostorderStack, Visited);
692 if (
Cmp->getOperand(0)->getType()->isPtrOrPtrVectorTy()) {
693 PushPtrOperand(
Cmp->getOperand(0));
694 PushPtrOperand(
Cmp->getOperand(1));
697 PushPtrOperand(ASC->getPointerOperand());
704 if (
auto *RV = RI->getReturnValue();
705 RV && RV->getType()->isPtrOrPtrVectorTy())
710 std::vector<WeakTrackingVH> Postorder;
711 while (!PostorderStack.empty()) {
712 Value *TopVal = PostorderStack.back().getPointer();
715 if (PostorderStack.back().getInt()) {
717 Postorder.push_back(TopVal);
718 PostorderStack.pop_back();
722 PostorderStack.back().setInt(
true);
725 for (
Value *PtrOperand : getPointerOperands(*TopVal, *
DL,
TTI)) {
726 appendsFlatAddressExpressionToPostorderStack(PtrOperand, PostorderStack,
738 auto InsertBefore = [NewI](
auto It) {
748 auto InsertI =
F->getEntryBlock().getFirstNonPHIIt();
749 return InsertBefore(InsertI);
759 auto InsertI = OpInst->
getParent()->getFirstNonPHIIt();
760 return InsertBefore(InsertI);
773 const Use &OperandUse,
unsigned NewAddrSpace,
775 const PredicatedAddrSpaceMapTy &PredicatedAS,
784 if (
Value *NewOperand = ValueWithNewAddrSpace.
lookup(Operand))
788 auto I = PredicatedAS.find(std::make_pair(Inst, Operand));
789 if (
I != PredicatedAS.end()) {
791 unsigned NewAS =
I->second;
809Value *InferAddressSpacesImpl::clonePtrMaskWithNewAddressSpace(
810 IntrinsicInst *
I,
unsigned NewAddrSpace,
812 const PredicatedAddrSpaceMapTy &PredicatedAS,
813 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const {
814 const Use &PtrOpUse =
I->getArgOperandUse(0);
816 Value *MaskOp =
I->getArgOperand(1);
819 KnownBits OldPtrBits{
DL->getPointerSizeInBits(OldAddrSpace)};
820 KnownBits NewPtrBits{
DL->getPointerSizeInBits(NewAddrSpace)};
822 std::tie(OldPtrBits, NewPtrBits) =
837 OldPtrBits.
One |= ~OldPtrBits.Zero;
839 KnownBits ClearedBits =
KnownBits::sub(OldPtrBits, OldPtrBits & MaskBits);
844 std::optional<BasicBlock::iterator> InsertPoint =
845 I->getInsertionPointAfterDef();
846 assert(InsertPoint &&
"insertion after ptrmask should be possible");
849 new AddrSpaceCastInst(
I, NewPtrType,
"", *InsertPoint);
851 return AddrSpaceCast;
858 MaskOp =
B.CreateTrunc(MaskOp, MaskTy);
861 PtrOpUse, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS,
863 return B.CreateIntrinsic(Intrinsic::ptrmask, {NewPtr->
getType(), MaskTy},
876Value *InferAddressSpacesImpl::cloneInstructionWithNewAddressSpace(
877 Instruction *
I,
unsigned NewAddrSpace,
879 const PredicatedAddrSpaceMapTy &PredicatedAS,
880 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const {
883 if (
I->getOpcode() == Instruction::AddrSpaceCast) {
884 Value *Src =
I->getOperand(0);
888 assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace);
895 assert(
II->getIntrinsicID() == Intrinsic::ptrmask);
896 return clonePtrMaskWithNewAddressSpace(
897 II, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, PoisonUsesToFix);
905 auto *NewI =
new AddrSpaceCastInst(
I, NewPtrTy);
906 NewI->insertAfter(
I->getIterator());
907 NewI->setDebugLoc(
I->getDebugLoc());
912 SmallVector<Value *, 4> NewPointerOperands;
913 for (
const Use &OperandUse :
I->operands()) {
914 if (!OperandUse.get()->getType()->isPtrOrPtrVectorTy())
918 OperandUse, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS,
922 switch (
I->getOpcode()) {
923 case Instruction::BitCast:
924 return new BitCastInst(NewPointerOperands[0], NewPtrType);
925 case Instruction::PHI: {
926 assert(
I->getType()->isPtrOrPtrVectorTy());
929 for (
unsigned Index = 0;
Index <
PHI->getNumIncomingValues(); ++
Index) {
932 PHI->getIncomingBlock(Index));
936 case Instruction::GetElementPtr: {
939 GEP->getSourceElementType(), NewPointerOperands[0],
940 SmallVector<Value *, 4>(
GEP->indices()));
944 case Instruction::Select:
945 assert(
I->getType()->isPtrOrPtrVectorTy());
947 NewPointerOperands[2],
"",
nullptr,
I);
948 case Instruction::IntToPtr: {
951 if (Src->getType() == NewPtrType)
957 return new AddrSpaceCastInst(Src, NewPtrType);
960 AddrSpaceCastInst *AsCast =
new AddrSpaceCastInst(
I, NewPtrType);
972Value *InferAddressSpacesImpl::cloneConstantExprWithNewAddressSpace(
973 ConstantExpr *CE,
unsigned NewAddrSpace,
975 const TargetTransformInfo *
TTI)
const {
977 CE->getType()->isPtrOrPtrVectorTy()
981 if (
CE->getOpcode() == Instruction::AddrSpaceCast) {
985 assert(CE->getOperand(0)->getType()->getPointerAddressSpace() ==
987 return CE->getOperand(0);
990 if (
CE->getOpcode() == Instruction::BitCast) {
991 if (Value *NewOperand = ValueWithNewAddrSpace.lookup(CE->getOperand(0)))
992 return ConstantExpr::getBitCast(cast<Constant>(NewOperand), TargetType);
993 return ConstantExpr::getAddrSpaceCast(CE, TargetType);
996 if (
CE->getOpcode() == Instruction::IntToPtr) {
997 if (isNoopPtrIntCastPair(cast<Operator>(CE), *DL, TTI)) {
998 Constant *Src = cast<ConstantExpr>(CE->getOperand(0))->getOperand(0);
999 assert(Src->getType()->getPointerAddressSpace() == NewAddrSpace);
1008 SmallVector<Constant *, 4> NewOperands;
1009 for (
unsigned Index = 0;
Index <
CE->getNumOperands(); ++
Index) {
1016 if (
Value *NewOperand = ValueWithNewAddrSpace.
lookup(Operand)) {
1022 if (
Value *NewOperand = cloneConstantExprWithNewAddressSpace(
1023 CExpr, NewAddrSpace, ValueWithNewAddrSpace,
DL,
TTI)) {
1037 if (
CE->getOpcode() == Instruction::GetElementPtr) {
1040 return CE->getWithOperands(NewOperands, TargetType,
false,
1044 return CE->getWithOperands(NewOperands, TargetType);
1052Value *InferAddressSpacesImpl::cloneValueWithNewAddressSpace(
1053 Value *V,
unsigned NewAddrSpace,
1055 const PredicatedAddrSpaceMapTy &PredicatedAS,
1056 SmallVectorImpl<const Use *> *PoisonUsesToFix)
const {
1058 assert(
V->getType()->getPointerAddressSpace() == FlatAddrSpace &&
1059 isAddressExpression(*V, *
DL,
TTI));
1067 Type *NewPtrTy = PointerType::get(Arg->getContext(), NewAddrSpace);
1068 auto *NewI =
new AddrSpaceCastInst(Arg, NewPtrTy);
1069 NewI->insertBefore(Insert);
1074 Value *NewV = cloneInstructionWithNewAddressSpace(
1075 I, NewAddrSpace, ValueWithNewAddrSpace, PredicatedAS, PoisonUsesToFix);
1077 if (NewI->getParent() ==
nullptr) {
1078 NewI->insertBefore(
I->getIterator());
1080 NewI->setDebugLoc(
I->getDebugLoc());
1086 return cloneConstantExprWithNewAddressSpace(
1092unsigned InferAddressSpacesImpl::joinAddressSpaces(
unsigned AS1,
1093 unsigned AS2)
const {
1094 if (AS1 == FlatAddrSpace || AS2 == FlatAddrSpace)
1106bool InferAddressSpacesImpl::run(Function &CurFn) {
1108 DL = &
F->getDataLayout();
1109 PtrIntCastPairs.
clear();
1120 collectIntToPtrPointerOperand();
1122 std::vector<WeakTrackingVH> Postorder = collectFlatAddressExpressions(*
F);
1126 ValueToAddrSpaceMapTy InferredAddrSpace;
1127 PredicatedAddrSpaceMapTy PredicatedAS;
1128 inferAddressSpaces(Postorder, InferredAddrSpace, PredicatedAS);
1132 return rewriteWithNewAddressSpaces(Postorder, InferredAddrSpace,
1138void InferAddressSpacesImpl::inferAddressSpaces(
1140 ValueToAddrSpaceMapTy &InferredAddrSpace,
1141 PredicatedAddrSpaceMapTy &PredicatedAS)
const {
1144 for (
Value *V : Postorder)
1147 while (!Worklist.empty()) {
1148 Value *
V = Worklist.pop_back_val();
1152 if (!updateAddressSpace(*V, InferredAddrSpace, PredicatedAS))
1155 for (
Value *User :
V->users()) {
1157 if (Worklist.count(User))
1160 auto Pos = InferredAddrSpace.find(User);
1163 if (Pos == InferredAddrSpace.end())
1169 if (Pos->second == FlatAddrSpace)
1172 Worklist.insert(User);
1178InferAddressSpacesImpl::getPredicatedAddrSpace(
const Value &Ptr,
1179 const Value *UserCtx)
const {
1202bool InferAddressSpacesImpl::updateAddressSpace(
1203 const Value &V, ValueToAddrSpaceMapTy &InferredAddrSpace,
1204 PredicatedAddrSpaceMapTy &PredicatedAS)
const {
1205 assert(InferredAddrSpace.count(&V));
1207 LLVM_DEBUG(
dbgs() <<
"Updating the address space of\n " << V <<
'\n');
1223 SmallVector<Value *, 2> PtrOps = getPointerOperands(V, *
DL,
TTI);
1224 for (
Value *PtrOperand : PtrOps) {
1225 auto I = InferredAddrSpace.find(PtrOperand);
1227 if (
I == InferredAddrSpace.end()) {
1228 OperandAS = PtrOperand->getType()->getPointerAddressSpace();
1235 if (OperandAS == FlatAddrSpace) {
1237 unsigned AS = getPredicatedAddrSpace(*PtrOperand, &V);
1240 <<
" deduce operand AS from the predicate addrspace "
1244 PredicatedAS[std::make_pair(&V, PtrOperand)] = OperandAS;
1248 OperandAS =
I->second;
1251 NewAS = joinAddressSpaces(NewAS, OperandAS);
1252 if (NewAS == FlatAddrSpace)
1257 if (
any_of(ConstantPtrOps, [=](Constant *
C) {
1258 return !isSafeToCastConstAddrSpace(
C, NewAS);
1260 NewAS = FlatAddrSpace;
1265 PtrOps.size() == ConstantPtrOps.
size())
1269 unsigned OldAS = InferredAddrSpace.lookup(&V);
1270 assert(OldAS != FlatAddrSpace);
1277 InferredAddrSpace[&
V] = NewAS;
1286 if (U.get() == OldVal) {
1294template <
typename InstrType>
1296 InstrType *MemInstr,
unsigned AddrSpace,
1298 if (!MemInstr->isVolatile() ||
TTI.hasVolatileVariant(MemInstr, AddrSpace)) {
1314 User *Inst,
unsigned AddrSpace,
1338 B.CreateMemSet(NewV, MSI->getValue(), MSI->getLength(), MSI->getDestAlign(),
1340 MI->getAAMetadata());
1342 Value *Src = MTI->getRawSource();
1343 Value *Dest = MTI->getRawDest();
1353 if (MCI->isForceInlined())
1354 B.CreateMemCpyInline(Dest, MTI->getDestAlign(), Src,
1355 MTI->getSourceAlign(), MTI->getLength(),
1357 MI->getAAMetadata());
1359 B.CreateMemCpy(Dest, MTI->getDestAlign(), Src, MTI->getSourceAlign(),
1362 MI->getAAMetadata());
1365 B.CreateMemMove(Dest, MTI->getDestAlign(), Src, MTI->getSourceAlign(),
1368 MI->getAAMetadata());
1373 MI->eraseFromParent();
1379bool InferAddressSpacesImpl::isSafeToCastConstAddrSpace(Constant *
C,
1380 unsigned NewAS)
const {
1383 unsigned SrcAS =
C->getType()->getPointerAddressSpace();
1388 if (SrcAS != FlatAddrSpace && NewAS != FlatAddrSpace)
1397 if (
Op->getOpcode() == Instruction::AddrSpaceCast)
1401 if (
Op->getOpcode() == Instruction::IntToPtr &&
1402 Op->getType()->getPointerAddressSpace() == FlatAddrSpace)
1411 User *CurUser =
I->getUser();
1414 while (
I != End &&
I->getUser() == CurUser)
1420void InferAddressSpacesImpl::performPointerReplacement(
1422 SmallVectorImpl<Instruction *> &DeadInstructions)
const {
1424 User *CurUser =
U.getUser();
1426 unsigned AddrSpace =
V->getType()->getPointerAddressSpace();
1431 if (CurUser == NewV)
1435 if (!CurUserI || CurUserI->getFunction() !=
F)
1445 if (rewriteIntrinsicOperands(
II, V, NewV))
1457 int SrcIdx =
U.getOperandNo();
1458 int OtherIdx = (SrcIdx == 0) ? 1 : 0;
1459 Value *OtherSrc =
Cmp->getOperand(OtherIdx);
1461 if (
Value *OtherNewV = ValueWithNewAddrSpace.
lookup(OtherSrc)) {
1462 if (OtherNewV->getType()->getPointerAddressSpace() == NewAS) {
1463 Cmp->setOperand(OtherIdx, OtherNewV);
1464 Cmp->setOperand(SrcIdx, NewV);
1471 if (isSafeToCastConstAddrSpace(KOtherSrc, NewAS)) {
1472 Cmp->setOperand(SrcIdx, NewV);
1482 if (ASC->getDestAddressSpace() == NewAS) {
1483 ASC->replaceAllUsesWith(NewV);
1498 InsertPos = std::next(NewVInst->getIterator());
1506 V,
new AddrSpaceCastInst(NewV,
V->getType(),
"", InsertPos));
1508 CurUserI->replaceUsesOfWith(
1513bool InferAddressSpacesImpl::rewriteWithNewAddressSpaces(
1515 const ValueToAddrSpaceMapTy &InferredAddrSpace,
1516 const PredicatedAddrSpaceMapTy &PredicatedAS)
const {
1523 for (
Value *V : Postorder) {
1524 unsigned NewAddrSpace = InferredAddrSpace.lookup(V);
1531 if (
V->getType()->getPointerAddressSpace() != NewAddrSpace) {
1533 cloneValueWithNewAddressSpace(V, NewAddrSpace, ValueWithNewAddrSpace,
1534 PredicatedAS, &PoisonUsesToFix);
1536 ValueWithNewAddrSpace[
V] =
New;
1540 if (ValueWithNewAddrSpace.
empty())
1544 for (
const Use *PoisonUse : PoisonUsesToFix) {
1545 User *
V = PoisonUse->getUser();
1550 unsigned OperandNo = PoisonUse->getOperandNo();
1552 WeakTrackingVH NewOp = ValueWithNewAddrSpace.
lookup(PoisonUse->get());
1554 "poison replacements in ValueWithNewAddrSpace shouldn't be null");
1558 SmallVector<Instruction *, 16> DeadInstructions;
1563 for (
const WeakTrackingVH &WVH : Postorder) {
1564 assert(WVH &&
"value was unexpectedly deleted");
1567 if (NewV ==
nullptr)
1570 LLVM_DEBUG(
dbgs() <<
"Replacing the uses of " << *V <<
"\n with\n "
1582 if (
I->getFunction() ==
F)
1585 WorkList.
append(
U->user_begin(),
U->user_end());
1588 if (!WorkList.
empty()) {
1590 DenseSet<User *> Visited{WorkList.
begin(), WorkList.
end()};
1591 while (!WorkList.
empty()) {
1594 if (
I->getFunction() ==
F)
1595 VMapper.remapInstruction(*
I);
1598 for (User *U2 :
U->users())
1599 if (Visited.
insert(U2).second)
1607 Value::use_iterator
I,
E,
Next;
1608 for (
I =
V->use_begin(),
E =
V->use_end();
I !=
E;) {
1615 performPointerReplacement(V, NewV, U, ValueWithNewAddrSpace,
1619 if (
V->use_empty()) {
1625 for (Instruction *
I : DeadInstructions)
1631bool InferAddressSpaces::runOnFunction(Function &
F) {
1632 if (skipFunction(
F))
1635 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
1636 DominatorTree *DT = DTWP ? &DTWP->getDomTree() :
nullptr;
1637 return InferAddressSpacesImpl(
1638 getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F), DT,
1639 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F),
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 cl::opt< bool > AssumeDefaultIsFlatAddressSpace("assume-default-is-flat-addrspace", cl::init(false), cl::ReallyHidden, cl::desc("The default address space is assumed as the flat address space. " "This is mainly for test purpose."))
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
MachineInstr unsigned OpIdx
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...
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)
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.
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)
const ParentTy * getParent() const
self_iterator getIterator()
#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)
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(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.
LLVM_ABI InferAddressSpacesPass()
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
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.