diff options
Diffstat (limited to 'lib/IR/Value.cpp')
-rw-r--r-- | lib/IR/Value.cpp | 111 |
1 files changed, 61 insertions, 50 deletions
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index b7f77dc3043e..3c8a5b536695 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -444,15 +444,11 @@ void Value::replaceUsesOutsideBlock(Value *New, BasicBlock *BB) { "replaceUses of value with new value of different type!"); assert(BB && "Basic block that may contain a use of 'New' must be defined\n"); - use_iterator UI = use_begin(), E = use_end(); - for (; UI != E;) { - Use &U = *UI; - ++UI; - auto *Usr = dyn_cast<Instruction>(U.getUser()); - if (Usr && Usr->getParent() == BB) - continue; - U.set(New); - } + replaceUsesWithIf(New, [BB](Use &U) { + auto *I = dyn_cast<Instruction>(U.getUser()); + // Don't replace if it's an instruction in the BB basic block. + return !I || I->getParent() != BB; + }); } namespace { @@ -460,8 +456,8 @@ namespace { enum PointerStripKind { PSK_ZeroIndices, PSK_ZeroIndicesAndAliases, - PSK_ZeroIndicesAndAliasesSameRepresentation, - PSK_ZeroIndicesAndAliasesAndInvariantGroups, + PSK_ZeroIndicesSameRepresentation, + PSK_ZeroIndicesAndInvariantGroups, PSK_InBoundsConstantIndices, PSK_InBounds }; @@ -479,10 +475,10 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) { do { if (auto *GEP = dyn_cast<GEPOperator>(V)) { switch (StripKind) { - case PSK_ZeroIndicesAndAliases: - case PSK_ZeroIndicesAndAliasesSameRepresentation: - case PSK_ZeroIndicesAndAliasesAndInvariantGroups: case PSK_ZeroIndices: + case PSK_ZeroIndicesAndAliases: + case PSK_ZeroIndicesSameRepresentation: + case PSK_ZeroIndicesAndInvariantGroups: if (!GEP->hasAllZeroIndices()) return V; break; @@ -498,15 +494,13 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) { V = GEP->getPointerOperand(); } else if (Operator::getOpcode(V) == Instruction::BitCast) { V = cast<Operator>(V)->getOperand(0); - } else if (StripKind != PSK_ZeroIndicesAndAliasesSameRepresentation && + } else if (StripKind != PSK_ZeroIndicesSameRepresentation && Operator::getOpcode(V) == Instruction::AddrSpaceCast) { // TODO: If we know an address space cast will not change the // representation we could look through it here as well. V = cast<Operator>(V)->getOperand(0); - } else if (auto *GA = dyn_cast<GlobalAlias>(V)) { - if (StripKind == PSK_ZeroIndices || GA->isInterposable()) - return V; - V = GA->getAliasee(); + } else if (StripKind == PSK_ZeroIndicesAndAliases && isa<GlobalAlias>(V)) { + V = cast<GlobalAlias>(V)->getAliasee(); } else { if (const auto *Call = dyn_cast<CallBase>(V)) { if (const Value *RV = Call->getReturnedArgOperand()) { @@ -516,7 +510,7 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) { // The result of launder.invariant.group must alias it's argument, // but it can't be marked with returned attribute, that's why it needs // special case. - if (StripKind == PSK_ZeroIndicesAndAliasesAndInvariantGroups && + if (StripKind == PSK_ZeroIndicesAndInvariantGroups && (Call->getIntrinsicID() == Intrinsic::launder_invariant_group || Call->getIntrinsicID() == Intrinsic::strip_invariant_group)) { V = Call->getArgOperand(0); @@ -533,16 +527,15 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) { } // end anonymous namespace const Value *Value::stripPointerCasts() const { - return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this); + return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this); } -const Value *Value::stripPointerCastsSameRepresentation() const { - return stripPointerCastsAndOffsets< - PSK_ZeroIndicesAndAliasesSameRepresentation>(this); +const Value *Value::stripPointerCastsAndAliases() const { + return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this); } -const Value *Value::stripPointerCastsNoFollowAliases() const { - return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this); +const Value *Value::stripPointerCastsSameRepresentation() const { + return stripPointerCastsAndOffsets<PSK_ZeroIndicesSameRepresentation>(this); } const Value *Value::stripInBoundsConstantOffsets() const { @@ -550,8 +543,7 @@ const Value *Value::stripInBoundsConstantOffsets() const { } const Value *Value::stripPointerCastsAndInvariantGroups() const { - return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliasesAndInvariantGroups>( - this); + return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndInvariantGroups>(this); } const Value * @@ -650,6 +642,19 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, } CanBeNull = true; } + } else if (auto *IP = dyn_cast<IntToPtrInst>(this)) { + if (MDNode *MD = IP->getMetadata(LLVMContext::MD_dereferenceable)) { + ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0)); + DerefBytes = CI->getLimitedValue(); + } + if (DerefBytes == 0) { + if (MDNode *MD = + IP->getMetadata(LLVMContext::MD_dereferenceable_or_null)) { + ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0)); + DerefBytes = CI->getLimitedValue(); + } + CanBeNull = true; + } } else if (auto *AI = dyn_cast<AllocaInst>(this)) { if (!AI->isArrayAllocation()) { DerefBytes = DL.getTypeStoreSize(AI->getAllocatedType()); @@ -666,21 +671,21 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, return DerefBytes; } -unsigned Value::getPointerAlignment(const DataLayout &DL) const { +MaybeAlign Value::getPointerAlignment(const DataLayout &DL) const { assert(getType()->isPointerTy() && "must be pointer"); - - unsigned Align = 0; if (auto *GO = dyn_cast<GlobalObject>(this)) { if (isa<Function>(GO)) { + const MaybeAlign FunctionPtrAlign = DL.getFunctionPtrAlign(); switch (DL.getFunctionPtrAlignType()) { case DataLayout::FunctionPtrAlignType::Independent: - return DL.getFunctionPtrAlign(); + return FunctionPtrAlign; case DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign: - return std::max(DL.getFunctionPtrAlign(), GO->getAlignment()); + return std::max(FunctionPtrAlign, MaybeAlign(GO->getAlignment())); } + llvm_unreachable("Unhandled FunctionPtrAlignType"); } - Align = GO->getAlignment(); - if (Align == 0) { + const MaybeAlign Alignment(GO->getAlignment()); + if (!Alignment) { if (auto *GVar = dyn_cast<GlobalVariable>(GO)) { Type *ObjectType = GVar->getValueType(); if (ObjectType->isSized()) { @@ -688,37 +693,43 @@ unsigned Value::getPointerAlignment(const DataLayout &DL) const { // it the preferred alignment. Otherwise, we have to assume that it // may only have the minimum ABI alignment. if (GVar->isStrongDefinitionForLinker()) - Align = DL.getPreferredAlignment(GVar); + return MaybeAlign(DL.getPreferredAlignment(GVar)); else - Align = DL.getABITypeAlignment(ObjectType); + return Align(DL.getABITypeAlignment(ObjectType)); } } } + return Alignment; } else if (const Argument *A = dyn_cast<Argument>(this)) { - Align = A->getParamAlignment(); - - if (!Align && A->hasStructRetAttr()) { + const MaybeAlign Alignment(A->getParamAlignment()); + if (!Alignment && A->hasStructRetAttr()) { // An sret parameter has at least the ABI alignment of the return type. Type *EltTy = cast<PointerType>(A->getType())->getElementType(); if (EltTy->isSized()) - Align = DL.getABITypeAlignment(EltTy); + return Align(DL.getABITypeAlignment(EltTy)); } + return Alignment; } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(this)) { - Align = AI->getAlignment(); - if (Align == 0) { + const MaybeAlign Alignment(AI->getAlignment()); + if (!Alignment) { Type *AllocatedType = AI->getAllocatedType(); if (AllocatedType->isSized()) - Align = DL.getPrefTypeAlignment(AllocatedType); + return MaybeAlign(DL.getPrefTypeAlignment(AllocatedType)); } - } else if (const auto *Call = dyn_cast<CallBase>(this)) - Align = Call->getAttributes().getRetAlignment(); - else if (const LoadInst *LI = dyn_cast<LoadInst>(this)) + return Alignment; + } else if (const auto *Call = dyn_cast<CallBase>(this)) { + const MaybeAlign Alignment(Call->getRetAlignment()); + if (!Alignment && Call->getCalledFunction()) + return MaybeAlign( + Call->getCalledFunction()->getAttributes().getRetAlignment()); + return Alignment; + } else if (const LoadInst *LI = dyn_cast<LoadInst>(this)) { if (MDNode *MD = LI->getMetadata(LLVMContext::MD_align)) { ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(0)); - Align = CI->getLimitedValue(); + return MaybeAlign(CI->getLimitedValue()); } - - return Align; + } + return llvm::None; } const Value *Value::DoPHITranslation(const BasicBlock *CurBB, |