diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -1012,12 +1012,9 @@ continue; // Otherwise, storing through it, or storing into GV... fine. } - // Must index into the array and into the struct. - if (isa(Inst) && Inst->getNumOperands() >= 3) { - if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Inst, GV, PHIs)) - return false; - continue; - } + // Cannot handle GEP. + if (isa(Inst)) + return false; if (const PHINode *PN = dyn_cast(Inst)) { // PHIs are ok if all uses are ok. Don't infinitely recurse through PHI diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll --- a/llvm/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll +++ b/llvm/test/Transforms/GlobalOpt/heap-sra-2-no-null-opt.ll @@ -9,8 +9,7 @@ define void @bar(i32 %Size) nounwind noinline #0 { entry: %malloccall = tail call i8* @malloc(i64 8000000) ; [#uses=1] - %0 = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1] - %.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %0, i32 0, i32 0 ; <%struct.foo*> [#uses=1] + %.sub = bitcast i8* %malloccall to %struct.foo* store %struct.foo* %.sub, %struct.foo** @X, align 4 ret void } diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-2.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-2.ll --- a/llvm/test/Transforms/GlobalOpt/heap-sra-2.ll +++ b/llvm/test/Transforms/GlobalOpt/heap-sra-2.ll @@ -9,8 +9,7 @@ define void @bar(i32 %Size) nounwind noinline { entry: %malloccall = tail call i8* @malloc(i64 8000000) ; [#uses=1] - %0 = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1] - %.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %0, i32 0, i32 0 ; <%struct.foo*> [#uses=1] + %.sub = bitcast i8* %malloccall to %struct.foo* store %struct.foo* %.sub, %struct.foo** @X, align 4 ret void } diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-negative.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-negative.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/heap-sra-negative.ll @@ -0,0 +1,31 @@ +; RUN: opt < %s -S -passes=globalopt | FileCheck %s + +;; PR50027: Suppress SROA because we cannot represent GEP of the only storer. +; CHECK: @X = internal unnamed_addr global %struct.foo* null + +target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" + +%struct.foo = type { i32, i32 } + +@X = internal global %struct.foo* null + +declare noalias i8* @malloc(i64) + +define void @test(i32 %Size) { +entry: + %buf = tail call i8* @malloc(i64 8000000) + %buf1 = bitcast i8* %buf to [1000000 x %struct.foo]* + + ;; GEP of the only storer. + %buf.gep = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %buf1, i32 0, i32 0 + store %struct.foo zeroinitializer, %struct.foo* %buf.gep, align 4 + + store %struct.foo* %buf.gep, %struct.foo** @X, align 4 + ret void +} + +define i32 @user() { +entry: + %unused = load %struct.foo*, %struct.foo** @X, align 4 + ret i32 0 +} diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll --- a/llvm/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll +++ b/llvm/test/Transforms/GlobalOpt/heap-sra-phi-no-null-opt.ll @@ -11,8 +11,7 @@ ; CHECK-LABEL: @bar( entry: %malloccall = tail call i8* @malloc(i64 8000000) ; [#uses=1] - %tmp = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1] - %.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %tmp, i32 0, i32 0 ; <%struct.foo*> [#uses=1] + %.sub = bitcast i8* %malloccall to %struct.foo* store %struct.foo* %.sub, %struct.foo** @X, align 4 ret void } diff --git a/llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll b/llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll --- a/llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll +++ b/llvm/test/Transforms/GlobalOpt/heap-sra-phi.ll @@ -9,8 +9,7 @@ define void @bar(i32 %Size) nounwind noinline { entry: %malloccall = tail call i8* @malloc(i64 8000000) ; [#uses=1] - %tmp = bitcast i8* %malloccall to [1000000 x %struct.foo]* ; <[1000000 x %struct.foo]*> [#uses=1] - %.sub = getelementptr [1000000 x %struct.foo], [1000000 x %struct.foo]* %tmp, i32 0, i32 0 ; <%struct.foo*> [#uses=1] + %.sub = bitcast i8* %malloccall to %struct.foo* store %struct.foo* %.sub, %struct.foo** @X, align 4 ret void }