diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1432,8 +1432,13 @@ if (ByValAlignment > 0) Alignment = std::max(Alignment, Align(ByValAlignment)); + // If we have a byval for a pointer type with a specific address space, we + // have to use that same address space when inlining the function, so the + // alloca should be in that address space. + auto AllocaAddressSpace = Arg->getType()->getPointerAddressSpace(); + Value *NewAlloca = - new AllocaInst(ByValType, DL.getAllocaAddrSpace(), nullptr, Alignment, + new AllocaInst(ByValType, AllocaAddressSpace, nullptr, Alignment, Arg->getName(), &*Caller->begin()->begin()); IFI.StaticAllocas.push_back(cast(NewAlloca)); diff --git a/llvm/test/Transforms/Inline/byval-different-addrspace.ll b/llvm/test/Transforms/Inline/byval-different-addrspace.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/Inline/byval-different-addrspace.ll @@ -0,0 +1,24 @@ +; RUN: opt -always-inline %s -S | FileCheck %s + +declare void @consume_ptr(i32 addrspace(3)*); + +define void @inlinee(i32 addrspace(3)* byval(i32) %this) #0 { + call void @consume_ptr(i32 addrspace(3) *%this); + ret void +} + +define void @inliner() { + %ptr = alloca i32, addrspace(3); + call void @inlinee(i32 addrspace(3) *%ptr); + ret void +} + +attributes #0 = { alwaysinline } + +; CHECK: define void @inliner() + +; This call is inlined into @inliner from @inlinee +; CHECK-DAG: call void @consume_ptr(i32 addrspace(3)* %[[ALLOCA:.*]]) + +; Check that the alloca that was created by -always-inline is in address space 3 +; CHECK-DAG: %[[ALLOCA]] = alloca i32, align 4, addrspace(3)