aboutsummaryrefslogtreecommitdiff
path: root/lib/IR/Value.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IR/Value.cpp')
-rw-r--r--lib/IR/Value.cpp85
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;
}