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 @@ -1615,8 +1615,11 @@ // one other value was stored into it, we can just change the // initializer to be the stored value, then delete all stores to the // global. This allows us to mark it constant. + // This is restricted to address space 0 globals. NVPTX, for example, + // does not support initializers for shared memory (AS 3). if (SOVConstant && SOVConstant->getType() == GV->getValueType() && - isa(GV->getInitializer())) { + isa(GV->getInitializer()) && + GV->getType()->getAddressSpace() == 0) { // Change the initial value here. GV->setInitializer(SOVConstant); diff --git a/llvm/test/Transforms/GlobalOpt/address_space_initializer.ll b/llvm/test/Transforms/GlobalOpt/address_space_initializer.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/address_space_initializer.ll @@ -0,0 +1,29 @@ +; RUN: opt -passes=globalopt < %s -S | FileCheck %s + +; Check that we don't try to set a global initializer for non AS(0) globals. + +@g0 = internal global i16 undef +@g1 = internal addrspace(3) global i16 undef +; CHECK: internal unnamed_addr constant i16 3 +; CHECK: internal unnamed_addr addrspace(3) global i16 undef + +define void @a() { + store i16 3, i16* @g0, align 8 + store i16 5, i16* addrspacecast (i16 addrspace(3)* @g1 to i16*), align 8 + ret void +} + +define i8 @get0() optnone noinline { + %bc = bitcast i16* @g0 to i8* + %gep = getelementptr i8, i8* %bc, i64 1 + %r = load i8, i8* %gep + ret i8 %r +} +define i8 @get1() { + %ac = addrspacecast i16 addrspace(3)* @g1 to i16* + %bc = bitcast i16* %ac to i8* + %gep = getelementptr i8, i8* %bc, i64 1 + %r = load i8, i8* %gep + ret i8 %r +} +