mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +00:00
IR: Don't constant fold GEP bitcasts between different address spaces
PR15262 reported a bug where the following instruction: i8 getelementptr inbounds i8* bitcast ([4 x i8] addrspace(12)* @buf to i8*), i32 2 was getting folded into: addrspace(12)* getelementptr inbounds ([4 x i8] addrspace(12)* @buf, i32 0, i32 2) This caused instcombine to crash because the original instruction and the folded instruction have different types. The issue was fixed by disallowing bitcasts between different address spaces to be folded away. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176156 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5e5974f51a
commit
8df7c39976
@ -1971,21 +1971,30 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
|
||||
}
|
||||
}
|
||||
|
||||
// Implement folding of:
|
||||
// i32* getelementptr ([2 x i32]* bitcast ([3 x i32]* %X to [2 x i32]*),
|
||||
// i64 0, i64 0)
|
||||
// To: i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
|
||||
// Attempt to fold casts to the same type away. For example, folding:
|
||||
//
|
||||
// i32* getelementptr ([2 x i32]* bitcast ([3 x i32]* %X to [2 x i32]*),
|
||||
// i64 0, i64 0)
|
||||
// into:
|
||||
//
|
||||
// i32* getelementptr ([3 x i32]* %X, i64 0, i64 0)
|
||||
//
|
||||
// Don't fold if the cast is changing address spaces.
|
||||
if (CE->isCast() && Idxs.size() > 1 && Idx0->isNullValue()) {
|
||||
if (PointerType *SPT =
|
||||
dyn_cast<PointerType>(CE->getOperand(0)->getType()))
|
||||
if (ArrayType *SAT = dyn_cast<ArrayType>(SPT->getElementType()))
|
||||
if (ArrayType *CAT =
|
||||
dyn_cast<ArrayType>(cast<PointerType>(C->getType())->getElementType()))
|
||||
if (CAT->getElementType() == SAT->getElementType())
|
||||
return
|
||||
ConstantExpr::getGetElementPtr((Constant*)CE->getOperand(0),
|
||||
Idxs, inBounds);
|
||||
PointerType *SrcPtrTy =
|
||||
dyn_cast<PointerType>(CE->getOperand(0)->getType());
|
||||
PointerType *DstPtrTy = dyn_cast<PointerType>(CE->getType());
|
||||
if (SrcPtrTy && DstPtrTy) {
|
||||
ArrayType *SrcArrayTy =
|
||||
dyn_cast<ArrayType>(SrcPtrTy->getElementType());
|
||||
ArrayType *DstArrayTy =
|
||||
dyn_cast<ArrayType>(DstPtrTy->getElementType());
|
||||
if (SrcArrayTy && DstArrayTy
|
||||
&& SrcArrayTy->getElementType() == DstArrayTy->getElementType()
|
||||
&& SrcPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace())
|
||||
return ConstantExpr::getGetElementPtr((Constant*)CE->getOperand(0),
|
||||
Idxs, inBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,4 +447,24 @@ define i32* @fZ() nounwind {
|
||||
ret i32* %t
|
||||
}
|
||||
|
||||
; PR15262 - Check GEP folding with casts between address spaces.
|
||||
|
||||
@p0 = global [4 x i8] zeroinitializer, align 1
|
||||
@p12 = addrspace(12) global [4 x i8] zeroinitializer, align 1
|
||||
|
||||
define i8* @different_addrspace() nounwind noinline {
|
||||
; OPT: different_addrspace
|
||||
%p = getelementptr inbounds i8* bitcast ([4 x i8] addrspace(12)* @p12 to i8*),
|
||||
i32 2
|
||||
ret i8* %p
|
||||
; OPT: ret i8* getelementptr (i8* bitcast ([4 x i8] addrspace(12)* @p12 to i8*), i32 2)
|
||||
}
|
||||
|
||||
define i8* @same_addrspace() nounwind noinline {
|
||||
; OPT: same_addrspace
|
||||
%p = getelementptr inbounds i8* bitcast ([4 x i8] * @p0 to i8*), i32 2
|
||||
ret i8* %p
|
||||
; OPT: ret i8* getelementptr inbounds ([4 x i8]* @p0, i32 0, i32 2)
|
||||
}
|
||||
|
||||
; CHECK: attributes #0 = { nounwind }
|
||||
|
Loading…
Reference in New Issue
Block a user