diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 6a2e173d6c0c..4cc00f181f5d 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -1672,11 +1672,25 @@ processInternalGlobal(GlobalVariable *GV, const GlobalStatus &GS, // This is restricted to address spaces that allow globals to have // initializers. NVPTX, for example, does not support initializers for // shared memory (AS 3). - if (SOVConstant && SOVConstant->getType() == GV->getValueType() && - isa(GV->getInitializer()) && + if (SOVConstant && isa(GV->getInitializer()) && + DL.getTypeAllocSize(SOVConstant->getType()) == + DL.getTypeAllocSize(GV->getValueType()) && CanHaveNonUndefGlobalInitializer) { - // Change the initial value here. - GV->setInitializer(SOVConstant); + if (SOVConstant->getType() == GV->getValueType()) { + // Change the initializer in place. + GV->setInitializer(SOVConstant); + } else { + // Create a new global with adjusted type. + auto *NGV = new GlobalVariable( + *GV->getParent(), SOVConstant->getType(), GV->isConstant(), + GV->getLinkage(), SOVConstant, "", GV, GV->getThreadLocalMode(), + GV->getAddressSpace()); + NGV->takeName(GV); + NGV->copyAttributesFrom(GV); + GV->replaceAllUsesWith(ConstantExpr::getBitCast(NGV, GV->getType())); + GV->eraseFromParent(); + GV = NGV; + } // Clean up any obviously simplifiable users now. CleanupConstantGlobalUsers(GV, DL); diff --git a/llvm/test/Transforms/GlobalOpt/stored-once-different-type.ll b/llvm/test/Transforms/GlobalOpt/stored-once-different-type.ll new file mode 100644 index 000000000000..a4fac27e7f6e --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/stored-once-different-type.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals +; RUN: opt -S -globalopt < %s | FileCheck %s + +@g = internal global [4 x i8] undef + +;. +; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr constant i32 42 +;. +define void @store() { +; CHECK-LABEL: @store( +; CHECK-NEXT: ret void +; + store i32 42, i32* bitcast ([4 x i8]* @g to i32*) + ret void +} + +define i32 @load1() { +; CHECK-LABEL: @load1( +; CHECK-NEXT: ret i32 42 +; + %v = load i32, i32* bitcast ([4 x i8]* @g to i32*) + ret i32 %v +} + +define i16 @load2() { +; CHECK-LABEL: @load2( +; CHECK-NEXT: ret i16 42 +; + %v = load i16, i16* bitcast ([4 x i8]* @g to i16*) + ret i16 %v +} + +define [4 x i8] @load3() { +; CHECK-LABEL: @load3( +; CHECK-NEXT: [[V:%.*]] = load [4 x i8], [4 x i8]* bitcast (i32* @g to [4 x i8]*), align 1 +; CHECK-NEXT: ret [4 x i8] [[V]] +; + %v = load [4 x i8], [4 x i8]* @g + ret [4 x i8] %v +} diff --git a/llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll b/llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll index a0b0e6c1be01..a971f74f3d77 100644 --- a/llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll +++ b/llvm/test/Transforms/GlobalOpt/stored-once-value-type.ll @@ -8,13 +8,8 @@ @0 = internal global %T* null -;. -; CHECK: @[[_BODY:[a-zA-Z0-9_$"\\.-]+]] = internal unnamed_addr global [[T:%.*]] undef -;. define void @a() { ; CHECK-LABEL: @a( -; CHECK-NEXT: store i32* null, i32** getelementptr inbounds ([[T:%.*]], %T* @.body, i64 0, i32 0), align 8 -; CHECK-NEXT: [[TMP1:%.*]] = load atomic i64, i64* bitcast (%T* @.body to i64*) acquire, align 8 ; CHECK-NEXT: ret void ; %1 = tail call i8* @_Znwm(i64 8)