[InstCombine] Don't fold bitcast into store if it would need addrspacecast

Summary:
Previously the code didn't check if the before and after types for the
store were pointers to different address spaces. This resulted in
instcombine using a bitcast to convert between pointers to different
address spaces, causing an assertion due to the invalid cast.

It is not be appropriate to use addrspacecast this case because it is
not guaranteed to be a no-op cast. Instead bail out and do not do the
transformation.

CC: llvm-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D3117

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204733 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Osborne 2014-03-25 17:21:41 +00:00
parent 902c799d96
commit 67cb554e65
2 changed files with 32 additions and 6 deletions

View File

@ -508,15 +508,27 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
if (!SrcPTy->isIntegerTy() && !SrcPTy->isPointerTy()) if (!SrcPTy->isIntegerTy() && !SrcPTy->isPointerTy())
return 0; return 0;
// If the pointers point into different address spaces or if they point to // If the pointers point into different address spaces don't do the
// values with different sizes, we can't do the transformation. // transformation.
if (SrcTy->getAddressSpace() !=
cast<PointerType>(CI->getType())->getAddressSpace())
return 0;
// If the pointers point to values of different sizes don't do the
// transformation.
if (!IC.getDataLayout() || if (!IC.getDataLayout() ||
SrcTy->getAddressSpace() !=
cast<PointerType>(CI->getType())->getAddressSpace() ||
IC.getDataLayout()->getTypeSizeInBits(SrcPTy) != IC.getDataLayout()->getTypeSizeInBits(SrcPTy) !=
IC.getDataLayout()->getTypeSizeInBits(DestPTy)) IC.getDataLayout()->getTypeSizeInBits(DestPTy))
return 0; return 0;
// If the pointers point to pointers to different address spaces don't do the
// transformation. It is not safe to introduce an addrspacecast instruction in
// this case since, depending on the target, addrspacecast may not be a no-op
// cast.
if (SrcPTy->isPointerTy() && DestPTy->isPointerTy() &&
SrcPTy->getPointerAddressSpace() != DestPTy->getPointerAddressSpace())
return 0;
// Okay, we are casting from one integer or pointer type to another of // Okay, we are casting from one integer or pointer type to another of
// the same size. Instead of casting the pointer before // the same size. Instead of casting the pointer before
// the store, cast the value to be stored. // the store, cast the value to be stored.

View File

@ -3,14 +3,14 @@
; Instcombine should preserve metadata and alignment while ; Instcombine should preserve metadata and alignment while
; folding a bitcast into a store. ; folding a bitcast into a store.
; CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 16, !tag !0
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
%struct.A = type { i32 (...)** } %struct.A = type { i32 (...)** }
@G = external constant [5 x i8*] @G = external constant [5 x i8*]
; CHECK-LABEL: @foo
; CHECK: store i32 (...)** bitcast (i8** getelementptr inbounds ([5 x i8*]* @G, i64 0, i64 2) to i32 (...)**), i32 (...)*** %0, align 16, !tag !0
define void @foo(%struct.A* %a) nounwind { define void @foo(%struct.A* %a) nounwind {
entry: entry:
%0 = bitcast %struct.A* %a to i8*** %0 = bitcast %struct.A* %a to i8***
@ -18,4 +18,18 @@ entry:
ret void ret void
} }
; Check instcombine doesn't try and fold the following bitcast into the store.
; This transformation would not be safe since we would need to use addrspacecast
; and addrspacecast is not guaranteed to be a no-op cast.
; CHECK-LABEL: @bar
; CHECK: %cast = bitcast i8** %b to i8 addrspace(1)**
; CHECK: store i8 addrspace(1)* %a, i8 addrspace(1)** %cast
define void @bar(i8 addrspace(1)* %a, i8** %b) nounwind {
entry:
%cast = bitcast i8** %b to i8 addrspace(1)**
store i8 addrspace(1)* %a, i8 addrspace(1)** %cast
ret void
}
!0 = metadata !{metadata !"hello"} !0 = metadata !{metadata !"hello"}