Skip to content

Commit

Permalink
Don't look through addrspacecast in GetPointerBaseWithConstantOffset
Browse files Browse the repository at this point in the history
Pointers in different addrspaces can have different sizes, so it's not valid to look through addrspace cast calculating base and offset for a value.

This is similar to D13008.

Reviewed By: reames

Differential Revision: https://reviews.llvm.org/D24729

llvm-svn: 282612
  • Loading branch information
arpilipe committed Sep 28, 2016
1 parent 7f5866c commit b6ce6e5
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 15 deletions.
9 changes: 7 additions & 2 deletions llvm/lib/Analysis/ValueTracking.cpp
Expand Up @@ -2848,9 +2848,14 @@ Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
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<Operator>(Ptr)->getOperand(0);
} else if (AddrSpaceCastInst *ASCI = dyn_cast<AddrSpaceCastInst>(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<GlobalAlias>(Ptr)) {
if (GA->isInterposable())
break;
Expand Down
14 changes: 14 additions & 0 deletions llvm/test/Transforms/GVN/PRE/rle-addrspace-cast.ll
@@ -0,0 +1,14 @@
; RUN: opt < %s -default-data-layout="e-p:32:32:32-p1:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-n8:16:32" -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
}
13 changes: 0 additions & 13 deletions llvm/test/Transforms/GVN/PRE/rle.ll
Expand Up @@ -318,19 +318,6 @@ define i8 @coerce_offset0(i32 %V, i32* %P) {
; 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*
Expand Down
21 changes: 21 additions & 0 deletions llvm/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
}

0 comments on commit b6ce6e5

Please sign in to comment.