diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-references.cl b/clang/test/CodeGenOpenCLCXX/addrspace-references.cl index b17e701426e2..19aeebe5df63 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-references.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-references.cl @@ -9,6 +9,6 @@ void foo() { // CHECK: [[REF:%.*]] = alloca i32 // CHECK: store i32 1, i32* [[REF]] // CHECK: [[REG:%[0-9]+]] = addrspacecast i32* [[REF]] to i32 addrspace(4)* - // CHECK: call spir_func i32 @_Z3barRU3AS4Kj(i32 addrspace(4)* nonnull dereferenceable(4) [[REG]]) + // CHECK: call spir_func i32 @_Z3barRU3AS4Kj(i32 addrspace(4)* dereferenceable(4) [[REG]]) bar(1); } diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h index d0de008db265..3f8caa668e51 100644 --- a/llvm/include/llvm/IR/Value.h +++ b/llvm/include/llvm/IR/Value.h @@ -493,7 +493,7 @@ public: /// swifterror attribute. bool isSwiftError() const; - /// Strip off pointer casts, all-zero GEPs, and aliases. + /// Strip off pointer casts, all-zero GEPs, address space casts, and aliases. /// /// Returns the original uncasted value. If this is called on a non-pointer /// value, it returns 'this'. @@ -503,6 +503,17 @@ public: static_cast(this)->stripPointerCasts()); } + /// Strip off pointer casts, all-zero GEPs, address space casts, and aliases + /// but ensures the representation of the result stays the same. + /// + /// Returns the original uncasted value with the same representation. If this + /// is called on a non-pointer value, it returns 'this'. + const Value *stripPointerCastsSameRepresentation() const; + Value *stripPointerCastsSameRepresentation() { + return const_cast(static_cast(this) + ->stripPointerCastsSameRepresentation()); + } + /// Strip off pointer casts, all-zero GEPs, aliases and invariant group /// info. /// diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index 53e9f49a5711..542ff709d475 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -1803,7 +1803,7 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C, // through would still be correct. const DataLayout &DL = CxtI->getModule()->getDataLayout(); if (V->getType()->isPointerTy() && C->isNullValue() && - isKnownNonZero(V->stripPointerCasts(), DL)) { + isKnownNonZero(V->stripPointerCastsSameRepresentation(), DL)) { if (Pred == ICmpInst::ICMP_EQ) return LazyValueInfo::False; else if (Pred == ICmpInst::ICMP_NE) diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index cf32a66c9014..9e0a43ce1e30 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -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(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(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(V)->getOperand(0); } else if (auto *GA = dyn_cast(V)) { if (StripKind == PSK_ZeroIndices || GA->isInterposable()) @@ -530,6 +536,11 @@ const Value *Value::stripPointerCasts() const { return stripPointerCastsAndOffsets(this); } +const Value *Value::stripPointerCastsSameRepresentation() const { + return stripPointerCastsAndOffsets< + PSK_ZeroIndicesAndAliasesSameRepresentation>(this); +} + const Value *Value::stripPointerCastsNoFollowAliases() const { return stripPointerCastsAndOffsets(this); }