From 6874a2ae033b7b5e1d0c10714e01d9c87480956a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 18 Aug 2009 14:58:19 +0000 Subject: [PATCH] Fix a bug that caused globalopt to miscompile tramp3d: don't miss unruly indices for arrays that are members of structs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79337 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/GlobalOpt.cpp | 11 +++-- .../GlobalOpt/globalsra-unknown-index.ll | 41 +++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 test/Transforms/GlobalOpt/globalsra-unknown-index.ll diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 46ff307c755..6ec20126d74 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(*GEPI) || isa(*GEPI)); + GEPI != E; ++GEPI) { uint64_t NumElements; if (const ArrayType *SubArrayTy = dyn_cast(*GEPI)) NumElements = SubArrayTy->getNumElements(); - else - NumElements = cast(*GEPI)->getNumElements(); + else if (const VectorType *SubVectorTy = dyn_cast(*GEPI)) + NumElements = SubVectorTy->getNumElements(); + else { + assert(isa(*GEPI) && + "Indexed GEP type is not array, vector, or struct!"); + continue; + } ConstantInt *IdxVal = dyn_cast(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 00000000000..7a5d5b7ebad --- /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 +} -- 2.34.1