Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -2840,9 +2840,14 @@ ByteOffset += GEPOffset; Ptr = GEP->getPointerOperand(); - } else if (Operator::getOpcode(Ptr) == Instruction::BitCast || - Operator::getOpcode(Ptr) == Instruction::AddrSpaceCast) { + } else if (Operator::getOpcode(Ptr) == Instruction::BitCast) { Ptr = cast(Ptr)->getOperand(0); + } else if (AddrSpaceCastInst *ASCI = dyn_cast(Ptr)) { + Value *SourcePtr = ASCI->getPointerOperand(); + // Don't look through addrspace cast which changes pointer size + if (BitWidth != DL.getPointerTypeSizeInBits(SourcePtr->getType())) + break; + Ptr = SourcePtr; } else if (GlobalAlias *GA = dyn_cast(Ptr)) { if (GA->isInterposable()) break; Index: test/Transforms/GVN/PRE/rle-addrspace-cast.ll =================================================================== --- /dev/null +++ test/Transforms/GVN/PRE/rle-addrspace-cast.ll @@ -0,0 +1,14 @@ +; RUN: opt < %s -basicaa -gvn -S -die | FileCheck %s + +define i8 @coerce_offset0_addrspacecast(i32 %V, i32* %P) { + store i32 %V, i32* %P + + %P2 = addrspacecast i32* %P to i8 addrspace(1)* + %P3 = getelementptr i8, i8 addrspace(1)* %P2, i32 2 + + %A = load i8, i8 addrspace(1)* %P3 + ret i8 %A +; CHECK-LABEL: @coerce_offset0_addrspacecast( +; CHECK-NOT: load +; CHECK: ret i8 +} Index: test/Transforms/GVN/PRE/rle.ll =================================================================== --- test/Transforms/GVN/PRE/rle.ll +++ test/Transforms/GVN/PRE/rle.ll @@ -318,19 +318,6 @@ ; CHECK: ret i8 } -define i8 @coerce_offset0_addrspacecast(i32 %V, i32* %P) { - store i32 %V, i32* %P - - %P2 = addrspacecast i32* %P to i8 addrspace(1)* - %P3 = getelementptr i8, i8 addrspace(1)* %P2, i32 2 - - %A = load i8, i8 addrspace(1)* %P3 - ret i8 %A -; CHECK-LABEL: @coerce_offset0_addrspacecast( -; CHECK-NOT: load -; CHECK: ret i8 -} - ;; non-local i32/float -> i8 load forwarding. define i8 @coerce_offset_nonlocal0(i32* %P, i1 %cond) { %P2 = bitcast i32* %P to float* Index: test/Transforms/GVN/addrspace-cast.ll =================================================================== --- /dev/null +++ test/Transforms/GVN/addrspace-cast.ll @@ -0,0 +1,21 @@ +; RUN: opt < %s -gvn -S | FileCheck %s +target datalayout = "e-m:e-p:16:16-p1:32:16-i32:16-i64:16-n8:16" + +; In cases where two address spaces do not have the same size pointer, the +; input for the addrspacecast should not be used as a substitute for itself +; when manipulating the pointer. + +; Check that we don't hit the assert in this scenario +define i8 @test(i32 %V, i32* %P) { +; CHECK-LABEL: @test( +; CHECK: load + %P1 = getelementptr inbounds i32, i32* %P, i16 16 + + store i32 %V, i32* %P1 + + %P2 = addrspacecast i32* %P1 to i8 addrspace(1)* + %P3 = getelementptr i8, i8 addrspace(1)* %P2, i32 2 + + %A = load i8, i8 addrspace(1)* %P3 + ret i8 %A +}