diff options
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 11 | ||||
-rw-r--r-- | test/Transforms/GlobalOpt/globalsra-unknown-index.ll | 41 |
2 files changed, 49 insertions, 3 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 46ff307..6ec2012 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -426,13 +426,18 @@ static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) { // Scalar replacing *just* the outer index of the array is probably not // going to be a win anyway, so just give up. for (++GEPI; // Skip array index. - GEPI != E && (isa<ArrayType>(*GEPI) || isa<VectorType>(*GEPI)); + GEPI != E; ++GEPI) { uint64_t NumElements; if (const ArrayType *SubArrayTy = dyn_cast<ArrayType>(*GEPI)) NumElements = SubArrayTy->getNumElements(); - else - NumElements = cast<VectorType>(*GEPI)->getNumElements(); + else if (const VectorType *SubVectorTy = dyn_cast<VectorType>(*GEPI)) + NumElements = SubVectorTy->getNumElements(); + else { + assert(isa<StructType>(*GEPI) && + "Indexed GEP type is not array, vector, or struct!"); + continue; + } ConstantInt *IdxVal = dyn_cast<ConstantInt>(GEPI.getOperand()); if (!IdxVal || IdxVal->getZExtValue() >= NumElements) diff --git a/test/Transforms/GlobalOpt/globalsra-unknown-index.ll b/test/Transforms/GlobalOpt/globalsra-unknown-index.ll new file mode 100644 index 0000000..7a5d5b7 --- /dev/null +++ b/test/Transforms/GlobalOpt/globalsra-unknown-index.ll @@ -0,0 +1,41 @@ +; RUN: llvm-as < %s | opt -globalopt | llvm-dis > %t +; RUN: grep {@Y = internal global \\\[3 x \[%\]struct.X\\\] zeroinitializer} %t +; RUN: grep load %t | count 6 +; RUN: grep {add i32 \[%\]a, \[%\]b} %t | count 3 + +; globalopt should not sra the global, because it can't see the index. + +%struct.X = type { [3 x i32], [3 x i32] } + +@Y = internal global [3 x %struct.X] zeroinitializer + +@addr = external global i8 + +define void @frob() { + store i32 1, i32* getelementptr inbounds ([3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 ptrtoint (i8* @addr to i64)), align 4 + ret void +} +define i32 @borf(i64 %i, i64 %j) { + %p = getelementptr inbounds [3 x %struct.X]* @Y, i64 0, i64 0, i32 0, i64 0 + %a = load i32* %p + %q = getelementptr inbounds [3 x %struct.X]* @Y, i64 0, i64 0, i32 1, i64 0 + %b = load i32* %q + %c = add i32 %a, %b + ret i32 %c +} +define i32 @borg(i64 %i, i64 %j) { + %p = getelementptr inbounds [3 x %struct.X]* @Y, i64 0, i64 1, i32 0, i64 1 + %a = load i32* %p + %q = getelementptr inbounds [3 x %struct.X]* @Y, i64 0, i64 1, i32 1, i64 1 + %b = load i32* %q + %c = add i32 %a, %b + ret i32 %c +} +define i32 @borh(i64 %i, i64 %j) { + %p = getelementptr inbounds [3 x %struct.X]* @Y, i64 0, i64 2, i32 0, i64 2 + %a = load i32* %p + %q = getelementptr inbounds [3 x %struct.X]* @Y, i64 0, i64 2, i32 1, i64 2 + %b = load i32* %q + %c = add i32 %a, %b + ret i32 %c +} |