diff options
Diffstat (limited to 'lib/IR/Value.cpp')
-rw-r--r-- | lib/IR/Value.cpp | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 80b993c89f7f..b7f77dc3043e 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -1,9 +1,8 @@ //===-- Value.cpp - Implement the Value class -----------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -58,7 +57,8 @@ Value::Value(Type *ty, unsigned scid) // FIXME: Why isn't this in the subclass gunk?? // Note, we cannot call isa<CallInst> before the CallInst has been // constructed. - if (SubclassID == Instruction::Call || SubclassID == Instruction::Invoke) + if (SubclassID == Instruction::Call || SubclassID == Instruction::Invoke || + SubclassID == Instruction::CallBr) assert((VTy->isFirstClassType() || VTy->isVoidTy() || VTy->isStructTy()) && "invalid CallInst type!"); else if (SubclassID != BasicBlockVal && @@ -460,6 +460,7 @@ namespace { enum PointerStripKind { PSK_ZeroIndices, PSK_ZeroIndicesAndAliases, + PSK_ZeroIndicesAndAliasesSameRepresentation, PSK_ZeroIndicesAndAliasesAndInvariantGroups, PSK_InBoundsConstantIndices, PSK_InBounds @@ -479,6 +480,7 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) { if (auto *GEP = dyn_cast<GEPOperator>(V)) { switch (StripKind) { case PSK_ZeroIndicesAndAliases: + case PSK_ZeroIndicesAndAliasesSameRepresentation: case PSK_ZeroIndicesAndAliasesAndInvariantGroups: case PSK_ZeroIndices: if (!GEP->hasAllZeroIndices()) @@ -494,8 +496,12 @@ static const Value *stripPointerCastsAndOffsets(const Value *V) { break; } V = GEP->getPointerOperand(); - } else if (Operator::getOpcode(V) == Instruction::BitCast || + } else if (Operator::getOpcode(V) == Instruction::BitCast) { + V = cast<Operator>(V)->getOperand(0); + } else if (StripKind != PSK_ZeroIndicesAndAliasesSameRepresentation && 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()) @@ -530,6 +536,11 @@ const Value *Value::stripPointerCasts() const { return stripPointerCastsAndOffsets<PSK_ZeroIndicesAndAliases>(this); } +const Value *Value::stripPointerCastsSameRepresentation() const { + return stripPointerCastsAndOffsets< + PSK_ZeroIndicesAndAliasesSameRepresentation>(this); +} + const Value *Value::stripPointerCastsNoFollowAliases() const { return stripPointerCastsAndOffsets<PSK_ZeroIndices>(this); } @@ -544,13 +555,13 @@ const Value *Value::stripPointerCastsAndInvariantGroups() const { } const Value * -Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, - APInt &Offset) const { - if (!getType()->isPointerTy()) +Value::stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, + bool AllowNonInbounds) const { + if (!getType()->isPtrOrPtrVectorTy()) return this; - assert(Offset.getBitWidth() == DL.getIndexSizeInBits(cast<PointerType>( - getType())->getAddressSpace()) && + unsigned BitWidth = Offset.getBitWidth(); + assert(BitWidth == DL.getIndexTypeSizeInBits(getType()) && "The offset bit width does not match the DL specification."); // Even though we don't look through PHI nodes, we could be called on an @@ -560,27 +571,39 @@ Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, const Value *V = this; do { if (auto *GEP = dyn_cast<GEPOperator>(V)) { - if (!GEP->isInBounds()) + // If in-bounds was requested, we do not strip non-in-bounds GEPs. + if (!AllowNonInbounds && !GEP->isInBounds()) return V; - APInt GEPOffset(Offset); + + // If one of the values we have visited is an addrspacecast, then + // the pointer type of this GEP may be different from the type + // of the Ptr parameter which was passed to this function. This + // means when we construct GEPOffset, we need to use the size + // of GEP's pointer type rather than the size of the original + // pointer type. + APInt GEPOffset(DL.getIndexTypeSizeInBits(V->getType()), 0); if (!GEP->accumulateConstantOffset(DL, GEPOffset)) return V; - Offset = GEPOffset; + + // Stop traversal if the pointer offset wouldn't fit in the bit-width + // provided by the Offset argument. This can happen due to AddrSpaceCast + // stripping. + if (GEPOffset.getMinSignedBits() > BitWidth) + return V; + + Offset += GEPOffset.sextOrTrunc(BitWidth); V = GEP->getPointerOperand(); - } else if (Operator::getOpcode(V) == Instruction::BitCast) { + } else if (Operator::getOpcode(V) == Instruction::BitCast || + Operator::getOpcode(V) == Instruction::AddrSpaceCast) { V = cast<Operator>(V)->getOperand(0); } else if (auto *GA = dyn_cast<GlobalAlias>(V)) { - V = GA->getAliasee(); - } else { - if (const auto *Call = dyn_cast<CallBase>(V)) - if (const Value *RV = Call->getReturnedArgOperand()) { + if (!GA->isInterposable()) + V = GA->getAliasee(); + } else if (const auto *Call = dyn_cast<CallBase>(V)) { + if (const Value *RV = Call->getReturnedArgOperand()) V = RV; - continue; - } - - return V; } - assert(V->getType()->isPointerTy() && "Unexpected operand type!"); + assert(V->getType()->isPtrOrPtrVectorTy() && "Unexpected operand type!"); } while (Visited.insert(V).second); return V; @@ -648,10 +671,14 @@ unsigned Value::getPointerAlignment(const DataLayout &DL) const { unsigned Align = 0; if (auto *GO = dyn_cast<GlobalObject>(this)) { - // Don't make any assumptions about function pointer alignment. Some - // targets use the LSBs to store additional information. - if (isa<Function>(GO)) - return 0; + if (isa<Function>(GO)) { + switch (DL.getFunctionPtrAlignType()) { + case DataLayout::FunctionPtrAlignType::Independent: + return DL.getFunctionPtrAlign(); + case DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign: + return std::max(DL.getFunctionPtrAlign(), GO->getAlignment()); + } + } Align = GO->getAlignment(); if (Align == 0) { if (auto *GVar = dyn_cast<GlobalVariable>(GO)) { @@ -931,7 +958,7 @@ void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) { << Old->getName() << " to " << *New->getType() << " %" << New->getName() << "\n"; llvm_unreachable( - "A weak tracking value handle still pointed to the old value!\n"); + "A weak tracking value handle still pointed to the old value!\n"); default: break; } |