Index: cfe/trunk/test/CodeGenOpenCLCXX/addrspace-references.cl =================================================================== --- cfe/trunk/test/CodeGenOpenCLCXX/addrspace-references.cl +++ cfe/trunk/test/CodeGenOpenCLCXX/addrspace-references.cl @@ -9,6 +9,6 @@ // 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); } Index: llvm/trunk/include/llvm/IR/Value.h =================================================================== --- llvm/trunk/include/llvm/IR/Value.h +++ llvm/trunk/include/llvm/IR/Value.h @@ -493,7 +493,7 @@ /// 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 @@ 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. /// Index: llvm/trunk/lib/Analysis/LazyValueInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LazyValueInfo.cpp +++ llvm/trunk/lib/Analysis/LazyValueInfo.cpp @@ -1803,7 +1803,7 @@ // 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) Index: llvm/trunk/lib/IR/Value.cpp =================================================================== --- llvm/trunk/lib/IR/Value.cpp +++ llvm/trunk/lib/IR/Value.cpp @@ -460,6 +460,7 @@ enum PointerStripKind { PSK_ZeroIndices, PSK_ZeroIndicesAndAliases, + PSK_ZeroIndicesAndAliasesSameRepresentation, PSK_ZeroIndicesAndAliasesAndInvariantGroups, PSK_InBoundsConstantIndices, PSK_InBounds @@ -479,6 +480,7 @@ 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 @@ 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 @@ return stripPointerCastsAndOffsets(this); } +const Value *Value::stripPointerCastsSameRepresentation() const { + return stripPointerCastsAndOffsets< + PSK_ZeroIndicesAndAliasesSameRepresentation>(this); +} + const Value *Value::stripPointerCastsNoFollowAliases() const { return stripPointerCastsAndOffsets(this); }