summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMeador Inge <meadori@codesourcery.com>2013-02-27 02:26:42 +0000
committerMeador Inge <meadori@codesourcery.com>2013-02-27 02:26:42 +0000
commit9b47f6414b7315f399376e90fa8a482b63efe3ee (patch)
treea99579e8cc34e606ae10433ee9aba3eabd082f4b
parenta8fbdab8501f0470da8bf414d52473749aaf8c24 (diff)
downloadbcm5719-llvm-9b47f6414b7315f399376e90fa8a482b63efe3ee.tar.gz
bcm5719-llvm-9b47f6414b7315f399376e90fa8a482b63efe3ee.zip
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. llvm-svn: 176156
-rw-r--r--llvm/lib/IR/ConstantFold.cpp35
-rw-r--r--llvm/test/Other/constant-fold-gep.ll20
2 files changed, 42 insertions, 13 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index a5a9d9f3a7c..bf93d4f9566 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -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);
+ }
}
}
diff --git a/llvm/test/Other/constant-fold-gep.ll b/llvm/test/Other/constant-fold-gep.ll
index 0224e9f984c..44b66284dd7 100644
--- a/llvm/test/Other/constant-fold-gep.ll
+++ b/llvm/test/Other/constant-fold-gep.ll
@@ -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 }
OpenPOWER on IntegriCloud