Index: lib/Analysis/Loads.cpp =================================================================== --- lib/Analysis/Loads.cpp +++ lib/Analysis/Loads.cpp @@ -100,9 +100,12 @@ return isDereferenceableAndAlignedPointer( RelocateInst->getDerivedPtr(), Align, Size, DL, CtxI, DT, Visited); - if (const AddrSpaceCastInst *ASC = dyn_cast(V)) - return isDereferenceableAndAlignedPointer(ASC->getOperand(0), Align, Size, - DL, CtxI, DT, Visited); + if (const AddrSpaceCastInst *ASC = dyn_cast(V)) { + const Value *Ptr = ASC->getPointerOperand(); + if (Size.getBitWidth() == DL.getPointerTypeSizeInBits(Ptr->getType())) + return isDereferenceableAndAlignedPointer(ASC->getOperand(0), Align, + Size, DL, CtxI, DT, Visited); + } if (auto CS = ImmutableCallSite(V)) if (const Value *RV = CS.getReturnedArgOperand()) Index: lib/IR/Value.cpp =================================================================== --- lib/IR/Value.cpp +++ lib/IR/Value.cpp @@ -516,6 +516,13 @@ V = GEP->getPointerOperand(); } else if (Operator::getOpcode(V) == Instruction::BitCast) { V = cast(V)->getOperand(0); + } else if (AddrSpaceCastInst *ASCI = dyn_cast(V)) { + Value *SourcePtr = ASCI->getPointerOperand(); + // Don't look through addrspace cast which changes pointer size + if (Offset.getBitWidth() != + DL.getPointerTypeSizeInBits(SourcePtr->getType())) + return V; + V = SourcePtr; } else if (GlobalAlias *GA = dyn_cast(V)) { V = GA->getAliasee(); } else { Index: test/Analysis/ValueTracking/dereferenceable-addrspace-cast.ll =================================================================== --- /dev/null +++ test/Analysis/ValueTracking/dereferenceable-addrspace-cast.ll @@ -0,0 +1,15 @@ +; RUN: opt -default-data-layout="e-m:e-p:16:16-p1:32:16-i32:16-i64:16-n8:16" -print-memderefs -analyze -S <%s | FileCheck %s --check-prefix=CHECK-DL +; RUN: opt -print-memderefs -analyze -S <%s | FileCheck %s --check-prefix=CHECK-NO-DL + +; CHECK-DL-LABEL: 'test' +; CHECK-DL: The following are dereferenceable: +; CHECK-DL-NOT: %cast{{.*}}(aligned) +; CHECK-NO-DL-LABEL: 'test' +; CHECK-NO-DL: The following are dereferenceable: +; CHECK-NO-DL: %cast{{.*}}(aligned) +define void @test(i32 addrspace(1)* dereferenceable(8) %dparam) { +entry: + %cast = addrspacecast i32 addrspace(1)* %dparam to i32* + %load3 = load i32, i32* %cast + ret void +} Index: test/Transforms/InstSimplify/addrspace-cast.ll =================================================================== --- /dev/null +++ test/Transforms/InstSimplify/addrspace-cast.ll @@ -0,0 +1,21 @@ +; RUN: opt -S -instsimplify -default-data-layout="p:32:32-p1:32:32" < %s | FileCheck %s --check-prefix=CHECK-32 +; RUN: opt -S -instsimplify -default-data-layout="p:32:32-p1:64:64" < %s | FileCheck %s --check-prefix=CHECK-64 + +; Check that we don't look through an addrspacecast if it changes pointer size +; and that we do look if it doesn't + +define i32 @test4() { +; CHECK-32-LABEL: @test4( +; CHECK-32-NEXT: ret i32 4 +; CHECK-64-LABEL: @test4( +; CHECK-64: ret i32 %add_to_int + %alloca = alloca i32, align 4 ; alloca + 0 + %gep = getelementptr inbounds i32, i32* %alloca, i32 1 ; alloca + 4 + %bc = bitcast i32* %gep to [4 x i8]* ; alloca + 4 + %ac = addrspacecast [4 x i8]* %bc to [4 x i8] addrspace(1)* ; alloca + 4 + %pti = ptrtoint i32* %alloca to i32 ; alloca + %sub = sub i32 0, %pti ; -alloca + %add = getelementptr [4 x i8], [4 x i8] addrspace(1)* %ac, i32 0, i32 %sub ; alloca + 4 - alloca == 4 + %add_to_int = ptrtoint i8 addrspace(1)* %add to i32 ; 4 + ret i32 %add_to_int ; 4 +} Index: test/Transforms/LoopUnswitch/2015-09-18-Addrspace.ll =================================================================== --- test/Transforms/LoopUnswitch/2015-09-18-Addrspace.ll +++ test/Transforms/LoopUnswitch/2015-09-18-Addrspace.ll @@ -6,10 +6,10 @@ target datalayout = "e-m:e-p:16:16-p1:32:16-i32:16-i64:16-n8:16" -define void @foo() { +define void @foo(i16* %p) { ; CHECK-LABEL: @foo entry: - %arrayidx.i1 = getelementptr inbounds i16, i16* undef, i16 undef + %arrayidx.i1 = getelementptr inbounds i16, i16* %p, i16 4 %arrayidx.i = addrspacecast i16* %arrayidx.i1 to i16 addrspace(1)* br i1 undef, label %for.body.i, label %bar.exit