diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2459,9 +2459,11 @@
address space 0, this property only affects the default value to be used
when creating globals without additional contextual information (e.g. in
LLVM passes).
-``A
``
- Specifies the address space of objects created by '``alloca``'.
- Defaults to the default address space of 0.
+``A::...``
+ Specifies the valid address spaces in which ``alloca`` can create
+ objects. The address space immediately following the ``A`` is
+ the default alloca address space. If omitted, the default is that
+ ``alloca`` should return pointers in address space 0.
``p[n]::::``
This specifies the *size* of a pointer and its ```` and
````\erred alignments for address space ``n``. The fourth parameter
@@ -9551,8 +9553,7 @@
The '``alloca``' instruction allocates memory on the stack frame of the
currently executing function, to be automatically released when this
-function returns to its caller. The object is always allocated in the
-address space for allocas indicated in the datalayout.
+function returns to its caller.
Arguments:
""""""""""
@@ -9583,6 +9584,12 @@
pointer may not be unique. The order in which memory is allocated (ie.,
which way the stack grows) is not specified.
+If not explicitly specified, the result is allocated in the default
+alloca address space for the target. Note that the set of valid address
+spaces for alloca is specified in the target's datalayout; see
+:ref:`datalayout string` for more on alloca address
+spaces.
+
If the returned pointer is used by :ref:`llvm.lifetime.start `,
the returned object is initially dead.
See :ref:`llvm.lifetime.start ` and
diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
--- a/llvm/include/llvm/IR/DataLayout.h
+++ b/llvm/include/llvm/IR/DataLayout.h
@@ -121,7 +121,7 @@
/// Defaults to false.
bool BigEndian;
- unsigned AllocaAddrSpace;
+ SmallVector AllocaAddrSpaces;
MaybeAlign StackNaturalAlign;
unsigned ProgramAddrSpace;
unsigned DefaultGlobalsAddrSpace;
@@ -211,7 +211,7 @@
clear();
StringRepresentation = DL.StringRepresentation;
BigEndian = DL.isBigEndian();
- AllocaAddrSpace = DL.AllocaAddrSpace;
+ AllocaAddrSpaces = DL.AllocaAddrSpaces;
StackNaturalAlign = DL.StackNaturalAlign;
FunctionPtrAlign = DL.FunctionPtrAlign;
TheFunctionPtrAlignType = DL.TheFunctionPtrAlignType;
@@ -276,7 +276,17 @@
return *StackNaturalAlign;
}
- unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; }
+ /// Return the address spaces in which we can alloca.
+ ArrayRef getAllocaAddrSpaces() const { return AllocaAddrSpaces; }
+
+ /// Return true if we can alloca in the given address space.
+ bool isAllocaAddrSpace(unsigned AddrSpace) const {
+ ArrayRef AllocaSpaces = getAllocaAddrSpaces();
+ return is_contained(AllocaSpaces, AddrSpace);
+ }
+
+ // Return the default alloca address space.
+ unsigned getAllocaAddrSpace() const { return getAllocaAddrSpaces().front(); }
/// Returns the alignment of function pointers, which may or may not be
/// related to the alignment of functions.
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -180,7 +180,7 @@
LayoutMap = nullptr;
BigEndian = false;
- AllocaAddrSpace = 0;
+ AllocaAddrSpaces.clear();
StackNaturalAlign.reset();
ProgramAddrSpace = 0;
DefaultGlobalsAddrSpace = 0;
@@ -476,9 +476,20 @@
return Err;
break;
}
- case 'A': { // Default stack/alloca address space.
- if (Error Err = getAddrSpace(Tok, AllocaAddrSpace))
- return Err;
+ case 'A': { // Alloca address spaces. The first one is the default.
+ while (true) {
+ unsigned AddrSpace;
+ if (Error Err = getAddrSpace(Tok, AddrSpace))
+ return Err;
+ if (isAllocaAddrSpace(AddrSpace))
+ return reportError(
+ "Duplicate alloca address space in datalayout string");
+ AllocaAddrSpaces.push_back(AddrSpace);
+ if (Rest.empty())
+ break;
+ if (Error Err = split(Rest, ':', Split))
+ return Err;
+ }
break;
}
case 'G': { // Default address space for global variables.
@@ -523,6 +534,10 @@
}
}
+ // If no alloca address spaces specified, default to address space 0.
+ if (AllocaAddrSpaces.empty())
+ AllocaAddrSpaces.push_back(0);
+
return Error::success();
}
@@ -534,7 +549,7 @@
bool DataLayout::operator==(const DataLayout &Other) const {
bool Ret = BigEndian == Other.BigEndian &&
- AllocaAddrSpace == Other.AllocaAddrSpace &&
+ getAllocaAddrSpaces() == Other.getAllocaAddrSpaces() &&
StackNaturalAlign == Other.StackNaturalAlign &&
ProgramAddrSpace == Other.ProgramAddrSpace &&
DefaultGlobalsAddrSpace == Other.DefaultGlobalsAddrSpace &&
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3802,10 +3802,8 @@
void Verifier::visitAllocaInst(AllocaInst &AI) {
SmallPtrSet Visited;
PointerType *PTy = AI.getType();
- // TODO: Relax this restriction?
- Assert(PTy->getAddressSpace() == DL.getAllocaAddrSpace(),
- "Allocation instruction pointer not in the stack address space!",
- &AI);
+ Assert(DL.isAllocaAddrSpace(PTy->getAddressSpace()),
+ "Allocation instruction pointer not in a stack address space!", &AI);
Assert(AI.getAllocatedType()->isSized(&Visited),
"Cannot allocate unsized type", &AI);
Assert(AI.getArraySize()->getType()->isIntegerTy(),
diff --git a/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-0.ll b/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-0.ll
--- a/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-0.ll
+++ b/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-0.ll
@@ -2,7 +2,7 @@
target datalayout = "A1"
-; CHECK: Allocation instruction pointer not in the stack address space!
+; CHECK: Allocation instruction pointer not in a stack address space!
; CHECK-NEXT: %alloca_scalar_no_align = alloca i32, align 4, addrspace(2)
define void @use_alloca() {
diff --git a/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-1.ll b/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-1.ll
--- a/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-1.ll
+++ b/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-1.ll
@@ -2,7 +2,7 @@
target datalayout = "A1"
-; CHECK: Allocation instruction pointer not in the stack address space!
+; CHECK: Allocation instruction pointer not in a stack address space!
; CHECK-NEXT: %alloca_scalar_no_align = alloca i32, align 4, addrspace(2)
define void @use_alloca() {
diff --git a/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-2.ll b/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-2.ll
--- a/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-2.ll
+++ b/llvm/test/Assembler/datalayout-alloca-addrspace-mismatch-2.ll
@@ -2,7 +2,7 @@
target datalayout = "A1"
-; CHECK: Allocation instruction pointer not in the stack address space!
+; CHECK: Allocation instruction pointer not in a stack address space!
; CHECK-NEXT: %alloca_scalar_no_align = alloca i32, align 4, addrspace(2), !foo !0
define void @use_alloca() {
diff --git a/llvm/test/Assembler/drop-debug-info-nonzero-alloca.ll b/llvm/test/Assembler/drop-debug-info-nonzero-alloca.ll
--- a/llvm/test/Assembler/drop-debug-info-nonzero-alloca.ll
+++ b/llvm/test/Assembler/drop-debug-info-nonzero-alloca.ll
@@ -12,7 +12,7 @@
metadata i8* undef,
metadata !DILocalVariable(scope: !1),
metadata !DIExpression())
-; ALL-NOT: Allocation instruction pointer not in the stack address space!
+; ALL-NOT: Allocation instruction pointer not in a stack address space!
; AS: llvm.dbg.value intrinsic requires a !dbg attachment
; AS: warning: ignoring invalid debug info in
ret void
diff --git a/llvm/test/CodeGen/AMDGPU/invalid-alloca.ll b/llvm/test/CodeGen/AMDGPU/invalid-alloca.ll
--- a/llvm/test/CodeGen/AMDGPU/invalid-alloca.ll
+++ b/llvm/test/CodeGen/AMDGPU/invalid-alloca.ll
@@ -5,7 +5,7 @@
; RUN: llvm-as < %s | not opt -data-layout=A5 2>&1 | FileCheck -check-prefixes=MISMATCH %s
; AS: assembly parsed, but does not verify as correct!
-; COMMON: Allocation instruction pointer not in the stack address space!
+; COMMON: Allocation instruction pointer not in a stack address space!
; COMMON: %tmp = alloca i32
; MISMATCH: Explicit load/store type does not match pointee type of pointer operand
; LLC: error: {{.*}}input module cannot be verified
diff --git a/llvm/test/Verifier/alloca-alternate-addrspace-invalid-0.ll b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-0.ll
new file mode 100644
--- /dev/null
+++ b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-0.ll
@@ -0,0 +1,9 @@
+; RUN: not llvm-as %s 2>&1 | FileCheck %s
+
+target datalayout = "A1"
+
+define void @use_alloca() {
+; CHECK: Allocation instruction pointer not in a stack address space!
+ %alloca_scalar_no_align = alloca i32, addrspace(2)
+ ret void
+}
diff --git a/llvm/test/Verifier/alloca-alternate-addrspace-invalid-1.ll b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-1.ll
new file mode 100644
--- /dev/null
+++ b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-1.ll
@@ -0,0 +1,9 @@
+; RUN: not llvm-as %s 2>&1 | FileCheck %s
+
+target datalayout = "A1:3"
+
+define void @use_alloca() {
+; CHECK: Allocation instruction pointer not in a stack address space!
+ %alloca_scalar_no_align = alloca i32, addrspace(2)
+ ret void
+}
diff --git a/llvm/test/Verifier/alloca-alternate-addrspace-invalid-2.ll b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-2.ll
new file mode 100644
--- /dev/null
+++ b/llvm/test/Verifier/alloca-alternate-addrspace-invalid-2.ll
@@ -0,0 +1,9 @@
+; RUN: not llvm-as < %s 2>&1 | FileCheck %s
+
+target datalayout = ""
+
+define void @use_alloca() {
+; CHECK: Allocation instruction pointer not in a stack address space!
+ %alloca_scalar_no_align = alloca i32, addrspace(2)
+ ret void
+}
diff --git a/llvm/test/Verifier/alloca-alternate-addrspace-valid.ll b/llvm/test/Verifier/alloca-alternate-addrspace-valid.ll
new file mode 100644
--- /dev/null
+++ b/llvm/test/Verifier/alloca-alternate-addrspace-valid.ll
@@ -0,0 +1,22 @@
+; RUN: llvm-as %s -o /dev/null
+
+; Should assemble without error.
+
+target datalayout = "A1:2:3"
+
+define void @use_alloca0() {
+ %alloca_scalar_no_align = alloca i32, addrspace(2)
+ ret void
+}
+
+define void @use_alloca1() {
+ %alloca_scalar_no_align = alloca i32, align 4, addrspace(2)
+ ret void
+}
+
+define void @use_alloca2() {
+ %alloca_scalar_no_align = alloca i32, align 4, addrspace(2), !foo !0
+ ret void
+}
+
+!0 = !{}