Value *PropagateJuliaAddrspaces::LiftPointer(Value *V, Type *LocTy, Instruction *InsertPt) { SmallVector<Value *, 4> Stack; Value *CurrentV = V; // Follow pointer casts back, see if we're based on a pointer in // an untracked address space, in which case we're allowed to drop // intermediate addrspace casts. while (true) { Stack.push_back(CurrentV); if (isa<BitCastInst>(CurrentV)) CurrentV = cast<BitCastInst>(CurrentV)->getOperand(0); else if (isa<AddrSpaceCastInst>(CurrentV)) { CurrentV = cast<AddrSpaceCastInst>(CurrentV)->getOperand(0); if (!isSpecialAS(getValueAddrSpace(CurrentV))) break; } else if (isa<GetElementPtrInst>(CurrentV)) { if (LiftingMap.count(CurrentV)) { CurrentV = LiftingMap[CurrentV]; break; } else if (Visited.count(CurrentV)) { return nullptr; } Visited.insert(CurrentV); CurrentV = cast<GetElementPtrInst>(CurrentV)->getOperand(0); } else break; } if (!CurrentV->getType()->isPointerTy()) return nullptr; if (isSpecialAS(getValueAddrSpace(CurrentV))) return nullptr; // Ok, we're allowed to change the address space of this load, go back and // reconstitute any GEPs in the new address space. for (Value *V : llvm::reverse(Stack)) { GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V); if (!GEP) continue; if (LiftingMap.count(GEP)) { CurrentV = LiftingMap[GEP]; continue; } GetElementPtrInst *NewGEP = cast<GetElementPtrInst>(GEP->clone()); ToInsert.push_back(std::make_pair(NewGEP, GEP)); Type *GEPTy = GEP->getSourceElementType(); Type *NewRetTy = cast<PointerType>(GEP->getType())->getElementType()->getPointerTo(getValueAddrSpace(CurrentV)); NewGEP->mutateType(NewRetTy); if (cast<PointerType>(CurrentV->getType())->getElementType() != GEPTy) { auto *BCI = new BitCastInst(CurrentV, GEPTy->getPointerTo()); ToInsert.push_back(std::make_pair(BCI, NewGEP)); CurrentV = BCI; } NewGEP->setOperand(GetElementPtrInst::getPointerOperandIndex(), CurrentV); LiftingMap[GEP] = NewGEP; CurrentV = NewGEP; } if (LocTy && cast<PointerType>(CurrentV->getType())->getElementType() != LocTy) { auto *BCI = new BitCastInst(CurrentV, LocTy->getPointerTo()); ToInsert.push_back(std::make_pair(BCI, InsertPt)); CurrentV = BCI; } return CurrentV; }