[clang] 4fefed6 - OpaquePtr: Turn inalloca into a type attribute

Matt Arsenault via cfe-commits cfe-commits at lists.llvm.org
Sun Mar 28 08:12:37 PDT 2021


Author: Matt Arsenault
Date: 2021-03-28T11:12:23-04:00
New Revision: 4fefed65637ec46c8c2edad6b07b5569ac61e9e5

URL: https://github.com/llvm/llvm-project/commit/4fefed65637ec46c8c2edad6b07b5569ac61e9e5
DIFF: https://github.com/llvm/llvm-project/commit/4fefed65637ec46c8c2edad6b07b5569ac61e9e5.diff

LOG: OpaquePtr: Turn inalloca into a type attribute

I think byval/sret and the others are close to being able to rip out
the code to support the missing type case. A lot of this code is
shared with inalloca, so catch this up to the others so that can
happen.

Added: 
    llvm/test/Assembler/inalloca-parse-error0.ll
    llvm/test/Bitcode/Inputs/inalloca-upgrade.bc
    llvm/test/Bitcode/inalloca-upgrade.test
    llvm/test/Linker/Inputs/inalloca-type-input.ll
    llvm/test/Linker/inalloca-types.ll

Modified: 
    clang/lib/CodeGen/CGCall.cpp
    clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp
    clang/test/CodeGenCXX/inalloca-overaligned.cpp
    clang/test/CodeGenCXX/inalloca-vector.cpp
    clang/test/CodeGenCXX/inheriting-constructor.cpp
    clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
    clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
    clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
    clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
    clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
    clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
    clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
    clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
    clang/test/CodeGenCXX/ms-thunks-ehspec.cpp
    clang/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
    clang/test/CodeGenObjCXX/arc-indirect.mm
    clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
    llvm/docs/LangRef.rst
    llvm/docs/ReleaseNotes.rst
    llvm/include/llvm/IR/Argument.h
    llvm/include/llvm/IR/Attributes.h
    llvm/include/llvm/IR/Attributes.td
    llvm/include/llvm/IR/Function.h
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/AsmParser/LLParser.h
    llvm/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/AttributeImpl.h
    llvm/lib/IR/Attributes.cpp
    llvm/lib/IR/Function.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/lib/Linker/IRMover.cpp
    llvm/lib/Transforms/Utils/ValueMapper.cpp
    llvm/test/Assembler/invalid-immarg.ll
    llvm/test/Bitcode/attributes.ll
    llvm/test/Bitcode/compatibility-3.6.ll
    llvm/test/Bitcode/compatibility-3.7.ll
    llvm/test/Bitcode/compatibility-3.8.ll
    llvm/test/Bitcode/compatibility-3.9.ll
    llvm/test/Bitcode/compatibility-4.0.ll
    llvm/test/Bitcode/compatibility-5.0.ll
    llvm/test/Bitcode/compatibility-6.0.ll
    llvm/test/Bitcode/compatibility.ll
    llvm/test/Bitcode/inalloca.ll
    llvm/test/CodeGen/X86/arg-copy-elide.ll
    llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
    llvm/test/CodeGen/X86/inalloca-ctor.ll
    llvm/test/CodeGen/X86/inalloca-invoke.ll
    llvm/test/CodeGen/X86/inalloca-regparm.ll
    llvm/test/CodeGen/X86/inalloca-stdcall.ll
    llvm/test/CodeGen/X86/inalloca.ll
    llvm/test/CodeGen/X86/movtopush.ll
    llvm/test/CodeGen/X86/musttail-inalloca.ll
    llvm/test/CodeGen/X86/musttail-indirect.ll
    llvm/test/CodeGen/X86/musttail-thiscall.ll
    llvm/test/CodeGen/X86/shrink-wrap-chkstk.ll
    llvm/test/CodeGen/X86/tail-call-mutable-memarg.ll
    llvm/test/CodeGen/X86/x86-repmov-copy-eflags.ll
    llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll
    llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll
    llvm/test/Transforms/ArgumentPromotion/X86/thiscall.ll
    llvm/test/Transforms/ArgumentPromotion/inalloca.ll
    llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll
    llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll
    llvm/test/Transforms/Attributor/readattrs.ll
    llvm/test/Transforms/Attributor/value-simplify.ll
    llvm/test/Transforms/DeadArgElim/keepalive.ll
    llvm/test/Transforms/DeadStoreElimination/simple.ll
    llvm/test/Transforms/FunctionAttrs/readattrs.ll
    llvm/test/Transforms/GVNHoist/hoist-pr28606.ll
    llvm/test/Transforms/GlobalOpt/fastcc.ll
    llvm/test/Transforms/Inline/inalloca-not-static.ll
    llvm/test/Transforms/InstCombine/alloca.ll
    llvm/test/Transforms/InstCombine/call-cast-target-inalloca.ll
    llvm/test/Transforms/InstCombine/stacksaverestore.ll
    llvm/test/Verifier/align.ll
    llvm/test/Verifier/amdgpu-cc.ll
    llvm/test/Verifier/byref.ll
    llvm/test/Verifier/byval-1.ll
    llvm/test/Verifier/inalloca-vararg.ll
    llvm/test/Verifier/inalloca1.ll
    llvm/test/Verifier/inalloca2.ll
    llvm/test/Verifier/inalloca3.ll
    llvm/test/Verifier/noundef.ll
    llvm/unittests/IR/AttributesTest.cpp
    llvm/unittests/Transforms/Utils/CloningTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index dc73e3260891c..1d71148d67e67 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2290,7 +2290,7 @@ void CodeGenModule::ConstructAttributeList(
   // Attach attributes to inalloca argument.
   if (IRFunctionArgs.hasInallocaArg()) {
     llvm::AttrBuilder Attrs;
-    Attrs.addAttribute(llvm::Attribute::InAlloca);
+    Attrs.addInAllocaAttr(FI.getArgStruct());
     ArgAttrs[IRFunctionArgs.getInallocaArgNo()] =
         llvm::AttributeSet::get(getLLVMContext(), Attrs);
   }

diff  --git a/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp b/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp
index a611587b56f72..be9fc941c4809 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp
@@ -16,20 +16,20 @@ void usage() {
   bar(f);
 }
 
-// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z"(<{ %struct.Foo }>* inalloca %0)
+// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z"(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %0)
 // WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
 // WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
 // WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
 // WINDOWS: ret i32 %[[LOAD]]
 
-// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* inalloca %0)
+// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %0)
 // WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
 // WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
 // WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
 // WINDOWS: %[[ADD:[0-9a-zA-Z]+]] = add nsw i32 %[[LOAD]], 1
 // WINDOWS: ret i32 %[[ADD]]
 
-// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* inalloca %0)
+// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %0)
 // WINDOWS: %[[O:[0-9a-zA-Z]+]] = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
 // WINDOWS: %[[X:[0-9a-zA-Z]+]] = getelementptr inbounds %struct.Foo, %struct.Foo* %[[O]], i32 0, i32 0
 // WINDOWS: %[[LOAD:[0-9a-zA-Z]+]] = load i32, i32* %[[X]]
@@ -39,7 +39,7 @@ void usage() {
 // WINDOWS: define dso_local void @"?usage@@YAXXZ"()
 // WINDOWS: %[[F:[0-9a-zA-Z]+]] = alloca %struct.Foo
 // WINDOWS: %[[ARGMEM:[0-9a-zA-Z]+]] = alloca inalloca <{ %struct.Foo }>
-// WINDOWS: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* inalloca %[[ARGMEM]])
+// WINDOWS: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %[[ARGMEM]])
 
 // WINDOWS: define weak_odr dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* %0)
 // WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* %0)

diff  --git a/clang/test/CodeGenCXX/inalloca-overaligned.cpp b/clang/test/CodeGenCXX/inalloca-overaligned.cpp
index 48a6183db8eb0..0a51875bb5922 100644
--- a/clang/test/CodeGenCXX/inalloca-overaligned.cpp
+++ b/clang/test/CodeGenCXX/inalloca-overaligned.cpp
@@ -28,7 +28,7 @@ int receive_inalloca_overaligned(NonTrivial nt, OverAligned o) {
 }
 
 // CHECK-LABEL: define dso_local i32 @"?receive_inalloca_overaligned@@Y{{.*}}"
-// CHECK-SAME: (<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca %0)
+// CHECK-SAME: (<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca(<{ %struct.NonTrivial, %struct.OverAligned* }>) %0)
 
 int pass_inalloca_overaligned() {
   gvi32 = receive_inalloca_overaligned(NonTrivial(), OverAligned());
@@ -50,7 +50,7 @@ int pass_inalloca_overaligned() {
 // Store the address of an OverAligned temporary into the struct.
 // CHECK: getelementptr inbounds <{ %struct.NonTrivial, %struct.OverAligned* }>, <{ %struct.NonTrivial, %struct.OverAligned* }>* %{{.*}}, i32 0, i32 1
 // CHECK: store %struct.OverAligned* [[TMP]], %struct.OverAligned** %{{.*}}, align 4
-// CHECK: call i32 @"?receive_inalloca_overaligned@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca %argmem)
+// CHECK: call i32 @"?receive_inalloca_overaligned@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.OverAligned* }>* inalloca(<{ %struct.NonTrivial, %struct.OverAligned* }>) %argmem)
 
 int receive_both(Both o) {
   return o.x + o.y;
@@ -74,7 +74,7 @@ int receive_inalloca_both(NonTrivial nt, Both o) {
 }
 
 // CHECK-LABEL: define dso_local i32 @"?receive_inalloca_both@@Y{{.*}}"
-// CHECK-SAME: (<{ %struct.NonTrivial, %struct.Both* }>* inalloca %0)
+// CHECK-SAME: (<{ %struct.NonTrivial, %struct.Both* }>* inalloca(<{ %struct.NonTrivial, %struct.Both* }>) %0)
 
 int pass_inalloca_both() {
   gvi32 = receive_inalloca_both(NonTrivial(), Both());
@@ -84,7 +84,7 @@ int pass_inalloca_both() {
 // CHECK-LABEL: define dso_local i32 @"?pass_inalloca_both@@Y{{.*}}"
 // CHECK: [[TMP:%[^ ]*]] = alloca %struct.Both, align 8
 // CHECK: call x86_thiscallcc %struct.Both* @"??0Both@@QAE at XZ"(%struct.Both* {{[^,]*}} [[TMP]])
-// CHECK: call i32 @"?receive_inalloca_both@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.Both* }>* inalloca %argmem)
+// CHECK: call i32 @"?receive_inalloca_both@@Y{{.*}}"(<{ %struct.NonTrivial, %struct.Both* }>* inalloca(<{ %struct.NonTrivial, %struct.Both* }>) %argmem)
 
 // Here we have a type that is:
 // - overaligned

diff  --git a/clang/test/CodeGenCXX/inalloca-vector.cpp b/clang/test/CodeGenCXX/inalloca-vector.cpp
index bf71fac37b6a8..e052d2e6728d6 100644
--- a/clang/test/CodeGenCXX/inalloca-vector.cpp
+++ b/clang/test/CodeGenCXX/inalloca-vector.cpp
@@ -21,7 +21,7 @@ void receive_vec_128(NonTrivial nt, __m128 x, __m128 y, __m128 z, __m128 w, __m1
 // CHECK-SAME: (<4 x float> inreg %x,
 // CHECK-SAME: <4 x float> inreg %y,
 // CHECK-SAME: <4 x float> inreg %z,
-// CHECK-SAME: <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* inalloca %0)
+// CHECK-SAME: <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* inalloca(<{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>) %0)
 
 void pass_vec_128() {
   __m128 z = {0};
@@ -45,7 +45,7 @@ void pass_vec_128() {
 // CHECK-SAME: (<4 x float> inreg %{{[^,]*}},
 // CHECK-SAME: <4 x float> inreg %{{[^,]*}},
 // CHECK-SAME: <4 x float> inreg %{{[^,]*}},
-// CHECK-SAME: <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* inalloca %{{[^,]*}})
+// CHECK-SAME: <{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>* inalloca(<{ %struct.NonTrivial, <4 x float>*, <4 x float>* }>) %{{[^,]*}})
 
 // w will be passed indirectly by register, and q will be passed indirectly, but
 // the pointer will be in memory.
@@ -58,7 +58,7 @@ void __fastcall fastcall_receive_vec(__m128 x, __m128 y, __m128 z, __m128 w, int
 // CHECK-SAME: <4 x float> inreg %z,
 // CHECK-SAME: <4 x float>* inreg %0,
 // CHECK-SAME: i32 inreg %edx,
-// CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca %1)
+// CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca(<{ <4 x float>*, %struct.NonTrivial }>) %1)
 
 
 void __vectorcall vectorcall_receive_vec(double xmm0, double xmm1, double xmm2,
@@ -75,4 +75,4 @@ void __vectorcall vectorcall_receive_vec(double xmm0, double xmm1, double xmm2,
 // CHECK-SAME: <4 x float> inreg %z,
 // CHECK-SAME: <4 x float>* inreg %0,
 // CHECK-SAME: i32 inreg %edx,
-// CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca %1)
+// CHECK-SAME: <{ <4 x float>*, %struct.NonTrivial }>* inalloca(<{ <4 x float>*, %struct.NonTrivial }>) %1)

diff  --git a/clang/test/CodeGenCXX/inheriting-constructor.cpp b/clang/test/CodeGenCXX/inheriting-constructor.cpp
index 6de8e92186dd7..c338edcc76ae4 100644
--- a/clang/test/CodeGenCXX/inheriting-constructor.cpp
+++ b/clang/test/CodeGenCXX/inheriting-constructor.cpp
@@ -134,7 +134,7 @@ namespace inalloca_nonvirt {
   // WIN32: store i32 2, i32* %[[ARG2]]
   // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
   // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
-  // WIN32: call {{.*}} @"??0A at inalloca_nonvirt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+  // WIN32: call {{.*}} @"??0A at inalloca_nonvirt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca(<{{.*}}>) %[[ARGMEM]])
   // WIN32: call void @llvm.stackrestore(
   // WIN32: call {{.*}} @"??0Z@@QAE at XZ"(
   // WIN32: call {{.*}} @"??1Q@@QAE at XZ"(
@@ -170,7 +170,7 @@ namespace inalloca_nonvirt {
   // WIN32: store i32 2, i32* %[[ARG2]]
   // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
   // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
-  // WIN32: call {{.*}} @"??0A at inalloca_nonvirt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+  // WIN32: call {{.*}} @"??0A at inalloca_nonvirt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca(<{{.*}}>) %[[ARGMEM]])
   // WIN32: call void @llvm.stackrestore(
   // WIN32: call {{.*}} @"??0Z@@QAE at XZ"(
   // WIN32: call {{.*}} @"??1Q@@QAE at XZ"(
@@ -216,7 +216,7 @@ namespace inalloca_virt {
   // WIN32: store i32 2, i32* %[[ARG2]]
   // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
   // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
-  // WIN32: call {{.*}} @"??0A at inalloca_virt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+  // WIN32: call {{.*}} @"??0A at inalloca_virt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca(<{{.*}}>) %[[ARGMEM]])
   // WIN32: call void @llvm.stackrestore(
   // WIN32: br
   //
@@ -266,7 +266,7 @@ namespace inalloca_virt {
   // WIN32: store i32 2, i32* %[[ARG2]]
   // WIN32: %[[ARG4:.*]] = getelementptr {{.*}} %[[ARGMEM]]
   // WIN32: store {{.*}}* %[[TMP]], {{.*}}** %[[ARG4]]
-  // WIN32: call {{.*}} @"??0A at inalloca_virt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca %[[ARGMEM]])
+  // WIN32: call {{.*}} @"??0A at inalloca_virt@@QAE at UQ@@H0$$QAU2@@Z"(%{{[^,]*}}, <{{.*}}>* inalloca(<{{.*}}>) %[[ARGMEM]])
   // WIN32: call void @llvm.stackrestore(
   // WIN32: br
   //

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
index 4da04a43ff610..215a39ec7d489 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-arg-order.cpp
@@ -14,7 +14,7 @@ void foo(A a, A b, A c) {
 // Order of destruction should be left to right.
 //
 // X86-LABEL: define dso_local void @"?foo@@YAXUA@@00 at Z"
-// X86:          ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca %0)
+// X86:          ([[argmem_ty:<{ %struct.A, %struct.A, %struct.A }>]]* inalloca([[argmem_ty]]) %0)
 // X86: %[[a:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 0
 // X86: %[[b:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 1
 // X86: %[[c:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %0, i32 0, i32 2
@@ -47,7 +47,7 @@ void call_foo() {
 // X86: invoke x86_thiscallcc %struct.A* @"??0A@@QAE at H@Z"(%struct.A* {{[^,]*}} %[[arg2]], i32 2)
 // X86: %[[arg1:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
 // X86: invoke x86_thiscallcc %struct.A* @"??0A@@QAE at H@Z"(%struct.A* {{[^,]*}} %[[arg1]], i32 1)
-// X86: call void @"?foo@@YAXUA@@00 at Z"([[argmem_ty]]* inalloca %[[argmem]])
+// X86: call void @"?foo@@YAXUA@@00 at Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %[[argmem]])
 // X86: call void @llvm.stackrestore
 // X86: ret void
 //

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
index 7f8730080a099..adf3921f71156 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-byval-sret.cpp
@@ -19,7 +19,7 @@ A B::foo(A x) {
 }
 
 // CHECK-LABEL: define dso_local x86_thiscallcc %struct.A* @"?foo at B@@QAE?AUA@@U2@@Z"
-// CHECK:       (%struct.B* %this, <{ %struct.A*, %struct.A }>* inalloca %0)
+// CHECK:       (%struct.B* %this, <{ %struct.A*, %struct.A }>* inalloca(<{ %struct.A*, %struct.A }>) %0)
 // CHECK:   getelementptr inbounds <{ %struct.A*, %struct.A }>, <{ %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 0
 // CHECK:   load %struct.A*, %struct.A**
 // CHECK:   ret %struct.A*
@@ -29,7 +29,7 @@ A B::bar(A x) {
 }
 
 // CHECK-LABEL: define dso_local %struct.A* @"?bar at B@@QAA?AUA@@U2@@Z"
-// CHECK:       (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %0)
+// CHECK:       (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A*, %struct.A }>) %0)
 // CHECK:   getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>, <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1
 // CHECK:   load %struct.A*, %struct.A**
 // CHECK:   ret %struct.A*
@@ -39,7 +39,7 @@ A B::baz(A x) {
 }
 
 // CHECK-LABEL: define dso_local x86_stdcallcc %struct.A* @"?baz at B@@QAG?AUA@@U2@@Z"
-// CHECK:       (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %0)
+// CHECK:       (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A*, %struct.A }>) %0)
 // CHECK:   getelementptr inbounds <{ %struct.B*, %struct.A*, %struct.A }>, <{ %struct.B*, %struct.A*, %struct.A }>* %{{.*}}, i32 0, i32 1
 // CHECK:   load %struct.A*, %struct.A**
 // CHECK:   ret %struct.A*
@@ -49,7 +49,7 @@ A B::qux(A x) {
 }
 
 // CHECK-LABEL: define dso_local x86_fastcallcc void @"?qux at B@@QAI?AUA@@U2@@Z"
-// CHECK:       (%struct.B* inreg %this, %struct.A* inreg noalias sret(%struct.A) align 4 %agg.result, <{ %struct.A }>* inalloca %0)
+// CHECK:       (%struct.B* inreg %this, %struct.A* inreg noalias sret(%struct.A) align 4 %agg.result, <{ %struct.A }>* inalloca(<{ %struct.A }>) %0)
 // CHECK:   ret void
 
 int main() {
@@ -61,10 +61,10 @@ int main() {
 }
 
 // CHECK: call x86_thiscallcc %struct.A* @"?foo at B@@QAE?AUA@@U2@@Z"
-// CHECK:       (%struct.B* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
+// CHECK:       (%struct.B* %{{[^,]*}}, <{ %struct.A*, %struct.A }>* inalloca(<{ %struct.A*, %struct.A }>) %{{[^,]*}})
 // CHECK: call %struct.A* @"?bar at B@@QAA?AUA@@U2@@Z"
-// CHECK:       (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
+// CHECK:       (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A*, %struct.A }>) %{{[^,]*}})
 // CHECK: call x86_stdcallcc %struct.A* @"?baz at B@@QAG?AUA@@U2@@Z"
-// CHECK:       (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca %{{[^,]*}})
+// CHECK:       (<{ %struct.B*, %struct.A*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A*, %struct.A }>) %{{[^,]*}})
 // CHECK: call x86_fastcallcc void @"?qux at B@@QAI?AUA@@U2@@Z"
-// CHECK:       (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret(%struct.A) align 4 %{{.*}}, <{ %struct.A }>* inalloca %{{[^,]*}})
+// CHECK:       (%struct.B* inreg %{{[^,]*}}, %struct.A* inreg sret(%struct.A) align 4 %{{.*}}, <{ %struct.A }>* inalloca(<{ %struct.A }>) %{{[^,]*}})

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
index 917a7677c41e4..65e789ce5c637 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-byval-thunks.cpp
@@ -15,10 +15,10 @@ struct C : A, B { C(); virtual void foo(Agg x); };
 C::C() {} // force emission
 
 // CHECK32-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?foo at C@byval_thunk@@W3AEXUAgg at 2@@Z"
-// CHECK32:             (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca %0)
+// CHECK32:             (%"struct.byval_thunk::C"* %this, <{ %"struct.byval_thunk::Agg" }>* inalloca(<{ %"struct.byval_thunk::Agg" }>) %0)
 // CHECK32:   getelementptr i8, i8* %{{.*}}, i32 -4
 // CHECK32:   musttail call x86_thiscallcc void @"?foo at C@byval_thunk@@UAEXUAgg at 2@@Z"
-// CHECK32:       (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca %0)
+// CHECK32:       (%"struct.byval_thunk::C"* %{{.*}}, <{ %"struct.byval_thunk::Agg" }>* inalloca(<{ %"struct.byval_thunk::Agg" }>) %0)
 // CHECK32-NEXT: ret void
 
 // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo at C@byval_thunk@@W7EAAXUAgg at 2@@Z"
@@ -44,13 +44,13 @@ struct C : A, B { C(); virtual void __stdcall foo(Agg x); };
 C::C() {} // force emission
 
 // CHECK32-LABEL: define linkonce_odr dso_local x86_stdcallcc void @"?foo at C@stdcall_thunk@@W3AGXUAgg at 2@@Z"
-// CHECK32:             (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca %0)
+// CHECK32:             (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* inalloca(<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>) %0)
 // CHECK32:   %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>, <{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>* %0, i32 0, i32 0
 // CHECK32:   load %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::C"** %[[this_slot]]
 // CHECK32:   getelementptr i8, i8* %{{.*}}, i32 -4
 // CHECK32:   store %"struct.stdcall_thunk::C"* %{{.*}}, %"struct.stdcall_thunk::C"** %[[this_slot]]
 // CHECK32:   musttail call x86_stdcallcc void @"?foo at C@stdcall_thunk@@UAGXUAgg at 2@@Z"
-// CHECK32:       (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>*  inalloca %0)
+// CHECK32:       (<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>*  inalloca(<{ %"struct.stdcall_thunk::C"*, %"struct.stdcall_thunk::Agg" }>) %0)
 // CHECK32-NEXT: ret void
 
 // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo at C@stdcall_thunk@@W7EAAXUAgg at 2@@Z"
@@ -76,13 +76,13 @@ struct C : A, B { C(); virtual Agg __cdecl foo(Agg x); };
 C::C() {} // force emission
 
 // CHECK32-LABEL: define linkonce_odr dso_local %"struct.sret_thunk::Agg"* @"?foo at C@sret_thunk@@W3AA?AUAgg at 2@U32@@Z"
-// CHECK32:             (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca %0)
+// CHECK32:             (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* inalloca(<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>) %0)
 // CHECK32:   %[[this_slot:[^ ]*]] = getelementptr inbounds <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>, <{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>* %0, i32 0, i32 0
 // CHECK32:   load %"struct.sret_thunk::C"*, %"struct.sret_thunk::C"** %[[this_slot]]
 // CHECK32:   getelementptr i8, i8* %{{.*}}, i32 -4
 // CHECK32:   store %"struct.sret_thunk::C"* %{{.*}}, %"struct.sret_thunk::C"** %[[this_slot]]
 // CHECK32:   %[[rv:[^ ]*]] = musttail call %"struct.sret_thunk::Agg"* @"?foo at C@sret_thunk@@UAA?AUAgg at 2@U32@@Z"
-// CHECK32:       (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>*  inalloca %0)
+// CHECK32:       (<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>*  inalloca(<{ %"struct.sret_thunk::C"*, %"struct.sret_thunk::Agg"*, %"struct.sret_thunk::Agg" }>) %0)
 // CHECK32-NEXT: ret %"struct.sret_thunk::Agg"* %[[rv]]
 
 // CHECK64-LABEL: define linkonce_odr dso_local void @"?foo at C@sret_thunk@@W7EAA?AUAgg at 2@U32@@Z"

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp b/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
index 26f6814cc1d4d..18333f36c239d 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-byval-vararg.cpp
@@ -19,14 +19,14 @@ int foo(A a, ...) {
   return sum;
 }
 
-// CHECK-LABEL: define dso_local i32 @"?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca %0, ...)
+// CHECK-LABEL: define dso_local i32 @"?foo@@YAHUA@@ZZ"(<{ %struct.A }>* inalloca(<{ %struct.A }>) %0, ...)
 
 int main() {
   return foo(A(3), 1, 2, 3);
 }
 // CHECK-LABEL: define dso_local i32 @main()
 // CHECK: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.A, i32, i32, i32 }>
-// CHECK: call i32 {{.*bitcast.*}}@"?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca %[[argmem]])
+// CHECK: call i32 {{.*bitcast.*}}@"?foo@@YAHUA@@ZZ"{{.*}}(<{ %struct.A, i32, i32, i32 }>* inalloca(<{ %struct.A, i32, i32, i32 }>) %[[argmem]])
 
 void varargs_zero(...);
 void varargs_one(int, ...);
@@ -41,10 +41,10 @@ void call_var_args() {
 }
 
 // CHECK-LABEL: define dso_local void @"?call_var_args@@YAXXZ"()
-// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca %{{.*}})
-// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca %{{.*}})
-// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca %{{.*}})
-// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca %{{.*}})
+// CHECK: call void {{.*bitcast.*varargs_zero.*}}(<{ %struct.A }>* inalloca(<{ %struct.A }>) %{{.*}})
+// CHECK: call void {{.*bitcast.*varargs_one.*}}(<{ i32, %struct.A }>* inalloca(<{ i32, %struct.A }>) %{{.*}})
+// CHECK: call void {{.*bitcast.*varargs_two.*}}(<{ i32, i32, %struct.A }>* inalloca(<{ i32, i32, %struct.A }>) %{{.*}})
+// CHECK: call void {{.*bitcast.*varargs_three.*}}(<{ i32, i32, i32, %struct.A }>* inalloca(<{ i32, i32, i32, %struct.A }>) %{{.*}})
 
 // CHECK-LABEL: declare dso_local void @"?varargs_zero@@YAXZZ"(...)
 // CHECK-LABEL: declare dso_local void @"?varargs_one@@YAXHZZ"(i32, ...)

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
index 7e173668f26ff..0b6b4385a3521 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-eh-cleanups.cpp
@@ -54,7 +54,7 @@ int HasDeactivatedCleanups() {
 // WIN32:   invoke x86_thiscallcc %struct.A* @"??0A@@QAE at XZ"
 // WIN32:   store i1 false, i1* %[[isactive]]
 //
-// WIN32:   invoke i32 @"?TakesTwo@@YAHUA@@0 at Z"([[argmem_ty]]* inalloca %[[argmem]])
+// WIN32:   invoke i32 @"?TakesTwo@@YAHUA@@0 at Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %[[argmem]])
 //        Destroy the two const ref temporaries.
 // WIN32:   call x86_thiscallcc void @"??1A@@QAE at XZ"({{.*}})
 // WIN32:   call x86_thiscallcc void @"??1A@@QAE at XZ"({{.*}})

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
index e0e4ba9e41b5f..b36ea9ccd9f01 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -76,7 +76,7 @@ struct SmallWithPrivate {
 
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:       (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
-// WIN32:           i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
+// WIN32:           i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca(<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor, i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>)
 void take_bools_and_chars(char a, char b, SmallWithDtor c, char d, bool e, int f, bool g);
 void call_bools_and_chars() {
   take_bools_and_chars('A', 'B', SmallWithDtor(), 'D', true, 13, false);
@@ -176,7 +176,7 @@ void packed_arg(Packed s) {}
 
 // Test that dtors are invoked in the callee.
 void small_arg_with_dtor(SmallWithDtor s) {}
-// WIN32: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca %0) {{.*}} {
+// WIN32: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(<{ %struct.SmallWithDtor }>* inalloca(<{ %struct.SmallWithDtor }>) %0) {{.*}} {
 // WIN32:   call x86_thiscallcc void @"??1SmallWithDtor@@QAE at XZ"
 // WIN32: }
 // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
@@ -253,13 +253,13 @@ void eh_cleanup_arg_with_dtor() {
 
 void small_arg_with_vftable(SmallWithVftable s) {}
 // LINUX-LABEL: define{{.*}} void @_Z22small_arg_with_vftable16SmallWithVftable(%struct.SmallWithVftable* %s)
-// WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca %0)
+// WIN32: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(<{ %struct.SmallWithVftable }>* inalloca(<{ %struct.SmallWithVftable }>) %0)
 // WIN64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
 // WOA64: define dso_local void @"?small_arg_with_vftable@@YAXUSmallWithVftable@@@Z"(%struct.SmallWithVftable* %s)
 
 void medium_arg_with_copy_ctor(MediumWithCopyCtor s) {}
 // LINUX-LABEL: define{{.*}} void @_Z25medium_arg_with_copy_ctor18MediumWithCopyCtor(%struct.MediumWithCopyCtor* %s)
-// WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca %0)
+// WIN32: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(<{ %struct.MediumWithCopyCtor }>* inalloca(<{ %struct.MediumWithCopyCtor }>) %0)
 // WIN64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
 // WOA: define dso_local arm_aapcs_vfpcc void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
 // WOA64: define dso_local void @"?medium_arg_with_copy_ctor@@YAXUMediumWithCopyCtor@@@Z"(%struct.MediumWithCopyCtor* %s)
@@ -363,7 +363,7 @@ struct X {
 };
 void g(X) {
 }
-// WIN32: define dso_local void @"?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca %0) {{.*}} {
+// WIN32: define dso_local void @"?g@@YAXUX@@@Z"(<{ %struct.X, [3 x i8] }>* inalloca(<{ %struct.X, [3 x i8] }>) %0) {{.*}} {
 // WIN32:   call x86_thiscallcc void @"??1X@@QAE at XZ"(%struct.X* {{.*}})
 // WIN32: }
 void f() {
@@ -398,7 +398,7 @@ void bar() {
 // WIN32:   call void @llvm.memcpy
 // WIN32:   getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
 // WIN32:   call x86_thiscallcc %"struct.test2::NonTrivial"* @"??0NonTrivial at test2@@QAE at XZ"
-// WIN32:   call i32 @"?foo at test2@@YAHUNonTrivial at 1@UPOD at 1@@Z"([[argmem_ty]]* inalloca %argmem)
+// WIN32:   call i32 @"?foo at test2@@YAHUNonTrivial at 1@UPOD at 1@@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %argmem)
 // WIN32:   ret void
 // WIN32: }
 
@@ -414,7 +414,7 @@ struct NonTrivial {
   int a;
 };
 void foo(NonTrivial a, bool b) { }
-// WIN32-LABEL: define dso_local void @"?foo at test3@@YAXUNonTrivial at 1@_N at Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca %0)
+// WIN32-LABEL: define dso_local void @"?foo at test3@@YAXUNonTrivial at 1@_N at Z"(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>* inalloca(<{ %"struct.test3::NonTrivial", i8, [3 x i8] }>) %0)
 
 }
 
@@ -440,7 +440,7 @@ void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); };
 // WIN32:   %[[gep2:[^ ]*]] = getelementptr inbounds [[argmem_ty]], [[argmem_ty]]* %[[argmem]], i32 0, i32 0
 // WIN32:   %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]*
 // WIN32:   store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4
-// WIN32:   call void @"?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]])
+// WIN32:   call void @"?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca([[argmem_ty]]) %[[argmem]])
 
 namespace pr30293 {
 // Virtual methods living in a secondary vtable take i8* as their 'this'
@@ -462,8 +462,8 @@ void C::g() { return h(SmallWithDtor()); }
 
 // WIN32-LABEL: define dso_local x86_thiscallcc void @"?g at C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* {{[^,]*}} %this)
 // WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"??0SmallWithDtor@@QAE at XZ"
-// WIN32: call void @"?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}})
-// WIN32: declare dso_local void @"?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca)
+// WIN32: call void @"?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca(<{ i8*, %struct.SmallWithDtor }>) %{{[^,)]*}})
+// WIN32: declare dso_local void @"?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca(<{ i8*, %struct.SmallWithDtor }>))
 
 // WIN64-LABEL: define dso_local void @"?g at C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* {{[^,]*}} %this)
 // WIN64: declare dso_local void @"?h at C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32)

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp b/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
index 6082228d36b6e..e71d6238c53ad 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp
@@ -94,7 +94,7 @@ void f(C *c) {
 
 // CHECK-LABEL: define dso_local void @"?f at cdecl_inalloca@@YAXPAUC at 1@@Z"(%"struct.cdecl_inalloca::C"* %c)
 // CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C at cdecl_inalloca@@$BA at AA" to void (%"struct.cdecl_inalloca::C"*)*)(%"struct.cdecl_inalloca::C"* {{[^,]*}} %{{.*}})
-// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C at cdecl_inalloca@@$BA at AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca %{{.*}})
+// CHECK: call void bitcast (void (%"struct.cdecl_inalloca::C"*, ...)* @"??_9C at cdecl_inalloca@@$BA at AA" to void (<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>*)*)(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>* inalloca(<{ %"struct.cdecl_inalloca::C"*, %"struct.cdecl_inalloca::Big" }>) %{{.*}})
 
 // CHECK-LABEL: define linkonce_odr void @"??_9C at cdecl_inalloca@@$BA at AA"(%"struct.cdecl_inalloca::C"* %this, ...) {{.*}} comdat
 // CHECK: musttail call void (%"struct.cdecl_inalloca::C"*, ...) %{{.*}}(%"struct.cdecl_inalloca::C"* %{{.*}}, ...)

diff  --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
index 93a7d4602223d..5cced42834e1b 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-this-adjustment.cpp
@@ -189,7 +189,7 @@ void C::g(NonTrivial o) {
   whatsthis = this;
 }
 
-// BITCODE-LABEL: define dso_local void @"?g at C@pr30293@@UAAXUNonTrivial at 2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca %0)
+// BITCODE-LABEL: define dso_local void @"?g at C@pr30293@@UAAXUNonTrivial at 2@@Z"(<{ i8*, %"struct.pr30293::NonTrivial" }>* inalloca(<{ i8*, %"struct.pr30293::NonTrivial" }>) %0)
 // BITCODE: %[[thisaddr:[^ ]*]] = getelementptr inbounds <{ i8*, %"struct.pr30293::NonTrivial" }>, <{ i8*, %"struct.pr30293::NonTrivial" }>* {{.*}}, i32 0, i32 0
 // BITCODE: %[[thisaddr1:[^ ]*]] = bitcast i8** %[[thisaddr]] to %"struct.pr30293::C"**
 // BITCODE: %[[this1:[^ ]*]] = load %"struct.pr30293::C"*, %"struct.pr30293::C"** %[[thisaddr1]], align 4

diff  --git a/clang/test/CodeGenCXX/ms-thunks-ehspec.cpp b/clang/test/CodeGenCXX/ms-thunks-ehspec.cpp
index 256f7123ee517..b8ebe2dd9f399 100644
--- a/clang/test/CodeGenCXX/ms-thunks-ehspec.cpp
+++ b/clang/test/CodeGenCXX/ms-thunks-ehspec.cpp
@@ -20,8 +20,8 @@ class C : A, B {
 };
 C c;
 
-// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f at C@@G3AEXUNonTrivial@@@Z"(%class.C* %this, <{ %struct.NonTrivial }>* inalloca %0)
+// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?f at C@@G3AEXUNonTrivial@@@Z"(%class.C* %this, <{ %struct.NonTrivial }>* inalloca(<{ %struct.NonTrivial }>) %0)
 // CHECK-NOT: invoke
-// CHECK: musttail call x86_thiscallcc void @"?f at C@@EAEXUNonTrivial@@@Z"(%class.C* %{{.*}}, <{ %struct.NonTrivial }>* inalloca %0)
+// CHECK: musttail call x86_thiscallcc void @"?f at C@@EAEXUNonTrivial@@@Z"(%class.C* %{{.*}}, <{ %struct.NonTrivial }>* inalloca(<{ %struct.NonTrivial }>) %0)
 // CHECK-NEXT:  ret void
 

diff  --git a/clang/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp b/clang/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
index 8f413021b3d0c..dd1c88a653343 100644
--- a/clang/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
+++ b/clang/test/CodeGenCXX/vararg-non-pod-ms-compat.cpp
@@ -13,7 +13,7 @@ void test(X x) {
   // CHECK-LABEL: define dso_local void @"?test@@YAXUX@@@Z"
 
   // X86: %[[argmem:[^ ]*]] = alloca inalloca <{ %struct.X }>
-  // X86: call void (<{ %struct.X }>*, ...) bitcast (void (...)* @"?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca %[[argmem]])
+  // X86: call void (<{ %struct.X }>*, ...) bitcast (void (...)* @"?vararg@@YAXZZ" to void (<{ %struct.X }>*, ...)*)(<{ %struct.X }>* inalloca(<{ %struct.X }>) %[[argmem]])
 
   // X64: alloca %struct.X
 

diff  --git a/clang/test/CodeGenObjCXX/arc-indirect.mm b/clang/test/CodeGenObjCXX/arc-indirect.mm
index de7566fcf987e..40543c054ea55 100644
--- a/clang/test/CodeGenObjCXX/arc-indirect.mm
+++ b/clang/test/CodeGenObjCXX/arc-indirect.mm
@@ -15,8 +15,8 @@ - (void)object:(id)obj struct:(S)s {
 }
 @end
 
-// CHECK-GNUSTEP: define internal void @_i_C__object_struct_(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca %0)
-// CHECK-DARWIN: define internal void @"\01-[C object:struct:]"(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca %0)
+// CHECK-GNUSTEP: define internal void @_i_C__object_struct_(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>) %0)
+// CHECK-DARWIN: define internal void @"\01-[C object:struct:]"(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* inalloca(<{ %0*, i8*, i8*, %struct.S, [3 x i8] }>) %0)
 // CHECK: %obj = getelementptr inbounds <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>, <{ %0*, i8*, i8*, %struct.S, [3 x i8] }>* %0, i32 0, i32 2
 // CHECK: %[[INSTANCE:[0-9]+]] = load i8*, i8** %obj, align 4
 // CHECK: call void @llvm.objc.storeStrong(i8** %obj, i8* %[[INSTANCE]])

diff  --git a/clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm b/clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
index 6be7995f5f019..26c13acf8959a 100644
--- a/clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
+++ b/clang/test/CodeGenObjCXX/microsoft-abi-arc-param-order.mm
@@ -10,7 +10,7 @@
 // Verify that we destruct things from left to right in the MS C++ ABI: a, b, c, d.
 //
 // CHECK-LABEL: define dso_local void @"?test_arc_order@@YAXUA@@PAUobjc_object@@01 at Z"
-// CHECK:                       (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca %0)
+// CHECK:                       (<{ %struct.A, i8*, %struct.A, i8* }>* inalloca(<{ %struct.A, i8*, %struct.A, i8* }>) %0)
 void test_arc_order(A a, id __attribute__((ns_consumed)) b , A c, id __attribute__((ns_consumed)) d) {
   // CHECK: call x86_thiscallcc void @"??1A@@QAE at XZ"(%struct.A* {{[^,]*}} %{{.*}})
   // CHECK: call void @llvm.objc.storeStrong(i8** %{{.*}}, i8* null)

diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 09a8933c110a2..794ca1092eafa 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1119,7 +1119,7 @@ Currently, only the following parameter attributes are defined:
 
 .. _attr_inalloca:
 
-``inalloca``
+``inalloca(<ty>)``
 
     The ``inalloca`` argument attribute allows the caller to take the
     address of outgoing stack arguments. An ``inalloca`` argument must
@@ -1143,6 +1143,9 @@ Currently, only the following parameter attributes are defined:
     must be cleared off with :ref:`llvm.stackrestore
     <int_stackrestore>`.
 
+    The inalloca attribute requires a type argument, which must be the
+    same as the pointee type of the argument.
+
     See :doc:`InAlloca` for more information on how to use this
     attribute.
 

diff  --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index e35dfddbe0439..e751ed90db2a4 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -58,7 +58,8 @@ Non-comprehensive list of changes in this release
 Changes to the LLVM IR
 ----------------------
 
-* ...
+* The ``inalloca`` attribute now has a mandatory type field, similar
+  to ``byval`` and ``sret``.
 
 
 Changes to building LLVM

diff  --git a/llvm/include/llvm/IR/Argument.h b/llvm/include/llvm/IR/Argument.h
index e8ca8a6e81b92..4b13e2d2a9e82 100644
--- a/llvm/include/llvm/IR/Argument.h
+++ b/llvm/include/llvm/IR/Argument.h
@@ -111,6 +111,9 @@ class Argument final : public Value {
   /// If this is a byref argument, return its type.
   Type *getParamByRefType() const;
 
+  /// If this is an inalloca argument, return its type.
+  Type *getParamInAllocaType() const;
+
   /// Return true if this argument has the nest attribute.
   bool hasNestAttr() const;
 

diff  --git a/llvm/include/llvm/IR/Attributes.h b/llvm/include/llvm/IR/Attributes.h
index d21d65bc4e798..a8c4017118580 100644
--- a/llvm/include/llvm/IR/Attributes.h
+++ b/llvm/include/llvm/IR/Attributes.h
@@ -114,6 +114,7 @@ class Attribute {
   static Attribute getWithStructRetType(LLVMContext &Context, Type *Ty);
   static Attribute getWithByRefType(LLVMContext &Context, Type *Ty);
   static Attribute getWithPreallocatedType(LLVMContext &Context, Type *Ty);
+  static Attribute getWithInAllocaType(LLVMContext &Context, Type *Ty);
 
   /// For a typed attribute, return the equivalent attribute with the type
   /// changed to \p ReplacementTy.
@@ -160,7 +161,7 @@ class Attribute {
   bool hasAttribute(StringRef Val) const;
 
   /// Return the attribute's kind as an enum (Attribute::AttrKind). This
-  /// requires the attribute to be an enum or integer attribute.
+  /// requires the attribute to be an enum, integer, or type attribute.
   Attribute::AttrKind getKindAsEnum() const;
 
   /// Return the attribute's value as an integer. This requires that the
@@ -325,6 +326,7 @@ class AttributeSet {
   Type *getStructRetType() const;
   Type *getByRefType() const;
   Type *getPreallocatedType() const;
+  Type *getInAllocaType() const;
   std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
   std::pair<unsigned, unsigned> getVScaleRangeArgs() const;
   std::string getAsString(bool InAttrGrp = false) const;
@@ -684,6 +686,9 @@ class AttributeList {
   /// Return the preallocated type for the specified function parameter.
   Type *getParamPreallocatedType(unsigned ArgNo) const;
 
+  /// Return the inalloca type for the specified function parameter.
+  Type *getParamInAllocaType(unsigned ArgNo) const;
+
   /// Get the stack alignment.
   MaybeAlign getStackAlignment(unsigned Index) const;
 
@@ -791,6 +796,7 @@ class AttrBuilder {
   Type *StructRetType = nullptr;
   Type *ByRefType = nullptr;
   Type *PreallocatedType = nullptr;
+  Type *InAllocaType = nullptr;
 
 public:
   AttrBuilder() = default;
@@ -885,6 +891,9 @@ class AttrBuilder {
   /// Retrieve the preallocated type.
   Type *getPreallocatedType() const { return PreallocatedType; }
 
+  /// Retrieve the inalloca type.
+  Type *getInAllocaType() const { return InAllocaType; }
+
   /// Retrieve the allocsize args, if the allocsize attribute exists.  If it
   /// doesn't exist, pair(0, 0) is returned.
   std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
@@ -944,6 +953,9 @@ class AttrBuilder {
   /// This turns a preallocated type into the form used internally in Attribute.
   AttrBuilder &addPreallocatedAttr(Type *Ty);
 
+  /// This turns an inalloca type into the form used internally in Attribute.
+  AttrBuilder &addInAllocaAttr(Type *Ty);
+
   /// Add an allocsize attribute, using the representation returned by
   /// Attribute.getIntValue().
   AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr);

diff  --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td
index 9f62723646e5b..9684ffa0009b1 100644
--- a/llvm/include/llvm/IR/Attributes.td
+++ b/llvm/include/llvm/IR/Attributes.td
@@ -80,7 +80,7 @@ def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly">;
 def InaccessibleMemOrArgMemOnly : EnumAttr<"inaccessiblemem_or_argmemonly">;
 
 /// Pass structure in an alloca.
-def InAlloca : EnumAttr<"inalloca">;
+def InAlloca : TypeAttr<"inalloca">;
 
 /// Source said inlining was desirable.
 def InlineHint : EnumAttr<"inlinehint">;

diff  --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index ab20cc4b68c83..a24b12c1a470a 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -493,6 +493,11 @@ class Function : public GlobalObject, public ilist_node<Function> {
     return AttributeSets.getParamStructRetType(ArgNo);
   }
 
+  /// Extract the inalloca type for a parameter.
+  Type *getParamInAllocaType(unsigned ArgNo) const {
+    return AttributeSets.getParamInAllocaType(ArgNo);
+  }
+
   /// Extract the byref type for a parameter.
   Type *getParamByRefType(unsigned ArgNo) const {
     return AttributeSets.getParamByRefType(ArgNo);

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 0372da19df55a..ee84424b31f63 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -1736,6 +1736,13 @@ bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) {
       B.addPreallocatedAttr(Ty);
       continue;
     }
+    case lltok::kw_inalloca: {
+      Type *Ty;
+      if (parseInalloca(Ty))
+        return true;
+      B.addInAllocaAttr(Ty);
+      continue;
+    }
     case lltok::kw_dereferenceable: {
       uint64_t Bytes;
       if (parseOptionalDerefAttrBytes(lltok::kw_dereferenceable, Bytes))
@@ -1757,7 +1764,6 @@ bool LLParser::parseOptionalParamAttrs(AttrBuilder &B) {
       B.addByRefAttr(Ty);
       continue;
     }
-    case lltok::kw_inalloca:        B.addAttribute(Attribute::InAlloca); break;
     case lltok::kw_inreg:           B.addAttribute(Attribute::InReg); break;
     case lltok::kw_nest:            B.addAttribute(Attribute::Nest); break;
     case lltok::kw_noundef:
@@ -2694,6 +2700,12 @@ bool LLParser::parsePreallocated(Type *&Result) {
   return parseRequiredTypeAttr(Result, lltok::kw_preallocated);
 }
 
+/// parseInalloca
+///   ::= inalloca(<ty>)
+bool LLParser::parseInalloca(Type *&Result) {
+  return parseRequiredTypeAttr(Result, lltok::kw_inalloca);
+}
+
 /// parseByRef
 ///   ::= byref(<type>)
 bool LLParser::parseByRef(Type *&Result) {

diff  --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h
index 1205394ff67fc..3d9ffe6e90da9 100644
--- a/llvm/lib/AsmParser/LLParser.h
+++ b/llvm/lib/AsmParser/LLParser.h
@@ -331,6 +331,7 @@ namespace llvm {
                                     bool inAttrGrp, LocTy &BuiltinLoc);
     bool parseRequiredTypeAttr(Type *&Result, lltok::Kind AttrName);
     bool parsePreallocated(Type *&Result);
+    bool parseInalloca(Type *&Result);
     bool parseByRef(Type *&Result);
 
     // Module Summary Index Parsing.

diff  --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 951e32e36dd65..46db3edcc3427 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1624,6 +1624,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
             B.addByValAttr(nullptr);
           else if (Kind == Attribute::StructRet)
             B.addStructRetAttr(nullptr);
+          else if (Kind == Attribute::InAlloca)
+            B.addInAllocaAttr(nullptr);
 
           B.addAttribute(Kind);
         } else if (Record[i] == 1) { // Integer attribute
@@ -1675,6 +1677,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
             B.addByRefAttr(getTypeByID(Record[++i]));
           } else if (Kind == Attribute::Preallocated) {
             B.addPreallocatedAttr(getTypeByID(Record[++i]));
+          } else if (Kind == Attribute::InAlloca) {
+            B.addInAllocaAttr(HasType ? getTypeByID(Record[++i]) : nullptr);
           }
         }
       }
@@ -3328,7 +3332,8 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
   // argument's pointee type. There should be no opaque pointers where the byval
   // type is implicit.
   for (unsigned i = 0; i != Func->arg_size(); ++i) {
-    for (Attribute::AttrKind Kind : {Attribute::ByVal, Attribute::StructRet}) {
+    for (Attribute::AttrKind Kind : {Attribute::ByVal, Attribute::StructRet,
+                                     Attribute::InAlloca}) {
       if (!Func->hasParamAttribute(i, Kind))
         continue;
 
@@ -3336,10 +3341,21 @@ Error BitcodeReader::parseFunctionRecord(ArrayRef<uint64_t> Record) {
 
       Type *PTy = cast<FunctionType>(FullFTy)->getParamType(i);
       Type *PtrEltTy = getPointerElementFlatType(PTy);
-      Attribute NewAttr =
-          Kind == Attribute::ByVal
-              ? Attribute::getWithByValType(Context, PtrEltTy)
-              : Attribute::getWithStructRetType(Context, PtrEltTy);
+      Attribute NewAttr;
+      switch (Kind) {
+      case Attribute::ByVal:
+        NewAttr = Attribute::getWithByValType(Context, PtrEltTy);
+        break;
+      case Attribute::StructRet:
+        NewAttr = Attribute::getWithStructRetType(Context, PtrEltTy);
+        break;
+      case Attribute::InAlloca:
+        NewAttr = Attribute::getWithInAllocaType(Context, PtrEltTy);
+        break;
+      default:
+        llvm_unreachable("not an upgraded type attribute");
+      }
+
       Func->addParamAttr(i, NewAttr);
     }
   }
@@ -3805,17 +3821,29 @@ Error BitcodeReader::typeCheckLoadStoreInst(Type *ValType, Type *PtrType) {
 void BitcodeReader::propagateByValSRetTypes(CallBase *CB,
                                             ArrayRef<Type *> ArgsFullTys) {
   for (unsigned i = 0; i != CB->arg_size(); ++i) {
-    for (Attribute::AttrKind Kind : {Attribute::ByVal, Attribute::StructRet}) {
+    for (Attribute::AttrKind Kind : {Attribute::ByVal, Attribute::StructRet,
+                                     Attribute::InAlloca}) {
       if (!CB->paramHasAttr(i, Kind))
         continue;
 
       CB->removeParamAttr(i, Kind);
 
       Type *PtrEltTy = getPointerElementFlatType(ArgsFullTys[i]);
-      Attribute NewAttr =
-          Kind == Attribute::ByVal
-              ? Attribute::getWithByValType(Context, PtrEltTy)
-              : Attribute::getWithStructRetType(Context, PtrEltTy);
+      Attribute NewAttr;
+      switch (Kind) {
+      case Attribute::ByVal:
+        NewAttr = Attribute::getWithByValType(Context, PtrEltTy);
+        break;
+      case Attribute::StructRet:
+        NewAttr = Attribute::getWithStructRetType(Context, PtrEltTy);
+        break;
+      case Attribute::InAlloca:
+        NewAttr = Attribute::getWithInAllocaType(Context, PtrEltTy);
+        break;
+      default:
+        llvm_unreachable("not an upgraded type attribute");
+      }
+
       CB->addParamAttr(i, NewAttr);
     }
   }

diff  --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 09f21d26971d4..91f8939a8ffa0 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -4413,20 +4413,18 @@ void AssemblyWriter::writeAttribute(const Attribute &Attr, bool InAttrGroup) {
     return;
   }
 
-  assert((Attr.hasAttribute(Attribute::ByVal) ||
-          Attr.hasAttribute(Attribute::StructRet) ||
-          Attr.hasAttribute(Attribute::ByRef) ||
-          Attr.hasAttribute(Attribute::Preallocated)) &&
-         "unexpected type attr");
-
   if (Attr.hasAttribute(Attribute::ByVal)) {
     Out << "byval";
   } else if (Attr.hasAttribute(Attribute::StructRet)) {
     Out << "sret";
   } else if (Attr.hasAttribute(Attribute::ByRef)) {
     Out << "byref";
-  } else {
+  } else if (Attr.hasAttribute(Attribute::Preallocated)) {
     Out << "preallocated";
+  } else if (Attr.hasAttribute(Attribute::InAlloca)) {
+    Out << "inalloca";
+  } else {
+    llvm_unreachable("unexpected type attr");
   }
 
   if (Type *Ty = Attr.getValueAsType()) {

diff  --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h
index 53c2228658b54..60e2ec2c21be3 100644
--- a/llvm/lib/IR/AttributeImpl.h
+++ b/llvm/lib/IR/AttributeImpl.h
@@ -258,6 +258,7 @@ class AttributeSetNode final
   Type *getStructRetType() const;
   Type *getByRefType() const;
   Type *getPreallocatedType() const;
+  Type *getInAllocaType() const;
 
   using iterator = const Attribute *;
 

diff  --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 831186a49fca7..c174e4f931969 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -195,6 +195,10 @@ Attribute Attribute::getWithPreallocatedType(LLVMContext &Context, Type *Ty) {
   return get(Context, Preallocated, Ty);
 }
 
+Attribute Attribute::getWithInAllocaType(LLVMContext &Context, Type *Ty) {
+  return get(Context, InAlloca, Ty);
+}
+
 Attribute
 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
                                 const Optional<unsigned> &NumElemsArg) {
@@ -377,8 +381,6 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
     return "inaccessiblememonly";
   if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly))
     return "inaccessiblemem_or_argmemonly";
-  if (hasAttribute(Attribute::InAlloca))
-    return "inalloca";
   if (hasAttribute(Attribute::InlineHint))
     return "inlinehint";
   if (hasAttribute(Attribute::InReg))
@@ -484,24 +486,30 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
   if (hasAttribute(Attribute::MustProgress))
     return "mustprogress";
 
-  const bool IsByVal = hasAttribute(Attribute::ByVal);
-  if (IsByVal || hasAttribute(Attribute::StructRet)) {
+  if (isTypeAttribute()) {
     std::string Result;
-    Result += IsByVal ? "byval" : "sret";
-    if (Type *Ty = getValueAsType()) {
-      raw_string_ostream OS(Result);
-      Result += '(';
-      Ty->print(OS, false, true);
-      OS.flush();
-      Result += ')';
+    raw_string_ostream OS(Result);
+
+    switch (getKindAsEnum()) {
+    case Attribute::ByVal:
+      Result += "byval";
+      break;
+    case Attribute::StructRet:
+      Result += "sret";
+      break;
+    case Attribute::ByRef:
+      Result += "byref";
+      break;
+    case Attribute::Preallocated:
+      Result += "preallocated";
+      break;
+    case Attribute::InAlloca:
+      Result += "inalloca";
+      break;
+    default:
+      llvm_unreachable("unhandled type attribute");
     }
-    return Result;
-  }
 
-  const bool IsByRef = hasAttribute(Attribute::ByRef);
-  if (IsByRef || hasAttribute(Attribute::Preallocated)) {
-    std::string Result = IsByRef ? "byref" : "preallocated";
-    raw_string_ostream OS(Result);
     Result += '(';
     getValueAsType()->print(OS, false, true);
     OS.flush();
@@ -809,6 +817,10 @@ Type *AttributeSet::getPreallocatedType() const {
   return SetNode ? SetNode->getPreallocatedType() : nullptr;
 }
 
+Type *AttributeSet::getInAllocaType() const {
+  return SetNode ? SetNode->getInAllocaType() : nullptr;
+}
+
 std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
   return SetNode ? SetNode->getAllocSizeArgs()
                  : std::pair<unsigned, Optional<unsigned>>(0, 0);
@@ -915,6 +927,9 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
     case Attribute::Preallocated:
       Attr = Attribute::getWithPreallocatedType(C, B.getPreallocatedType());
       break;
+    case Attribute::InAlloca:
+      Attr = Attribute::getWithInAllocaType(C, B.getInAllocaType());
+      break;
     case Attribute::Alignment:
       assert(B.getAlignment() && "Alignment must be set");
       Attr = Attribute::getWithAlignment(C, *B.getAlignment());
@@ -1021,6 +1036,12 @@ Type *AttributeSetNode::getPreallocatedType() const {
   return nullptr;
 }
 
+Type *AttributeSetNode::getInAllocaType() const {
+  if (auto A = findEnumAttribute(Attribute::InAlloca))
+    return A->getValueAsType();
+  return nullptr;
+}
+
 uint64_t AttributeSetNode::getDereferenceableBytes() const {
   if (auto A = findEnumAttribute(Attribute::Dereferenceable))
     return A->getDereferenceableBytes();
@@ -1578,6 +1599,10 @@ Type *AttributeList::getParamPreallocatedType(unsigned Index) const {
   return getAttributes(Index + FirstArgIndex).getPreallocatedType();
 }
 
+Type *AttributeList::getParamInAllocaType(unsigned Index) const {
+  return getAttributes(Index + FirstArgIndex).getInAllocaType();
+}
+
 MaybeAlign AttributeList::getStackAlignment(unsigned Index) const {
   return getAttributes(Index).getStackAlignment();
 }
@@ -1699,6 +1724,9 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
     AllocSizeArgs = Attr.getValueAsInt();
   else if (Kind == Attribute::VScaleRange)
     VScaleRangeArgs = Attr.getValueAsInt();
+  else if (Kind == Attribute::InAlloca)
+    InAllocaType = Attr.getValueAsType();
+
   return *this;
 }
 
@@ -1723,6 +1751,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
     ByRefType = nullptr;
   else if (Val == Attribute::Preallocated)
     PreallocatedType = nullptr;
+  else if (Val == Attribute::InAlloca)
+    InAllocaType = nullptr;
   else if (Val == Attribute::Dereferenceable)
     DerefBytes = 0;
   else if (Val == Attribute::DereferenceableOrNull)
@@ -1852,6 +1882,12 @@ AttrBuilder &AttrBuilder::addPreallocatedAttr(Type *Ty) {
   return *this;
 }
 
+AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
+  Attrs[Attribute::InAlloca] = true;
+  InAllocaType = Ty;
+  return *this;
+}
+
 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
   // FIXME: What if both have alignments, but they don't match?!
   if (!Alignment)
@@ -1881,6 +1917,9 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
   if (!PreallocatedType)
     PreallocatedType = B.PreallocatedType;
 
+  if (!InAllocaType)
+    InAllocaType = B.InAllocaType;
+
   if (!VScaleRangeArgs)
     VScaleRangeArgs = B.VScaleRangeArgs;
 
@@ -1921,6 +1960,9 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
   if (B.PreallocatedType)
     PreallocatedType = nullptr;
 
+  if (B.InAllocaType)
+    InAllocaType = nullptr;
+
   if (B.VScaleRangeArgs)
     VScaleRangeArgs = 0;
 
@@ -1985,6 +2027,7 @@ bool AttrBuilder::operator==(const AttrBuilder &B) const {
          DerefBytes == B.DerefBytes && ByValType == B.ByValType &&
          StructRetType == B.StructRetType && ByRefType == B.ByRefType &&
          PreallocatedType == B.PreallocatedType &&
+         InAllocaType == B.InAllocaType &&
          VScaleRangeArgs == B.VScaleRangeArgs;
 }
 
@@ -2014,6 +2057,7 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
         .addAttribute(Attribute::ReadOnly)
         .addAttribute(Attribute::InAlloca)
         .addPreallocatedAttr(Ty)
+        .addInAllocaAttr(Ty)
         .addByValAttr(Ty)
         .addStructRetAttr(Ty)
         .addByRefAttr(Ty);

diff  --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 7389ec6858ed5..1001607403d2e 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -162,6 +162,8 @@ static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) {
     return ByRefTy;
   if (Type *PreAllocTy = ParamAttrs.getPreallocatedType())
     return PreAllocTy;
+  if (Type *InAllocaTy = ParamAttrs.getInAllocaType())
+    return InAllocaTy;
 
   // FIXME: sret and inalloca always depends on pointee element type. It's also
   // possible for byval to miss it.
@@ -213,6 +215,11 @@ Type *Argument::getParamByRefType() const {
   return getParent()->getParamByRefType(getArgNo());
 }
 
+Type *Argument::getParamInAllocaType() const {
+  assert(getType()->isPointerTy() && "Only pointers have inalloca types");
+  return getParent()->getParamInAllocaType(getArgNo());
+}
+
 uint64_t Argument::getDereferenceableBytes() const {
   assert(getType()->isPointerTy() &&
          "Only pointers have dereferenceable bytes");

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 0a96b29407bb5..b6952f7030416 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -1813,6 +1813,11 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
       Assert(Attrs.getPreallocatedType() == PTy->getElementType(),
              "Attribute 'preallocated' type does not match parameter!", V);
     }
+
+    if (Attrs.hasAttribute(Attribute::InAlloca)) {
+      Assert(Attrs.getInAllocaType() == PTy->getElementType(),
+             "Attribute 'inalloca' type does not match parameter!", V);
+    }
   } else {
     Assert(!Attrs.hasAttribute(Attribute::ByVal),
            "Attribute 'byval' only applies to parameters with pointer type!",

diff  --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp
index f9b9b94911a71..1433d074595ba 100644
--- a/llvm/lib/Linker/IRMover.cpp
+++ b/llvm/lib/Linker/IRMover.cpp
@@ -647,7 +647,8 @@ GlobalVariable *IRLinker::copyGlobalVariableProto(const GlobalVariable *SGVar) {
 AttributeList IRLinker::mapAttributeTypes(LLVMContext &C, AttributeList Attrs) {
   for (unsigned i = 0; i < Attrs.getNumAttrSets(); ++i) {
     for (Attribute::AttrKind TypedAttr :
-         {Attribute::ByVal, Attribute::StructRet, Attribute::ByRef}) {
+         {Attribute::ByVal, Attribute::StructRet, Attribute::ByRef,
+          Attribute::InAlloca}) {
       if (Attrs.hasAttribute(i, TypedAttr)) {
         if (Type *Ty = Attrs.getAttribute(i, TypedAttr).getValueAsType()) {
           Attrs = Attrs.replaceAttributeType(C, i, TypedAttr, TypeMap.get(Ty));

diff  --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp
index ae839bd3a3d36..d8751888ad21e 100644
--- a/llvm/lib/Transforms/Utils/ValueMapper.cpp
+++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp
@@ -945,7 +945,8 @@ void Mapper::remapInstruction(Instruction *I) {
     AttributeList Attrs = CB->getAttributes();
     for (unsigned i = 0; i < Attrs.getNumAttrSets(); ++i) {
       for (Attribute::AttrKind TypedAttr :
-           {Attribute::ByVal, Attribute::StructRet, Attribute::ByRef}) {
+             {Attribute::ByVal, Attribute::StructRet, Attribute::ByRef,
+              Attribute::InAlloca}) {
         if (Type *Ty = Attrs.getAttribute(i, TypedAttr).getValueAsType()) {
           Attrs = Attrs.replaceAttributeType(C, i, TypedAttr,
                                              TypeMapper->remapType(Ty));

diff  --git a/llvm/test/Assembler/inalloca-parse-error0.ll b/llvm/test/Assembler/inalloca-parse-error0.ll
new file mode 100644
index 0000000000000..24fe82baaeff2
--- /dev/null
+++ b/llvm/test/Assembler/inalloca-parse-error0.ll
@@ -0,0 +1,6 @@
+; RUN: not llvm-as < %s 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:40: error: expected '('{{$}}
+define void @test_inalloca(i8* inalloca) {
+  ret void
+}

diff  --git a/llvm/test/Assembler/invalid-immarg.ll b/llvm/test/Assembler/invalid-immarg.ll
index f2203d2609fd3..023a528ea7bb0 100644
--- a/llvm/test/Assembler/invalid-immarg.ll
+++ b/llvm/test/Assembler/invalid-immarg.ll
@@ -4,7 +4,7 @@
 declare void @llvm.immarg.byval(i32* byval(i32) immarg)
 
 ; CHECK: Attribute 'immarg' is incompatible with other attributes
-declare void @llvm.immarg.inalloca(i32* inalloca immarg)
+declare void @llvm.immarg.inalloca(i32* inalloca(i32) immarg)
 
 ; CHECK: Attribute 'immarg' is incompatible with other attributes
 declare void @llvm.immarg.inreg(i32 inreg immarg)

diff  --git a/llvm/test/Bitcode/Inputs/inalloca-upgrade.bc b/llvm/test/Bitcode/Inputs/inalloca-upgrade.bc
new file mode 100644
index 0000000000000..51012caacddce
Binary files /dev/null and b/llvm/test/Bitcode/Inputs/inalloca-upgrade.bc 
diff er

diff  --git a/llvm/test/Bitcode/attributes.ll b/llvm/test/Bitcode/attributes.ll
index b8b41e5c4e5c6..936a2953901a9 100644
--- a/llvm/test/Bitcode/attributes.ll
+++ b/llvm/test/Bitcode/attributes.ll
@@ -214,8 +214,8 @@ define void @f35() optnone noinline
         ret void;
 }
 
-define void @f36(i8* inalloca %0) {
-; CHECK: define void @f36(i8* inalloca %0) {
+define void @f36(i8* inalloca(i8) %0) {
+; CHECK: define void @f36(i8* inalloca(i8) %0) {
         ret void
 }
 

diff  --git a/llvm/test/Bitcode/compatibility-3.6.ll b/llvm/test/Bitcode/compatibility-3.6.ll
index 05e6b71f14778..882f0416e8936 100644
--- a/llvm/test/Bitcode/compatibility-3.6.ll
+++ b/llvm/test/Bitcode/compatibility-3.6.ll
@@ -406,7 +406,7 @@ declare void @f.param.inreg(i8 inreg)
 declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 declare void @f.param.inalloca(i8* inalloca)
-; CHECK: declare void @f.param.inalloca(i8* inalloca)
+; CHECK: declare void @f.param.inalloca(i8* inalloca(i8))
 declare void @f.param.sret(i8* sret(i8))
 ; CHECK: declare void @f.param.sret(i8* sret(i8))
 declare void @f.param.noalias(i8* noalias)
@@ -993,7 +993,7 @@ exit:
 
 define void @instructions.call_musttail(i8* inalloca %val) {
   musttail call void @f.param.inalloca(i8* inalloca %val)
-  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val)
+  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
 
   ret void
 }

diff  --git a/llvm/test/Bitcode/compatibility-3.7.ll b/llvm/test/Bitcode/compatibility-3.7.ll
index b31509ec0a867..65dae1b6a7553 100644
--- a/llvm/test/Bitcode/compatibility-3.7.ll
+++ b/llvm/test/Bitcode/compatibility-3.7.ll
@@ -412,7 +412,7 @@ declare void @f.param.inreg(i8 inreg)
 declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 declare void @f.param.inalloca(i8* inalloca)
-; CHECK: declare void @f.param.inalloca(i8* inalloca)
+; CHECK: declare void @f.param.inalloca(i8* inalloca(i8))
 declare void @f.param.sret(i8* sret(i8))
 ; CHECK: declare void @f.param.sret(i8* sret(i8))
 declare void @f.param.noalias(i8* noalias)
@@ -1034,7 +1034,7 @@ exit:
 
 define void @instructions.call_musttail(i8* inalloca %val) {
   musttail call void @f.param.inalloca(i8* inalloca %val)
-  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val)
+  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
 
   ret void
 }

diff  --git a/llvm/test/Bitcode/compatibility-3.8.ll b/llvm/test/Bitcode/compatibility-3.8.ll
index 72b01f6a1d98b..51b4740ea42e3 100644
--- a/llvm/test/Bitcode/compatibility-3.8.ll
+++ b/llvm/test/Bitcode/compatibility-3.8.ll
@@ -437,7 +437,7 @@ declare void @f.param.inreg(i8 inreg)
 declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 declare void @f.param.inalloca(i8* inalloca)
-; CHECK: declare void @f.param.inalloca(i8* inalloca)
+; CHECK: declare void @f.param.inalloca(i8* inalloca(i8))
 declare void @f.param.sret(i8* sret(i8))
 ; CHECK: declare void @f.param.sret(i8* sret(i8))
 declare void @f.param.noalias(i8* noalias)
@@ -1182,7 +1182,7 @@ exit:
 
 define void @instructions.call_musttail(i8* inalloca %val) {
   musttail call void @f.param.inalloca(i8* inalloca %val)
-  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val)
+  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
 
   ret void
 }

diff  --git a/llvm/test/Bitcode/compatibility-3.9.ll b/llvm/test/Bitcode/compatibility-3.9.ll
index f5b409ab25789..e203e5144c28c 100644
--- a/llvm/test/Bitcode/compatibility-3.9.ll
+++ b/llvm/test/Bitcode/compatibility-3.9.ll
@@ -506,7 +506,7 @@ declare void @f.param.inreg(i8 inreg)
 declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 declare void @f.param.inalloca(i8* inalloca)
-; CHECK: declare void @f.param.inalloca(i8* inalloca)
+; CHECK: declare void @f.param.inalloca(i8* inalloca(i8))
 declare void @f.param.sret(i8* sret(i8))
 ; CHECK: declare void @f.param.sret(i8* sret(i8))
 declare void @f.param.noalias(i8* noalias)
@@ -1253,7 +1253,7 @@ exit:
 
 define void @instructions.call_musttail(i8* inalloca %val) {
   musttail call void @f.param.inalloca(i8* inalloca %val)
-  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val)
+  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
 
   ret void
 }

diff  --git a/llvm/test/Bitcode/compatibility-4.0.ll b/llvm/test/Bitcode/compatibility-4.0.ll
index c7874106d2b99..b0b65fe75da81 100644
--- a/llvm/test/Bitcode/compatibility-4.0.ll
+++ b/llvm/test/Bitcode/compatibility-4.0.ll
@@ -506,7 +506,7 @@ declare void @f.param.inreg(i8 inreg)
 declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 declare void @f.param.inalloca(i8* inalloca)
-; CHECK: declare void @f.param.inalloca(i8* inalloca)
+; CHECK: declare void @f.param.inalloca(i8* inalloca(i8))
 declare void @f.param.sret(i8* sret(i8))
 ; CHECK: declare void @f.param.sret(i8* sret(i8))
 declare void @f.param.noalias(i8* noalias)
@@ -1253,7 +1253,7 @@ exit:
 
 define void @instructions.call_musttail(i8* inalloca %val) {
   musttail call void @f.param.inalloca(i8* inalloca %val)
-  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val)
+  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
 
   ret void
 }

diff  --git a/llvm/test/Bitcode/compatibility-5.0.ll b/llvm/test/Bitcode/compatibility-5.0.ll
index e63ff3a7cc066..93916d9ff8902 100644
--- a/llvm/test/Bitcode/compatibility-5.0.ll
+++ b/llvm/test/Bitcode/compatibility-5.0.ll
@@ -510,7 +510,7 @@ declare void @f.param.inreg(i8 inreg)
 declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 declare void @f.param.inalloca(i8* inalloca)
-; CHECK: declare void @f.param.inalloca(i8* inalloca)
+; CHECK: declare void @f.param.inalloca(i8* inalloca(i8))
 declare void @f.param.sret(i8* sret(i8))
 ; CHECK: declare void @f.param.sret(i8* sret(i8))
 declare void @f.param.noalias(i8* noalias)
@@ -1265,7 +1265,7 @@ exit:
 
 define void @instructions.call_musttail(i8* inalloca %val) {
   musttail call void @f.param.inalloca(i8* inalloca %val)
-  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val)
+  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
 
   ret void
 }

diff  --git a/llvm/test/Bitcode/compatibility-6.0.ll b/llvm/test/Bitcode/compatibility-6.0.ll
index 980dd92563c7e..bd5dfd3457928 100644
--- a/llvm/test/Bitcode/compatibility-6.0.ll
+++ b/llvm/test/Bitcode/compatibility-6.0.ll
@@ -517,7 +517,7 @@ declare void @f.param.inreg(i8 inreg)
 declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 declare void @f.param.inalloca(i8* inalloca)
-; CHECK: declare void @f.param.inalloca(i8* inalloca)
+; CHECK: declare void @f.param.inalloca(i8* inalloca(i8))
 declare void @f.param.sret(i8* sret(i8))
 ; CHECK: declare void @f.param.sret(i8* sret(i8))
 declare void @f.param.noalias(i8* noalias)
@@ -1276,7 +1276,7 @@ exit:
 
 define void @instructions.call_musttail(i8* inalloca %val) {
   musttail call void @f.param.inalloca(i8* inalloca %val)
-  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val)
+  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
 
   ret void
 }

diff  --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index 34c5cfd412046..95bb2639e09bc 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -532,8 +532,8 @@ declare void @f.param.inreg(i8 inreg)
 ; CHECK: declare void @f.param.inreg(i8 inreg)
 declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
 ; CHECK: declare void @f.param.byval({ i8, i8 }* byval({ i8, i8 }))
-declare void @f.param.inalloca(i8* inalloca)
-; CHECK: declare void @f.param.inalloca(i8* inalloca)
+declare void @f.param.inalloca(i8* inalloca(i8))
+; CHECK: declare void @f.param.inalloca(i8* inalloca(i8))
 declare void @f.param.sret(i8* sret(i8))
 ; CHECK: declare void @f.param.sret(i8* sret(i8))
 declare void @f.param.noalias(i8* noalias)
@@ -1520,9 +1520,9 @@ exit:
   ret void
 }
 
-define void @instructions.call_musttail(i8* inalloca %val) {
-  musttail call void @f.param.inalloca(i8* inalloca %val)
-  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca %val)
+define void @instructions.call_musttail(i8* inalloca(i8) %val) {
+  musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
+  ; CHECK: musttail call void @f.param.inalloca(i8* inalloca(i8) %val)
 
   ret void
 }

diff  --git a/llvm/test/Bitcode/inalloca-upgrade.test b/llvm/test/Bitcode/inalloca-upgrade.test
new file mode 100644
index 0000000000000..20d41365b3601
--- /dev/null
+++ b/llvm/test/Bitcode/inalloca-upgrade.test
@@ -0,0 +1,7 @@
+RUN: llvm-dis %p/Inputs/inalloca-upgrade.bc -o - | FileCheck %s
+
+Make sure we upgrade old-style IntAttribute inalloca records to a
+fully typed version correctly.
+
+CHECK: call void @bar({ i32*, i8 }* inalloca({ i32*, i8 }) %ptr)
+CHECK: invoke void @bar({ i32*, i8 }* inalloca({ i32*, i8 }) %ptr)

diff  --git a/llvm/test/Bitcode/inalloca.ll b/llvm/test/Bitcode/inalloca.ll
index 84abe176d65e9..3b56f571b15b2 100644
--- a/llvm/test/Bitcode/inalloca.ll
+++ b/llvm/test/Bitcode/inalloca.ll
@@ -3,17 +3,17 @@
 
 ; inalloca should roundtrip.
 
-define void @foo(i32* inalloca %args) {
+define void @foo(i32* inalloca(i32) %args) {
   ret void
 }
-; CHECK-LABEL: define void @foo(i32* inalloca %args)
+; CHECK-LABEL: define void @foo(i32* inalloca(i32) %args)
 
 define void @bar() {
   ; Use the maximum alignment, since we stuff our bit with alignment.
   %args = alloca inalloca i32, align 536870912
-  call void @foo(i32* inalloca %args)
+  call void @foo(i32* inalloca(i32) %args)
   ret void
 }
 ; CHECK-LABEL: define void @bar() {
 ; CHECK: %args = alloca inalloca i32, align 536870912
-; CHECK: call void @foo(i32* inalloca %args)
+; CHECK: call void @foo(i32* inalloca(i32) %args)

diff  --git a/llvm/test/CodeGen/X86/arg-copy-elide.ll b/llvm/test/CodeGen/X86/arg-copy-elide.ll
index f8761bd0ac9b4..36510e09beba2 100644
--- a/llvm/test/CodeGen/X86/arg-copy-elide.ll
+++ b/llvm/test/CodeGen/X86/arg-copy-elide.ll
@@ -232,7 +232,7 @@ entry:
 ; CHECK: retl
 
 
-define void @avoid_inalloca(i32* inalloca %x) {
+define void @avoid_inalloca(i32* inalloca(i32) %x) {
 entry:
   %x.p.p = alloca i32*
   store i32* %x, i32** %x.p.p

diff  --git a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
index 4e28b5f1a3e92..927956d441295 100644
--- a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
+++ b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll
@@ -25,7 +25,7 @@ entry:
           to label %invoke.cont unwind label %ehcleanup
 
 invoke.cont:                                      ; preds = %entry
-  call void @takes_two(<{ %struct.A, %struct.A }>* inalloca nonnull %argmem)
+  call void @takes_two(<{ %struct.A, %struct.A }>* inalloca(<{ %struct.A, %struct.A }>) nonnull %argmem)
   ret void
 
 ehcleanup:                                        ; preds = %entry
@@ -57,7 +57,7 @@ ehcleanup:                                        ; preds = %entry
 ; CHECK: addl $8, %esp
 ; CHECK: retl
 
-declare void @takes_two(<{ %struct.A, %struct.A }>* inalloca) #0
+declare void @takes_two(<{ %struct.A, %struct.A }>* inalloca(<{ %struct.A, %struct.A }>)) #0
 
 declare x86_thiscallcc %struct.A* @"\01??0A@@QAE at XZ"(%struct.A* returned) #0
 

diff  --git a/llvm/test/CodeGen/X86/inalloca-ctor.ll b/llvm/test/CodeGen/X86/inalloca-ctor.ll
index f13d537d90b8f..740c61a3e7d3a 100644
--- a/llvm/test/CodeGen/X86/inalloca-ctor.ll
+++ b/llvm/test/CodeGen/X86/inalloca-ctor.ll
@@ -4,7 +4,7 @@
 
 %frame = type { %Foo, i32, %Foo }
 
-declare void @f(%frame* inalloca %a)
+declare void @f(%frame* inalloca(%frame) %a)
 
 declare void @Foo_ctor(%Foo* %this)
 
@@ -28,7 +28,7 @@ entry:
 ; CHECK-NEXT: pushl
 ; CHECK-NEXT: calll _Foo_ctor
 ; CHECK: addl $4, %esp
-  call void @f(%frame* inalloca %args)
+  call void @f(%frame* inalloca(%frame) %args)
 ; CHECK: calll   _f
   ret void
 }

diff  --git a/llvm/test/CodeGen/X86/inalloca-invoke.ll b/llvm/test/CodeGen/X86/inalloca-invoke.ll
index 4623c58210a3e..39a9ac5751f29 100644
--- a/llvm/test/CodeGen/X86/inalloca-invoke.ll
+++ b/llvm/test/CodeGen/X86/inalloca-invoke.ll
@@ -9,7 +9,7 @@ declare void @llvm.stackrestore(i8*)
 declare i8* @llvm.stacksave()
 declare void @begin(%Iter* sret(%Iter))
 declare void @plus(%Iter* sret(%Iter), %Iter*, i32)
-declare void @reverse(%frame.reverse* inalloca align 4)
+declare void @reverse(%frame.reverse* inalloca(%frame.reverse) align 4)
 
 define i32 @main() personality i32 (...)* @pers {
   %temp.lvalue = alloca %Iter
@@ -42,7 +42,7 @@ invoke.cont:
 ; CHECK:  pushl %[[beg]]
 ; CHECK:  calll _begin
 
-  invoke void @reverse(%frame.reverse* inalloca align 4 %rev_args)
+  invoke void @reverse(%frame.reverse* inalloca(%frame.reverse) align 4 %rev_args)
           to label %invoke.cont5 unwind label %lpad
 
 invoke.cont5:                                     ; preds = %invoke.cont

diff  --git a/llvm/test/CodeGen/X86/inalloca-regparm.ll b/llvm/test/CodeGen/X86/inalloca-regparm.ll
index d379333a962f6..24a7d17d4b4aa 100644
--- a/llvm/test/CodeGen/X86/inalloca-regparm.ll
+++ b/llvm/test/CodeGen/X86/inalloca-regparm.ll
@@ -4,11 +4,11 @@
 ; This will compile successfully on x86 but not x86_64, because %b will become a
 ; register parameter.
 
-declare x86_thiscallcc i32 @f(i32 %a, i32* inalloca %b)
+declare x86_thiscallcc i32 @f(i32 %a, i32* inalloca(i32) %b)
 define void @g() {
   %b = alloca inalloca i32
   store i32 2, i32* %b
-  call x86_thiscallcc i32 @f(i32 0, i32* inalloca %b)
+  call x86_thiscallcc i32 @f(i32 0, i32* inalloca(i32) %b)
   ret void
 }
 

diff  --git a/llvm/test/CodeGen/X86/inalloca-stdcall.ll b/llvm/test/CodeGen/X86/inalloca-stdcall.ll
index 69d94d8bfa744..e0a292b866f2c 100644
--- a/llvm/test/CodeGen/X86/inalloca-stdcall.ll
+++ b/llvm/test/CodeGen/X86/inalloca-stdcall.ll
@@ -2,7 +2,7 @@
 
 %Foo = type { i32, i32 }
 
-declare x86_stdcallcc void @f(%Foo* inalloca %a)
+declare x86_stdcallcc void @f(%Foo* inalloca(%Foo) %a)
 declare x86_stdcallcc void @i(i32 %a)
 
 define void @g() {
@@ -17,7 +17,7 @@ define void @g() {
 ; CHECK: movl %esp, %eax
 ; CHECK: movl    $13, (%eax)
 ; CHECK: movl    $42, 4(%eax)
-  call x86_stdcallcc void @f(%Foo* inalloca %b)
+  call x86_stdcallcc void @f(%Foo* inalloca(%Foo) %b)
 ; CHECK: calll   _f at 8
 ; CHECK-NOT: %esp
 ; CHECK: pushl

diff  --git a/llvm/test/CodeGen/X86/inalloca.ll b/llvm/test/CodeGen/X86/inalloca.ll
index 134de2f58ddad..ed85c79f6d44c 100644
--- a/llvm/test/CodeGen/X86/inalloca.ll
+++ b/llvm/test/CodeGen/X86/inalloca.ll
@@ -2,7 +2,7 @@
 
 %Foo = type { i32, i32 }
 
-declare void @f(%Foo* inalloca %b)
+declare void @f(%Foo* inalloca(%Foo) %b)
 
 define void @a() {
 ; CHECK-LABEL: _a:
@@ -17,12 +17,12 @@ entry:
 ; CHECK: movl %esp, %eax
 ; CHECK: movl    $13, (%eax)
 ; CHECK: movl    $42, 4(%eax)
-  call void @f(%Foo* inalloca %b)
+  call void @f(%Foo* inalloca(%Foo) %b)
 ; CHECK: calll   _f
   ret void
 }
 
-declare void @inreg_with_inalloca(i32 inreg %a, %Foo* inalloca %b)
+declare void @inreg_with_inalloca(i32 inreg %a, %Foo* inalloca(%Foo) %b)
 
 define void @b() {
 ; CHECK-LABEL: _b:
@@ -37,13 +37,13 @@ entry:
 ; CHECK: movl %esp, %eax
 ; CHECK: movl    $13, (%eax)
 ; CHECK: movl    $42, 4(%eax)
-  call void @inreg_with_inalloca(i32 inreg 1, %Foo* inalloca %b)
+  call void @inreg_with_inalloca(i32 inreg 1, %Foo* inalloca(%Foo) %b)
 ; CHECK: movl    $1, %eax
 ; CHECK: calll   _inreg_with_inalloca
   ret void
 }
 
-declare x86_thiscallcc void @thiscall_with_inalloca(i8* %a, %Foo* inalloca %b)
+declare x86_thiscallcc void @thiscall_with_inalloca(i8* %a, %Foo* inalloca(%Foo) %b)
 
 define void @c() {
 ; CHECK-LABEL: _c:
@@ -58,7 +58,7 @@ entry:
 ; CHECK: movl %esp, %eax
 ; CHECK-DAG: movl    $13, (%eax)
 ; CHECK-DAG: movl    $42, 4(%eax)
-  call x86_thiscallcc void @thiscall_with_inalloca(i8* null, %Foo* inalloca %b)
+  call x86_thiscallcc void @thiscall_with_inalloca(i8* null, %Foo* inalloca(%Foo) %b)
 ; CHECK-DAG: xorl    %ecx, %ecx
 ; CHECK: calll   _thiscall_with_inalloca
   ret void

diff  --git a/llvm/test/CodeGen/X86/movtopush.ll b/llvm/test/CodeGen/X86/movtopush.ll
index fa200c2253b94..33e11235fe83b 100644
--- a/llvm/test/CodeGen/X86/movtopush.ll
+++ b/llvm/test/CodeGen/X86/movtopush.ll
@@ -15,7 +15,7 @@ declare void @eightparams(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g
 declare void @eightparams16(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e, i16 %f, i16 %g, i16 %h)
 declare void @eightparams64(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g, i64 %h)
 declare void @struct(%struct.s* byval(%struct.s) %a, i32 %b, i32 %c, i32 %d)
-declare void @inalloca(<{ %struct.s }>* inalloca)
+declare void @inalloca(<{ %struct.s }>* inalloca(<{ %struct.s }>))
 
 declare i8* @llvm.stacksave()
 declare void @llvm.stackrestore(i8*)

diff  --git a/llvm/test/CodeGen/X86/musttail-inalloca.ll b/llvm/test/CodeGen/X86/musttail-inalloca.ll
index c0e571a7213b4..f3e27fac3a9d8 100644
--- a/llvm/test/CodeGen/X86/musttail-inalloca.ll
+++ b/llvm/test/CodeGen/X86/musttail-inalloca.ll
@@ -11,10 +11,10 @@ target triple = "i386-pc-windows-msvc19.16.0"
 ; 20 bytes of memory.
 %struct.Args = type { i32, i32, i32, i32, i32 }
 
-declare dso_local x86_thiscallcc void @methodWithVtorDisp(i8* nocapture readonly, <{ %struct.Args }>* inalloca)
+declare dso_local x86_thiscallcc void @methodWithVtorDisp(i8* nocapture readonly, <{ %struct.Args }>* inalloca(<{ %struct.Args }>))
 
 ; Function Attrs: nounwind optsize
-define dso_local x86_thiscallcc void @methodWithVtorDisp_thunk(i8* %0, <{ %struct.Args }>* inalloca %1) #0 {
+define dso_local x86_thiscallcc void @methodWithVtorDisp_thunk(i8* %0, <{ %struct.Args }>* inalloca(<{ %struct.Args }>) %1) #0 {
 ; CHECK-LABEL: methodWithVtorDisp_thunk:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    pushl %esi
@@ -34,7 +34,7 @@ define dso_local x86_thiscallcc void @methodWithVtorDisp_thunk(i8* %0, <{ %struc
   %7 = getelementptr i8, i8* %0, i32 %6
   %8 = call i8* @llvm.returnaddress(i32 0)
   call void @__cyg_profile_func_exit(i8* bitcast (void (i8*, <{ %struct.Args }>*)* @methodWithVtorDisp_thunk to i8*), i8* %8)
-  musttail call x86_thiscallcc void @methodWithVtorDisp(i8* %7, <{ %struct.Args }>* inalloca nonnull %1)
+  musttail call x86_thiscallcc void @methodWithVtorDisp(i8* %7, <{ %struct.Args }>* inalloca(<{ %struct.Args }>) nonnull %1)
   ret void
 }
 

diff  --git a/llvm/test/CodeGen/X86/musttail-indirect.ll b/llvm/test/CodeGen/X86/musttail-indirect.ll
index f30d775a343b3..cb7a31433e275 100644
--- a/llvm/test/CodeGen/X86/musttail-indirect.ll
+++ b/llvm/test/CodeGen/X86/musttail-indirect.ll
@@ -42,13 +42,13 @@ entry:
 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
 ; CHECK: jmpl
 ; CHECK-NOT: ret
-define x86_thiscallcc i32 @g_thunk(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca) {
+define x86_thiscallcc i32 @g_thunk(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca(<{ %struct.A, i32, %struct.A }>)) {
 entry:
   %1 = bitcast %struct.B* %this to i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)***
   %vtable = load i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)**, i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*** %1
   %vfn = getelementptr inbounds i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*, i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)** %vtable, i32 1
   %2 = load i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*, i32 (%struct.B*, <{ %struct.A, i32, %struct.A }>*)** %vfn
-  %3 = musttail call x86_thiscallcc i32 %2(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca %0)
+  %3 = musttail call x86_thiscallcc i32 %2(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca(<{ %struct.A, i32, %struct.A }>) %0)
   ret i32 %3
 }
 
@@ -71,13 +71,13 @@ entry:
 ; CHECK: jmpl
 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
 ; CHECK-NOT: ret
-define x86_thiscallcc void @h_thunk(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca) {
+define x86_thiscallcc void @h_thunk(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca(<{ %struct.A, i32, %struct.A }>)) {
 entry:
   %1 = bitcast %struct.B* %this to void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)***
   %vtable = load void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)**, void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*** %1
   %vfn = getelementptr inbounds void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*, void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)** %vtable, i32 2
   %2 = load void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)*, void (%struct.B*, <{ %struct.A, i32, %struct.A }>*)** %vfn
-  musttail call x86_thiscallcc void %2(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca %0)
+  musttail call x86_thiscallcc void %2(%struct.B* %this, <{ %struct.A, i32, %struct.A }>* inalloca(<{ %struct.A, i32, %struct.A }>) %0)
   ret void
 }
 
@@ -99,13 +99,13 @@ entry:
 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
 ; CHECK: jmpl
 ; CHECK-NOT: ret
-define x86_thiscallcc %struct.A* @i_thunk(%struct.B* %this, <{ %struct.A*, %struct.A, i32, %struct.A }>* inalloca) {
+define x86_thiscallcc %struct.A* @i_thunk(%struct.B* %this, <{ %struct.A*, %struct.A, i32, %struct.A }>* inalloca(<{ %struct.A*, %struct.A, i32, %struct.A }>)) {
 entry:
   %1 = bitcast %struct.B* %this to %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)***
   %vtable = load %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)**, %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)*** %1
   %vfn = getelementptr inbounds %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)*, %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)** %vtable, i32 3
   %2 = load %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)*, %struct.A* (%struct.B*, <{ %struct.A*, %struct.A, i32, %struct.A }>*)** %vfn
-  %3 = musttail call x86_thiscallcc %struct.A* %2(%struct.B* %this, <{ %struct.A*, %struct.A, i32, %struct.A }>* inalloca %0)
+  %3 = musttail call x86_thiscallcc %struct.A* %2(%struct.B* %this, <{ %struct.A*, %struct.A, i32, %struct.A }>* inalloca(<{ %struct.A*, %struct.A, i32, %struct.A }>) %0)
   ret %struct.A* %3
 }
 
@@ -140,7 +140,7 @@ entry:
 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
 ; CHECK: jmpl
 ; CHECK-NOT: ret
-define x86_stdcallcc i32 @stdcall_thunk(<{ %struct.B*, %struct.A }>* inalloca) {
+define x86_stdcallcc i32 @stdcall_thunk(<{ %struct.B*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A }>)) {
 entry:
   %this_ptr = getelementptr inbounds <{ %struct.B*, %struct.A }>, <{ %struct.B*, %struct.A }>* %0, i32 0, i32 0
   %this = load %struct.B*, %struct.B** %this_ptr
@@ -148,7 +148,7 @@ entry:
   %vtable = load i32 (<{ %struct.B*, %struct.A }>*)**, i32 (<{ %struct.B*, %struct.A }>*)*** %1
   %vfn = getelementptr inbounds i32 (<{ %struct.B*, %struct.A }>*)*, i32 (<{ %struct.B*, %struct.A }>*)** %vtable, i32 1
   %2 = load i32 (<{ %struct.B*, %struct.A }>*)*, i32 (<{ %struct.B*, %struct.A }>*)** %vfn
-  %3 = musttail call x86_stdcallcc i32 %2(<{ %struct.B*, %struct.A }>* inalloca %0)
+  %3 = musttail call x86_stdcallcc i32 %2(<{ %struct.B*, %struct.A }>* inalloca(<{ %struct.B*, %struct.A }>) %0)
   ret i32 %3
 }
 
@@ -172,13 +172,13 @@ entry:
 ; CHECK-NOT: mov %{{.*}}, {{.*(.*esp.*)}}
 ; CHECK: jmpl
 ; CHECK-NOT: ret
-define x86_fastcallcc i32 @fastcall_thunk(%struct.B* inreg %this, <{ %struct.A }>* inalloca) {
+define x86_fastcallcc i32 @fastcall_thunk(%struct.B* inreg %this, <{ %struct.A }>* inalloca(<{ %struct.A }>)) {
 entry:
   %1 = bitcast %struct.B* %this to i32 (%struct.B*, <{ %struct.A }>*)***
   %vtable = load i32 (%struct.B*, <{ %struct.A }>*)**, i32 (%struct.B*, <{ %struct.A }>*)*** %1
   %vfn = getelementptr inbounds i32 (%struct.B*, <{ %struct.A }>*)*, i32 (%struct.B*, <{ %struct.A }>*)** %vtable, i32 1
   %2 = load i32 (%struct.B*, <{ %struct.A }>*)*, i32 (%struct.B*, <{ %struct.A }>*)** %vfn
-  %3 = musttail call x86_fastcallcc i32 %2(%struct.B* inreg %this, <{ %struct.A }>* inalloca %0)
+  %3 = musttail call x86_fastcallcc i32 %2(%struct.B* inreg %this, <{ %struct.A }>* inalloca(<{ %struct.A }>) %0)
   ret i32 %3
 }
 

diff  --git a/llvm/test/CodeGen/X86/musttail-thiscall.ll b/llvm/test/CodeGen/X86/musttail-thiscall.ll
index 682f85e1eb852..b9994963132c7 100644
--- a/llvm/test/CodeGen/X86/musttail-thiscall.ll
+++ b/llvm/test/CodeGen/X86/musttail-thiscall.ll
@@ -21,14 +21,14 @@ declare x86_thiscallcc i32 @t2_callee(i8* %this, i32 %a)
 
 ; CHECK-LABEL: t3:
 ; CHECK: jmp {{_?}}t3_callee
-define x86_thiscallcc i8* @t3(i8* %this, <{ i8*, i32 }>* inalloca %args) {
+define x86_thiscallcc i8* @t3(i8* %this, <{ i8*, i32 }>* inalloca(<{ i8*, i32 }>) %args) {
   %adj = getelementptr i8, i8* %this, i32 4
   %a_ptr = getelementptr <{ i8*, i32 }>, <{ i8*, i32 }>* %args, i32 0, i32 1
   store i32 0, i32* %a_ptr
-  %rv = musttail call x86_thiscallcc i8* @t3_callee(i8* %adj, <{ i8*, i32 }>* inalloca %args)
+  %rv = musttail call x86_thiscallcc i8* @t3_callee(i8* %adj, <{ i8*, i32 }>* inalloca(<{ i8*, i32 }>) %args)
   ret i8* %rv
 }
-declare x86_thiscallcc i8* @t3_callee(i8* %this, <{ i8*, i32 }>* inalloca %args);
+declare x86_thiscallcc i8* @t3_callee(i8* %this, <{ i8*, i32 }>* inalloca(<{ i8*, i32 }>) %args);
 
 ; CHECK-LABEL: t4:
 ; CHECK: jmp {{_?}}t4_callee

diff  --git a/llvm/test/CodeGen/X86/shrink-wrap-chkstk.ll b/llvm/test/CodeGen/X86/shrink-wrap-chkstk.ll
index 32e046df6bb05..241d42c3227b2 100644
--- a/llvm/test/CodeGen/X86/shrink-wrap-chkstk.ll
+++ b/llvm/test/CodeGen/X86/shrink-wrap-chkstk.ll
@@ -25,7 +25,7 @@ bb1:
   br label %bb2
 
 bb2:
-  call void @inalloca_params(<{ %struct.S }>* inalloca nonnull %argmem)
+  call void @inalloca_params(<{ %struct.S }>* inalloca(<{ %struct.S }>) nonnull %argmem)
   ret void
 }
 
@@ -39,7 +39,7 @@ bb2:
 ; CHECK: popl %ebp
 ; CHECK: retl
 
-declare void @inalloca_params(<{ %struct.S }>* inalloca)
+declare void @inalloca_params(<{ %struct.S }>* inalloca(<{ %struct.S }>))
 
 declare i32 @doSomething(i32, i32*)
 

diff  --git a/llvm/test/CodeGen/X86/tail-call-mutable-memarg.ll b/llvm/test/CodeGen/X86/tail-call-mutable-memarg.ll
index 34db632ec2050..e4b9dada399d7 100644
--- a/llvm/test/CodeGen/X86/tail-call-mutable-memarg.ll
+++ b/llvm/test/CodeGen/X86/tail-call-mutable-memarg.ll
@@ -24,7 +24,7 @@ entry:
 ; CHECK:         calll   _tail_std at 4
 ; CHECK:         retl    $4
 
-define x86_thiscallcc void @inalloca(i32* %this, i32* inalloca %args) {
+define x86_thiscallcc void @inalloca(i32* %this, i32* inalloca(i32) %args) {
 entry:
   %val = load i32, i32* %args
   store i32 0, i32* %args

diff  --git a/llvm/test/CodeGen/X86/x86-repmov-copy-eflags.ll b/llvm/test/CodeGen/X86/x86-repmov-copy-eflags.ll
index 91bce1610c8b8..110691504655b 100644
--- a/llvm/test/CodeGen/X86/x86-repmov-copy-eflags.ll
+++ b/llvm/test/CodeGen/X86/x86-repmov-copy-eflags.ll
@@ -5,7 +5,7 @@ target triple = "i686-pc-windows-msvc18.0.0"
 %struct.T = type { i64, [3 x i32] }
 
 ; Function Attrs: nounwind optsize
-define void @f(i8* %p, i8* %q, i32* inalloca nocapture %unused) #0 {
+define void @f(i8* %p, i8* %q, i32* inalloca(i32) nocapture %unused) #0 {
 entry:
   %g = alloca %struct.T, align 8
   %r = alloca i32, align 8
@@ -25,7 +25,7 @@ while.end:                                        ; preds = %while.body
   ret void
 }
 
-define void @f_pgso(i8* %p, i8* %q, i32* inalloca nocapture %unused) !prof !14 {
+define void @f_pgso(i8* %p, i8* %q, i32* inalloca(i32) nocapture %unused) !prof !14 {
 entry:
   %g = alloca %struct.T, align 8
   %r = alloca i32, align 8

diff  --git a/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll b/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll
index ce5e583f91154..d6920a7f9a59f 100644
--- a/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll
+++ b/llvm/test/DebugInfo/X86/dbg-declare-inalloca.ll
@@ -109,7 +109,7 @@ target triple = "i386-pc-windows-msvc19.10.24728"
 %struct.NonTrivial = type { i32 }
 
 ; Function Attrs: nounwind
-define void @f(<{ %struct.NonTrivial, i32, i32, i32 }>* inalloca) local_unnamed_addr #0 !dbg !7 {
+define void @f(<{ %struct.NonTrivial, i32, i32, i32 }>* inalloca(<{ %struct.NonTrivial, i32, i32, i32 }>)) local_unnamed_addr #0 !dbg !7 {
 entry:
   %a = getelementptr inbounds <{ %struct.NonTrivial, i32, i32, i32 }>, <{ %struct.NonTrivial, i32, i32, i32 }>* %0, i32 0, i32 0
   %b = getelementptr inbounds <{ %struct.NonTrivial, i32, i32, i32 }>, <{ %struct.NonTrivial, i32, i32, i32 }>* %0, i32 0, i32 1

diff  --git a/llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll
index 434e4be4e8e6d..257c0cbf0c7e9 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll
@@ -31,8 +31,8 @@ define void @has_inalloca() uwtable sanitize_address {
 entry:
   %t = alloca inalloca i32
   store i32 42, i32* %t
-  call void @pass_inalloca(i32* inalloca %t)
+  call void @pass_inalloca(i32* inalloca(i32) %t)
   ret void
 }
 
-declare void @pass_inalloca(i32* inalloca)
+declare void @pass_inalloca(i32* inalloca(i32))

diff  --git a/llvm/test/Linker/Inputs/inalloca-type-input.ll b/llvm/test/Linker/Inputs/inalloca-type-input.ll
new file mode 100644
index 0000000000000..7fa2d8fdb3f3d
--- /dev/null
+++ b/llvm/test/Linker/Inputs/inalloca-type-input.ll
@@ -0,0 +1,13 @@
+%a = type { i64 }
+%struct = type { i32, i8 }
+
+define void @g(%a* inalloca(%a)) {
+  ret void
+}
+
+declare void @baz(%struct* inalloca(%struct))
+
+define void @foo(%struct* inalloca(%struct) %a) {
+  call void @baz(%struct* inalloca(%struct) %a)
+  ret void
+}

diff  --git a/llvm/test/Linker/inalloca-types.ll b/llvm/test/Linker/inalloca-types.ll
new file mode 100644
index 0000000000000..36cc9c3f7ef4a
--- /dev/null
+++ b/llvm/test/Linker/inalloca-types.ll
@@ -0,0 +1,25 @@
+; RUN: llvm-link %s %p/Inputs/inalloca-type-input.ll -S | FileCheck %s
+
+%a = type { i64 }
+%struct = type { i32, i8 }
+
+; CHECK-LABEL: define void @f(%a* inalloca(%a) %0)
+define void @f(%a* inalloca(%a)) {
+  ret void
+}
+
+; CHECK-LABEL: define void @bar(
+; CHECK: call void @foo(%struct* inalloca(%struct) %ptr)
+define void @bar() {
+  %ptr = alloca inalloca %struct
+  call void @foo(%struct* inalloca(%struct) %ptr)
+  ret void
+}
+
+; CHECK-LABEL: define void @g(%a* inalloca(%a) %0)
+
+; CHECK-LABEL: define void @foo(%struct* inalloca(%struct) %a)
+; CHECK-NEXT:   call void @baz(%struct* inalloca(%struct) %a)
+declare void @foo(%struct* inalloca(%struct) %a)
+
+; CHECK: declare void @baz(%struct* inalloca(%struct))

diff  --git a/llvm/test/Transforms/ArgumentPromotion/X86/thiscall.ll b/llvm/test/Transforms/ArgumentPromotion/X86/thiscall.ll
index d9f3681ba4ab2..0643397be0992 100644
--- a/llvm/test/Transforms/ArgumentPromotion/X86/thiscall.ll
+++ b/llvm/test/Transforms/ArgumentPromotion/X86/thiscall.ll
@@ -12,25 +12,25 @@ target triple = "i386-pc-windows-msvc19.11.0"
 
 %struct.a = type { i8 }
 
-define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a }>* inalloca) {
+define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a }>* inalloca(<{ %struct.a }>)) {
 ; ARGPROMOTION-LABEL: define {{[^@]+}}@internalfun
-; ARGPROMOTION-SAME: (%struct.a* [[THIS:%.*]], <{ [[STRUCT_A:%.*]] }>* inalloca [[TMP0:%.*]])
+; ARGPROMOTION-SAME: (%struct.a* [[THIS:%.*]], <{ [[STRUCT_A:%.*]] }>* inalloca(<{ [[STRUCT_A]] }>) [[TMP0:%.*]]) {
 ; ARGPROMOTION-NEXT:  entry:
 ; ARGPROMOTION-NEXT:    [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0
 ; ARGPROMOTION-NEXT:    [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4
 ; ARGPROMOTION-NEXT:    [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0
 ; ARGPROMOTION-NEXT:    [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* [[TMP1]], %struct.a* dereferenceable(1) [[A]])
-; ARGPROMOTION-NEXT:    call void @ext(<{ [[STRUCT_A]] }>* inalloca [[ARGMEM]])
+; ARGPROMOTION-NEXT:    call void @ext(<{ [[STRUCT_A]] }>* inalloca(<{ [[STRUCT_A]] }>) [[ARGMEM]])
 ; ARGPROMOTION-NEXT:    ret void
 ;
 ; GLOBALOPT_ARGPROMOTION-LABEL: define {{[^@]+}}@internalfun
-; GLOBALOPT_ARGPROMOTION-SAME: (<{ [[STRUCT_A:%.*]] }>* [[TMP0:%.*]]) unnamed_addr
+; GLOBALOPT_ARGPROMOTION-SAME: (<{ [[STRUCT_A:%.*]] }>* [[TMP0:%.*]]) unnamed_addr {
 ; GLOBALOPT_ARGPROMOTION-NEXT:  entry:
 ; GLOBALOPT_ARGPROMOTION-NEXT:    [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0
 ; GLOBALOPT_ARGPROMOTION-NEXT:    [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4
 ; GLOBALOPT_ARGPROMOTION-NEXT:    [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0
 ; GLOBALOPT_ARGPROMOTION-NEXT:    [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* [[TMP1]], %struct.a* dereferenceable(1) [[A]])
-; GLOBALOPT_ARGPROMOTION-NEXT:    call void @ext(<{ [[STRUCT_A]] }>* inalloca [[ARGMEM]])
+; GLOBALOPT_ARGPROMOTION-NEXT:    call void @ext(<{ [[STRUCT_A]] }>* inalloca(<{ [[STRUCT_A]] }>) [[ARGMEM]])
 ; GLOBALOPT_ARGPROMOTION-NEXT:    ret void
 ;
 entry:
@@ -38,22 +38,22 @@ entry:
   %argmem = alloca inalloca <{ %struct.a }>, align 4
   %1 = getelementptr inbounds <{ %struct.a }>, <{ %struct.a }>* %argmem, i32 0, i32 0
   %call = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* %1, %struct.a* dereferenceable(1) %a)
-  call void @ext(<{ %struct.a }>* inalloca %argmem)
+  call void @ext(<{ %struct.a }>* inalloca(<{ %struct.a }>) %argmem)
   ret void
 }
 
 ; This is here to ensure @internalfun is live.
 define void @exportedfun(%struct.a* %a) {
 ; ARGPROMOTION-LABEL: define {{[^@]+}}@exportedfun
-; ARGPROMOTION-SAME: (%struct.a* [[A:%.*]])
+; ARGPROMOTION-SAME: (%struct.a* [[A:%.*]]) {
 ; ARGPROMOTION-NEXT:    [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave()
 ; ARGPROMOTION-NEXT:    [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4
-; ARGPROMOTION-NEXT:    call x86_thiscallcc void @internalfun(%struct.a* [[A]], <{ [[STRUCT_A]] }>* inalloca [[ARGMEM]])
+; ARGPROMOTION-NEXT:    call x86_thiscallcc void @internalfun(%struct.a* [[A]], <{ [[STRUCT_A]] }>* inalloca(<{ [[STRUCT_A]] }>) [[ARGMEM]])
 ; ARGPROMOTION-NEXT:    call void @llvm.stackrestore(i8* [[INALLOCA_SAVE]])
 ; ARGPROMOTION-NEXT:    ret void
 ;
 ; GLOBALOPT_ARGPROMOTION-LABEL: define {{[^@]+}}@exportedfun
-; GLOBALOPT_ARGPROMOTION-SAME: (%struct.a* [[A:%.*]]) local_unnamed_addr
+; GLOBALOPT_ARGPROMOTION-SAME: (%struct.a* [[A:%.*]]) local_unnamed_addr {
 ; GLOBALOPT_ARGPROMOTION-NEXT:    [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave()
 ; GLOBALOPT_ARGPROMOTION-NEXT:    [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4
 ; GLOBALOPT_ARGPROMOTION-NEXT:    call fastcc void @internalfun(<{ [[STRUCT_A]] }>* [[ARGMEM]])
@@ -62,12 +62,12 @@ define void @exportedfun(%struct.a* %a) {
 ;
   %inalloca.save = tail call i8* @llvm.stacksave()
   %argmem = alloca inalloca <{ %struct.a }>, align 4
-  call x86_thiscallcc void @internalfun(%struct.a* %a, <{ %struct.a }>* inalloca %argmem)
+  call x86_thiscallcc void @internalfun(%struct.a* %a, <{ %struct.a }>* inalloca(<{ %struct.a }>) %argmem)
   call void @llvm.stackrestore(i8* %inalloca.save)
   ret void
 }
 
 declare x86_thiscallcc %struct.a* @copy_ctor(%struct.a* returned, %struct.a* dereferenceable(1))
-declare void @ext(<{ %struct.a }>* inalloca)
+declare void @ext(<{ %struct.a }>* inalloca(<{ %struct.a }>))
 declare i8* @llvm.stacksave()
 declare void @llvm.stackrestore(i8*)

diff  --git a/llvm/test/Transforms/ArgumentPromotion/inalloca.ll b/llvm/test/Transforms/ArgumentPromotion/inalloca.ll
index ebf3d18f2fc5c..7eaa7499af6b4 100644
--- a/llvm/test/Transforms/ArgumentPromotion/inalloca.ll
+++ b/llvm/test/Transforms/ArgumentPromotion/inalloca.ll
@@ -7,9 +7,9 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1
 %struct.ss = type { i32, i32 }
 
 ; Argpromote + sroa should change this to passing the two integers by value.
-define internal i32 @f(%struct.ss* inalloca  %s) {
+define internal i32 @f(%struct.ss* inalloca(%struct.ss)  %s) {
 ; CHECK-LABEL: define {{[^@]+}}@f
-; CHECK-SAME: (i32 [[S_0_0_VAL:%.*]], i32 [[S_0_1_VAL:%.*]]) unnamed_addr
+; CHECK-SAME: (i32 [[S_0_0_VAL:%.*]], i32 [[S_0_1_VAL:%.*]]) unnamed_addr {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[R:%.*]] = add i32 [[S_0_0_VAL]], [[S_0_1_VAL]]
 ; CHECK-NEXT:    ret i32 [[R]]
@@ -24,7 +24,7 @@ entry:
 }
 
 define i32 @main() {
-; CHECK-LABEL: define {{[^@]+}}@main() local_unnamed_addr
+; CHECK-LABEL: define {{[^@]+}}@main() local_unnamed_addr {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[R:%.*]] = call fastcc i32 @f(i32 1, i32 2)
 ; CHECK-NEXT:    ret i32 [[R]]
@@ -35,14 +35,14 @@ entry:
   %f1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1
   store i32 1, i32* %f0, align 4
   store i32 2, i32* %f1, align 4
-  %r = call i32 @f(%struct.ss* inalloca %S)
+  %r = call i32 @f(%struct.ss* inalloca(%struct.ss) %S)
   ret i32 %r
 }
 
 ; Argpromote can't promote %a because of the icmp use.
-define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca %b) nounwind  {
+define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca(%struct.ss) %b) nounwind  {
 ; CHECK-LABEL: define {{[^@]+}}@g
-; CHECK-SAME: (%struct.ss* [[A:%.*]], %struct.ss* [[B:%.*]]) unnamed_addr
+; CHECK-SAME: (%struct.ss* [[A:%.*]], %struct.ss* [[B:%.*]]) unnamed_addr #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[C:%.*]] = icmp eq %struct.ss* [[A]], [[B]]
 ; CHECK-NEXT:    ret i1 [[C]]
@@ -53,14 +53,14 @@ entry:
 }
 
 define i32 @test() {
-; CHECK-LABEL: define {{[^@]+}}@test() local_unnamed_addr
+; CHECK-LABEL: define {{[^@]+}}@test() local_unnamed_addr {
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]]
+; CHECK-NEXT:    [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]], align 4
 ; CHECK-NEXT:    [[C:%.*]] = call fastcc i1 @g(%struct.ss* [[S]], %struct.ss* [[S]])
 ; CHECK-NEXT:    ret i32 0
 ;
 entry:
   %S = alloca inalloca %struct.ss
-  %c = call i1 @g(%struct.ss* %S, %struct.ss* inalloca %S)
+  %c = call i1 @g(%struct.ss* %S, %struct.ss* inalloca(%struct.ss) %S)
   ret i32 0
 }

diff  --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll
index 9937e6cf20729..ad452d68acbdc 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll
@@ -14,15 +14,15 @@ target triple = "i386-pc-windows-msvc19.11.0"
 
 %struct.a = type { i8 }
 
-define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a }>* inalloca) {
+define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a }>* inalloca(<{ %struct.a }>)) {
 ; CHECK-LABEL: define {{[^@]+}}@internalfun
-; CHECK-SAME: (%struct.a* noalias nocapture nofree readnone [[THIS:%.*]], <{ [[STRUCT_A:%.*]] }>* inalloca noundef nonnull align 4 dereferenceable(1) [[TMP0:%.*]]) {
+; CHECK-SAME: (%struct.a* noalias nocapture nofree readnone [[THIS:%.*]], <{ [[STRUCT_A:%.*]] }>* noundef nonnull inalloca(<{ [[STRUCT_A]] }>) align 4 dereferenceable(1) [[TMP0:%.*]]) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0
 ; CHECK-NEXT:    [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4
 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0
 ; CHECK-NEXT:    [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* noundef nonnull align 4 dereferenceable(1) [[TMP1]], %struct.a* noundef nonnull align 4 dereferenceable(1) [[A]])
-; CHECK-NEXT:    call void @ext(<{ [[STRUCT_A]] }>* inalloca noundef nonnull align 4 dereferenceable(1) [[ARGMEM]])
+; CHECK-NEXT:    call void @ext(<{ [[STRUCT_A]] }>* noundef nonnull inalloca(<{ [[STRUCT_A]] }>) align 4 dereferenceable(1) [[ARGMEM]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
@@ -30,7 +30,7 @@ entry:
   %argmem = alloca inalloca <{ %struct.a }>, align 4
   %1 = getelementptr inbounds <{ %struct.a }>, <{ %struct.a }>* %argmem, i32 0, i32 0
   %call = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* %1, %struct.a* dereferenceable(1) %a)
-  call void @ext(<{ %struct.a }>* inalloca %argmem)
+  call void @ext(<{ %struct.a }>* inalloca(<{ %struct.a }>) %argmem)
   ret void
 }
 
@@ -40,19 +40,19 @@ define void @exportedfun(%struct.a* %a) {
 ; CHECK-SAME: (%struct.a* nocapture nofree readnone [[A:%.*]]) {
 ; CHECK-NEXT:    [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave() #[[ATTR1:[0-9]+]]
 ; CHECK-NEXT:    [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4
-; CHECK-NEXT:    call x86_thiscallcc void @internalfun(%struct.a* noalias nocapture nofree readnone undef, <{ [[STRUCT_A]] }>* inalloca noundef nonnull align 4 dereferenceable(1) [[ARGMEM]])
+; CHECK-NEXT:    call x86_thiscallcc void @internalfun(%struct.a* noalias nocapture nofree readnone undef, <{ [[STRUCT_A]] }>* noundef nonnull inalloca(<{ [[STRUCT_A]] }>) align 4 dereferenceable(1) [[ARGMEM]])
 ; CHECK-NEXT:    call void @llvm.stackrestore(i8* nofree [[INALLOCA_SAVE]])
 ; CHECK-NEXT:    ret void
 ;
   %inalloca.save = tail call i8* @llvm.stacksave()
   %argmem = alloca inalloca <{ %struct.a }>, align 4
-  call x86_thiscallcc void @internalfun(%struct.a* %a, <{ %struct.a }>* inalloca %argmem)
+  call x86_thiscallcc void @internalfun(%struct.a* %a, <{ %struct.a }>* inalloca(<{ %struct.a }>) %argmem)
   call void @llvm.stackrestore(i8* %inalloca.save)
   ret void
 }
 
 declare x86_thiscallcc %struct.a* @copy_ctor(%struct.a* returned, %struct.a* dereferenceable(1))
-declare void @ext(<{ %struct.a }>* inalloca)
+declare void @ext(<{ %struct.a }>* inalloca(<{ %struct.a }>))
 declare i8* @llvm.stacksave()
 declare void @llvm.stackrestore(i8*)
 ;.

diff  --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll
index 30575fe8bde93..0b82eac6b982a 100644
--- a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll
@@ -9,12 +9,12 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1
 %struct.ss = type { i32, i32 }
 
 ; Argpromote + sroa should change this to passing the two integers by value.
-define internal i32 @f(%struct.ss* inalloca  %s) {
+define internal i32 @f(%struct.ss* inalloca(%struct.ss) %s) {
 ; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn
 ; IS__TUNIT____-LABEL: define {{[^@]+}}@f
-; IS__TUNIT____-SAME: (%struct.ss* inalloca noalias nocapture nofree noundef nonnull align 4 dereferenceable(8) [[S:%.*]]) #[[ATTR0:[0-9]+]] {
+; IS__TUNIT____-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull inalloca([[STRUCT_SS:%.*]]) align 4 dereferenceable(8) [[S:%.*]]) #[[ATTR0:[0-9]+]] {
 ; IS__TUNIT____-NEXT:  entry:
-; IS__TUNIT____-NEXT:    [[F0:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[S]], i32 0, i32 0
+; IS__TUNIT____-NEXT:    [[F0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
 ; IS__TUNIT____-NEXT:    [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
 ; IS__TUNIT____-NEXT:    [[A:%.*]] = load i32, i32* [[F0]], align 4
 ; IS__TUNIT____-NEXT:    [[B:%.*]] = load i32, i32* [[F1]], align 4
@@ -23,9 +23,9 @@ define internal i32 @f(%struct.ss* inalloca  %s) {
 ;
 ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@f
-; IS__CGSCC____-SAME: (%struct.ss* inalloca noalias nocapture nofree noundef nonnull align 4 dereferenceable(8) [[S:%.*]]) #[[ATTR0:[0-9]+]] {
+; IS__CGSCC____-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull inalloca([[STRUCT_SS:%.*]]) align 4 dereferenceable(8) [[S:%.*]]) #[[ATTR0:[0-9]+]] {
 ; IS__CGSCC____-NEXT:  entry:
-; IS__CGSCC____-NEXT:    [[F0:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[S]], i32 0, i32 0
+; IS__CGSCC____-NEXT:    [[F0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
 ; IS__CGSCC____-NEXT:    [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
 ; IS__CGSCC____-NEXT:    [[A:%.*]] = load i32, i32* [[F0]], align 4
 ; IS__CGSCC____-NEXT:    [[B:%.*]] = load i32, i32* [[F1]], align 4
@@ -51,7 +51,7 @@ define i32 @main() {
 ; IS__TUNIT____-NEXT:    [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
 ; IS__TUNIT____-NEXT:    store i32 1, i32* [[F0]], align 4
 ; IS__TUNIT____-NEXT:    store i32 2, i32* [[F1]], align 4
-; IS__TUNIT____-NEXT:    [[R:%.*]] = call i32 @f(%struct.ss* inalloca noalias nocapture nofree noundef nonnull align 4 dereferenceable(8) [[S]]) #[[ATTR2:[0-9]+]]
+; IS__TUNIT____-NEXT:    [[R:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull inalloca([[STRUCT_SS]]) align 4 dereferenceable(8) [[S]]) #[[ATTR2:[0-9]+]]
 ; IS__TUNIT____-NEXT:    ret i32 [[R]]
 ;
 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
@@ -63,7 +63,7 @@ define i32 @main() {
 ; IS__CGSCC____-NEXT:    [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
 ; IS__CGSCC____-NEXT:    store i32 1, i32* [[F0]], align 4
 ; IS__CGSCC____-NEXT:    store i32 2, i32* [[F1]], align 4
-; IS__CGSCC____-NEXT:    [[R:%.*]] = call i32 @f(%struct.ss* inalloca noalias nocapture nofree noundef nonnull align 4 dereferenceable(8) [[S]]) #[[ATTR2:[0-9]+]]
+; IS__CGSCC____-NEXT:    [[R:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull inalloca([[STRUCT_SS]]) align 4 dereferenceable(8) [[S]]) #[[ATTR2:[0-9]+]]
 ; IS__CGSCC____-NEXT:    ret i32 [[R]]
 ;
 entry:
@@ -72,15 +72,15 @@ entry:
   %f1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1
   store i32 1, i32* %f0, align 4
   store i32 2, i32* %f1, align 4
-  %r = call i32 @f(%struct.ss* inalloca %S)
+  %r = call i32 @f(%struct.ss* inalloca(%struct.ss) %S)
   ret i32 %r
 }
 
 ; Argpromote can't promote %a because of the icmp use.
-define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca %b) nounwind  {
+define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca(%struct.ss) %b) nounwind  {
 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@g
-; IS__CGSCC____-SAME: (%struct.ss* noalias nocapture nofree nonnull readnone align 4 dereferenceable(8) [[A:%.*]], %struct.ss* inalloca noalias nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[B:%.*]]) #[[ATTR1]] {
+; IS__CGSCC____-SAME: (%struct.ss* noalias nocapture nofree nonnull readnone align 4 dereferenceable(8) [[A:%.*]], %struct.ss* noalias nocapture nofree nonnull writeonly inalloca([[STRUCT_SS:%.*]]) align 4 dereferenceable(8) [[B:%.*]]) #[[ATTR1]] {
 ; IS__CGSCC____-NEXT:  entry:
 ; IS__CGSCC____-NEXT:    ret i1 undef
 ;
@@ -104,7 +104,7 @@ define i32 @test() {
 ;
 entry:
   %S = alloca inalloca %struct.ss
-  %c = call i1 @g(%struct.ss* %S, %struct.ss* inalloca %S)
+  %c = call i1 @g(%struct.ss* %S, %struct.ss* inalloca(%struct.ss) %S)
   ret i32 0
 }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/readattrs.ll b/llvm/test/Transforms/Attributor/readattrs.ll
index 9f28407c76c47..c440e12ddfce4 100644
--- a/llvm/test/Transforms/Attributor/readattrs.ll
+++ b/llvm/test/Transforms/Attributor/readattrs.ll
@@ -107,15 +107,15 @@ define void @test6_2(i8** %p, i8* %q) {
 }
 
 ; inalloca parameters are always considered written
-define void @test7_1(i32* inalloca %a) {
+define void @test7_1(i32* inalloca(i32) %a) {
 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
 ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7_1
-; IS__TUNIT____-SAME: (i32* inalloca nocapture nofree nonnull writeonly dereferenceable(4) [[A:%.*]]) #[[ATTR1]] {
+; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly inalloca(i32) dereferenceable(4) [[A:%.*]]) #[[ATTR1]] {
 ; IS__TUNIT____-NEXT:    ret void
 ;
 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@test7_1
-; IS__CGSCC____-SAME: (i32* inalloca nocapture nofree nonnull writeonly dereferenceable(4) [[A:%.*]]) #[[ATTR1]] {
+; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly inalloca(i32) dereferenceable(4) [[A:%.*]]) #[[ATTR1]] {
 ; IS__CGSCC____-NEXT:    ret void
 ;
   ret void

diff  --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll
index 41fa16c0284a8..0ed93a912789b 100644
--- a/llvm/test/Transforms/Attributor/value-simplify.ll
+++ b/llvm/test/Transforms/Attributor/value-simplify.ll
@@ -332,15 +332,15 @@ define i32 @ipccp3() {
 
 ; Do not touch complicated arguments (for now)
 %struct.X = type { i8* }
-define internal i32* @test_inalloca(i32* inalloca %a) {
+define internal i32* @test_inalloca(i32* inalloca(i32) %a) {
 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
 ; IS__TUNIT____-LABEL: define {{[^@]+}}@test_inalloca
-; IS__TUNIT____-SAME: (i32* inalloca noalias nofree nonnull returned writeonly dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {
+; IS__TUNIT____-SAME: (i32* noalias nofree nonnull returned writeonly inalloca(i32) dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {
 ; IS__TUNIT____-NEXT:    ret i32* [[A]]
 ;
 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@test_inalloca
-; IS__CGSCC____-SAME: (i32* inalloca noalias nofree noundef nonnull returned writeonly dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {
+; IS__CGSCC____-SAME: (i32* noalias nofree noundef nonnull returned writeonly inalloca(i32) dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {
 ; IS__CGSCC____-NEXT:    ret i32* [[A]]
 ;
   ret i32* %a

diff  --git a/llvm/test/Transforms/DeadArgElim/keepalive.ll b/llvm/test/Transforms/DeadArgElim/keepalive.ll
index fff14a7f52a85..b9be83e5cdf94 100644
--- a/llvm/test/Transforms/DeadArgElim/keepalive.ll
+++ b/llvm/test/Transforms/DeadArgElim/keepalive.ll
@@ -39,13 +39,13 @@ define void @caller() {
 
 ; We can't remove 'this' here, as that would put argmem in ecx instead of
 ; memory.
-define internal x86_thiscallcc i32 @unused_this(i32* %this, i32* inalloca %argmem) {
+define internal x86_thiscallcc i32 @unused_this(i32* %this, i32* inalloca(i32) %argmem) {
 ;
 ;
   %v = load i32, i32* %argmem
   ret i32 %v
 }
-; CHECK-LABEL: define internal x86_thiscallcc i32 @unused_this(i32* %this, i32* inalloca %argmem)
+; CHECK-LABEL: define internal x86_thiscallcc i32 @unused_this(i32* %this, i32* inalloca(i32) %argmem)
 
 define i32 @caller2() {
 ;
@@ -53,7 +53,7 @@ define i32 @caller2() {
   %t = alloca i32
   %m = alloca inalloca i32
   store i32 42, i32* %m
-  %v = call x86_thiscallcc i32 @unused_this(i32* %t, i32* inalloca %m)
+  %v = call x86_thiscallcc i32 @unused_this(i32* %t, i32* inalloca(i32) %m)
   ret i32 %v
 }
 

diff  --git a/llvm/test/Transforms/DeadStoreElimination/simple.ll b/llvm/test/Transforms/DeadStoreElimination/simple.ll
index 48a939c1228f9..361b243f51210 100644
--- a/llvm/test/Transforms/DeadStoreElimination/simple.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/simple.ll
@@ -148,7 +148,7 @@ define void @test9(%struct.x* byval(%struct.x)  %a) nounwind  {
 }
 
 ; Test for inalloca handling.
-define void @test9_2(%struct.x* inalloca  %a) nounwind  {
+define void @test9_2(%struct.x* inalloca(%struct.x) %a) nounwind {
 ; CHECK-LABEL: @test9_2(
 ; CHECK-NEXT:    ret void
 ;

diff  --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
index ae34219bd011e..6585ee4d24482 100644
--- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
@@ -50,9 +50,9 @@ define void @test6_2(i8** %p, i8* %q) {
   ret void
 }
 
-; CHECK: define void @test7_1(i32* inalloca nocapture %a)
+; CHECK: define void @test7_1(i32* nocapture inalloca(i32) %a)
 ; inalloca parameters are always considered written
-define void @test7_1(i32* inalloca %a) {
+define void @test7_1(i32* inalloca(i32) %a) {
   ret void
 }
 

diff  --git a/llvm/test/Transforms/GVNHoist/hoist-pr28606.ll b/llvm/test/Transforms/GVNHoist/hoist-pr28606.ll
index 2c588283ea914..d8bad7ae45638 100644
--- a/llvm/test/Transforms/GVNHoist/hoist-pr28606.ll
+++ b/llvm/test/Transforms/GVNHoist/hoist-pr28606.ll
@@ -5,7 +5,7 @@ target triple = "i686-pc-windows-msvc18.0.0"
 
 %struct.S = type { i8* }
 
-declare void @f(<{ %struct.S }>* inalloca)
+declare void @f(<{ %struct.S }>* inalloca(<{ %struct.S }>))
 
 
 ; Check that we don't clone the %x alloca and insert it in the live range of
@@ -41,7 +41,7 @@ false:
   br label %exit
 
 exit:
-  call void @f(<{ %struct.S }>* inalloca %argmem)
+  call void @f(<{ %struct.S }>* inalloca(<{ %struct.S }>) %argmem)
   call void @llvm.stackrestore(i8* %inalloca.save)
   ret void
 }

diff  --git a/llvm/test/Transforms/GlobalOpt/fastcc.ll b/llvm/test/Transforms/GlobalOpt/fastcc.ll
index edd0688ea92b7..0278d83d209f3 100644
--- a/llvm/test/Transforms/GlobalOpt/fastcc.ll
+++ b/llvm/test/Transforms/GlobalOpt/fastcc.ll
@@ -29,19 +29,19 @@ define internal i32 @j(i32* %m) {
   ret i32 %v
 }
 
-define internal i32 @inalloca(i32* inalloca %p) {
+define internal i32 @inalloca(i32* inalloca(i32) %p) {
 ; CHECK-LABEL: define internal fastcc i32 @inalloca(i32* %p)
   %rv = load i32, i32* %p
   ret i32 %rv
 }
 
-define i32 @inalloca2_caller(i32* inalloca %p) {
-  %rv = musttail call i32 @inalloca2(i32* inalloca %p)
+define i32 @inalloca2_caller(i32* inalloca(i32) %p) {
+  %rv = musttail call i32 @inalloca2(i32* inalloca(i32) %p)
   ret i32 %rv
 }
-define internal i32 @inalloca2(i32* inalloca %p) {
+define internal i32 @inalloca2(i32* inalloca(i32) %p) {
 ; Because of the musttail caller, this inalloca cannot be dropped.
-; CHECK-LABEL: define internal i32 @inalloca2(i32* inalloca %p)
+; CHECK-LABEL: define internal i32 @inalloca2(i32* inalloca(i32) %p)
   %rv = load i32, i32* %p
   ret i32 %rv
 }
@@ -59,7 +59,7 @@ define void @call_things() {
   call coldcc i32 @h(i32* %m)
   call i32 @j(i32* %m)
   %args = alloca inalloca i32
-  call i32 @inalloca(i32* inalloca %args)
+  call i32 @inalloca(i32* inalloca(i32) %args)
   %c = call token @llvm.call.preallocated.setup(i32 1)
   %N = call i8* @llvm.call.preallocated.arg(token %c, i32 0) preallocated(i32)
   %n = bitcast i8* %N to i32*

diff  --git a/llvm/test/Transforms/Inline/inalloca-not-static.ll b/llvm/test/Transforms/Inline/inalloca-not-static.ll
index 74b5ecf420ce9..1a6dd75a01781 100644
--- a/llvm/test/Transforms/Inline/inalloca-not-static.ll
+++ b/llvm/test/Transforms/Inline/inalloca-not-static.ll
@@ -41,13 +41,13 @@ entry:
   %argmem = alloca inalloca <{ %struct.Foo }>, align 4
   %0 = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %argmem, i32 0, i32 0
   %call = call x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE at XZ"(%struct.Foo* %0)
-  call void @h(<{ %struct.Foo }>* inalloca %argmem)
+  call void @h(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>) %argmem)
   call void @llvm.stackrestore(i8* %inalloca.save)
   ret void
 }
 
 ; Function Attrs: alwaysinline inlinehint nounwind
-define internal void @h(<{ %struct.Foo }>* inalloca) alwaysinline {
+define internal void @h(<{ %struct.Foo }>* inalloca(<{ %struct.Foo }>)) alwaysinline {
 entry:
   %o = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0
   call x86_thiscallcc void @"\01??1Foo@@QAE at XZ"(%struct.Foo* %o)

diff  --git a/llvm/test/Transforms/InstCombine/alloca.ll b/llvm/test/Transforms/InstCombine/alloca.ll
index 072d5f2fe9f94..fee8e0ef70f14 100644
--- a/llvm/test/Transforms/InstCombine/alloca.ll
+++ b/llvm/test/Transforms/InstCombine/alloca.ll
@@ -207,7 +207,7 @@ define void @test8() {
 
 ; PR19569
 %struct_type = type { i32, i32 }
-declare void @test9_aux(<{ %struct_type }>* inalloca)
+declare void @test9_aux(<{ %struct_type }>* inalloca(<{ %struct_type }>))
 declare i8* @llvm.stacksave()
 declare void @llvm.stackrestore(i8*)
 
@@ -219,7 +219,7 @@ define void @test9(%struct_type* %a) {
 ; ALL-NEXT:    [[TMP0:%.*]] = bitcast %struct_type* [[A:%.*]] to i64*
 ; ALL-NEXT:    [[TMP1:%.*]] = load i64, i64* [[TMP0]], align 4
 ; ALL-NEXT:    store i64 [[TMP1]], i64* [[ARGMEM]], align 8
-; ALL-NEXT:    call void @test9_aux(<{ [[STRUCT_TYPE]] }>* inalloca nonnull [[TMPCAST]])
+; ALL-NEXT:    call void @test9_aux(<{ [[STRUCT_TYPE]] }>* nonnull inalloca(<{ [[STRUCT_TYPE]] }>) [[TMPCAST]])
 ; ALL-NEXT:    ret void
 ;
 entry:
@@ -229,7 +229,7 @@ entry:
   %1 = bitcast %struct_type* %0 to i8*
   %2 = bitcast %struct_type* %a to i8*
   call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %1, i8* align 4 %2, i32 8, i1 false)
-  call void @test9_aux(<{ %struct_type }>* inalloca %argmem)
+  call void @test9_aux(<{ %struct_type }>* inalloca(<{ %struct_type }>) %argmem)
   call void @llvm.stackrestore(i8* %inalloca.save)
   ret void
 }

diff  --git a/llvm/test/Transforms/InstCombine/call-cast-target-inalloca.ll b/llvm/test/Transforms/InstCombine/call-cast-target-inalloca.ll
index 90289e2468f85..bbf2008d58544 100644
--- a/llvm/test/Transforms/InstCombine/call-cast-target-inalloca.ll
+++ b/llvm/test/Transforms/InstCombine/call-cast-target-inalloca.ll
@@ -4,12 +4,12 @@ target datalayout = "e-p:32:32"
 target triple = "i686-pc-linux-gnu"
 
 declare void @takes_i32(i32)
-declare void @takes_i32_inalloca(i32* inalloca)
+declare void @takes_i32_inalloca(i32* inalloca(i32))
 
 define void @f() {
 ; CHECK-LABEL: define void @f()
   %args = alloca inalloca i32
-  call void bitcast (void (i32)* @takes_i32 to void (i32*)*)(i32* inalloca %args)
+  call void bitcast (void (i32)* @takes_i32 to void (i32*)*)(i32* inalloca(i32) %args)
 ; CHECK: call void bitcast
   ret void
 }

diff  --git a/llvm/test/Transforms/InstCombine/stacksaverestore.ll b/llvm/test/Transforms/InstCombine/stacksaverestore.ll
index 9eb0efb1911ba..cbc353afe6190 100644
--- a/llvm/test/Transforms/InstCombine/stacksaverestore.ll
+++ b/llvm/test/Transforms/InstCombine/stacksaverestore.ll
@@ -9,7 +9,7 @@ declare void @llvm.stackrestore(i8*)
 define i32* @test1(i32 %P) {
 	%tmp = call i8* @llvm.stacksave( )
 	call void @llvm.stackrestore( i8* %tmp ) ;; not restoring anything
-	%A = alloca i32, i32 %P		
+	%A = alloca i32, i32 %P
 	ret i32* %A
 }
 
@@ -49,7 +49,7 @@ bb:		; preds = %bb, %bb.preheader
 	%tmp77 = alloca i8, i32 %size		; <i8*> [#uses=1]
 	%tmp78 = call i8* @llvm.stacksave( )		; <i8*> [#uses=1]
 	%tmp102 = alloca i8, i32 %size		; <i8*> [#uses=1]
-	call void @bar( i32 %i.0.reg2mem.0, i8* %tmp23, i8* %tmp52, i8* %tmp77, i8* %tmp102, i32 %size ) nounwind 
+	call void @bar( i32 %i.0.reg2mem.0, i8* %tmp23, i8* %tmp52, i8* %tmp77, i8* %tmp102, i32 %size ) nounwind
 	call void @llvm.stackrestore( i8* %tmp78 )
 	call void @llvm.stackrestore( i8* %tmp53 )
 	call void @llvm.stackrestore( i8* %tmp28 )
@@ -72,7 +72,7 @@ return:		; preds = %bb, %entry
 
 declare void @bar(i32, i8*, i8*, i8*, i8*, i32)
 
-declare void @inalloca_callee(i32* inalloca)
+declare void @inalloca_callee(i32* inalloca(i32))
 
 define void @test3(i32 %c) {
 entry:
@@ -83,7 +83,7 @@ loop:
   %save1 = call i8* @llvm.stacksave()
   %argmem = alloca inalloca i32
   store i32 0, i32* %argmem
-  call void @inalloca_callee(i32* inalloca %argmem)
+  call void @inalloca_callee(i32* inalloca(i32) %argmem)
 
   ; This restore cannot be deleted, the restore below does not make it dead.
   call void @llvm.stackrestore(i8* %save1)
@@ -106,7 +106,7 @@ return:
 ; CHECK: %save1 = call i8* @llvm.stacksave()
 ; CHECK: %argmem = alloca inalloca i32
 ; CHECK: store i32 0, i32* %argmem
-; CHECK: call void @inalloca_callee(i32* inalloca {{.*}} %argmem)
+; CHECK: call void @inalloca_callee(i32* {{.*}} inalloca(i32) %argmem)
 ; CHECK: call void @llvm.stackrestore(i8* %save1)
 ; CHECK: br i1 %done, label %loop, label %return
 ; CHECK: ret void

diff  --git a/llvm/test/Verifier/align.ll b/llvm/test/Verifier/align.ll
index 38ce3772e7652..1f5c8da7654a4 100644
--- a/llvm/test/Verifier/align.ll
+++ b/llvm/test/Verifier/align.ll
@@ -1,12 +1,12 @@
 ; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
 
-; CHECK: Wrong types for attribute: inalloca nest noalias nocapture nonnull readnone readonly byref(i32) byval(i32) preallocated(i32) sret(i32) align 1 dereferenceable(1) dereferenceable_or_null(1)
+; CHECK: Wrong types for attribute: nest noalias nocapture nonnull readnone readonly byref(i32) byval(i32) inalloca(i32) preallocated(i32) sret(i32) align 1 dereferenceable(1) dereferenceable_or_null(1)
 ; CHECK-NEXT: @align_non_pointer1
 define void @align_non_pointer1(i32 align 4 %a) {
   ret void
 }
 
-; CHECK: Wrong types for attribute: inalloca nest noalias nocapture noundef nonnull readnone readonly signext zeroext byref(void) byval(void) preallocated(void) sret(void) align 1 dereferenceable(1) dereferenceable_or_null(1)
+; CHECK: Wrong types for attribute: nest noalias nocapture noundef nonnull readnone readonly signext zeroext byref(void) byval(void) inalloca(void) preallocated(void) sret(void) align 1 dereferenceable(1) dereferenceable_or_null(1)
 ; CHECK-NEXT: @align_non_pointer2
 define align 4 void @align_non_pointer2(i32 %a) {
   ret void

diff  --git a/llvm/test/Verifier/amdgpu-cc.ll b/llvm/test/Verifier/amdgpu-cc.ll
index b9b4c5027a198..61f1c68cd5b3d 100644
--- a/llvm/test/Verifier/amdgpu-cc.ll
+++ b/llvm/test/Verifier/amdgpu-cc.ll
@@ -118,7 +118,7 @@ define amdgpu_kernel void @preallocated_as0_cc_amdgpu_kernel(i32* preallocated(i
 
 ; CHECK: Calling convention disallows inalloca
 ; CHECK-NEXT: void (i32*)* @inalloca_as0_cc_amdgpu_kernel
-define amdgpu_kernel void @inalloca_as0_cc_amdgpu_kernel(i32* inalloca %ptr) {
+define amdgpu_kernel void @inalloca_as0_cc_amdgpu_kernel(i32* inalloca(i32) %ptr) {
   ret void
 }
 

diff  --git a/llvm/test/Verifier/byref.ll b/llvm/test/Verifier/byref.ll
index 2f22ee37292e7..d5921bf5b2614 100644
--- a/llvm/test/Verifier/byref.ll
+++ b/llvm/test/Verifier/byref.ll
@@ -28,7 +28,7 @@ define void @byref_byval(i32* byref(i32) byval(i32)) {
 
 ; CHECK: Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', 'byref', and 'sret' are incompatible!
 ; CHECK-NEXT: void (i32*)* @byref_inalloca
-define void @byref_inalloca(i32* byref(i32) inalloca) {
+define void @byref_inalloca(i32* byref(i32) inalloca(i32)) {
   ret void
 }
 
@@ -56,7 +56,7 @@ define void @byref_nest(i32* byref(i32) nest) {
   ret void
 }
 
-; CHECK: Wrong types for attribute: inalloca nest noalias nocapture nonnull readnone readonly byref(i32) byval(i32) preallocated(i32) sret(i32) align 1 dereferenceable(1) dereferenceable_or_null(1)
+; CHECK: Wrong types for attribute: nest noalias nocapture nonnull readnone readonly byref(i32) byval(i32) inalloca(i32) preallocated(i32) sret(i32) align 1 dereferenceable(1) dereferenceable_or_null(1)
 ; CHECK-NEXT: void (i32)* @byref_non_pointer
 define void @byref_non_pointer(i32 byref(i32)) {
   ret void

diff  --git a/llvm/test/Verifier/byval-1.ll b/llvm/test/Verifier/byval-1.ll
index e2b4519b17cb9..6344371bba5e0 100644
--- a/llvm/test/Verifier/byval-1.ll
+++ b/llvm/test/Verifier/byval-1.ll
@@ -1,5 +1,5 @@
 ; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
 
-; CHECK: Wrong types for attribute: inalloca nest noalias nocapture nonnull readnone readonly byref(i32) byval(i32) preallocated(i32) sret(i32) align 1 dereferenceable(1) dereferenceable_or_null(1)
+; CHECK: Wrong types for attribute: nest noalias nocapture nonnull readnone readonly byref(i32) byval(i32) inalloca(i32) preallocated(i32) sret(i32) align 1 dereferenceable(1) dereferenceable_or_null(1)
 ; CHECK-NEXT: void (i32)* @h
 declare void @h(i32 byval(i32) %num)

diff  --git a/llvm/test/Verifier/inalloca-vararg.ll b/llvm/test/Verifier/inalloca-vararg.ll
index 428f89ec88f10..de7622b638d88 100644
--- a/llvm/test/Verifier/inalloca-vararg.ll
+++ b/llvm/test/Verifier/inalloca-vararg.ll
@@ -3,7 +3,7 @@
 declare void @h(i32, ...)
 define void @i() {
   %args = alloca inalloca i32
-  call void (i32, ...) @h(i32 1, i32* inalloca %args, i32 3)
+  call void (i32, ...) @h(i32 1, i32* inalloca(i32) %args, i32 3)
 ; CHECK: inalloca isn't on the last argument!
   ret void
 }

diff  --git a/llvm/test/Verifier/inalloca1.ll b/llvm/test/Verifier/inalloca1.ll
index 7ee2cba5ac174..76da66adc7983 100644
--- a/llvm/test/Verifier/inalloca1.ll
+++ b/llvm/test/Verifier/inalloca1.ll
@@ -1,22 +1,34 @@
 ; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
 
-declare void @a(i64* byval(i64) inalloca %p)
+declare void @a(i64* byval(i64) inalloca(i64) %p)
 ; CHECK: Attributes {{.*}} are incompatible
 
-declare void @b(i64* inreg inalloca %p)
+declare void @b(i64* inreg inalloca(i64) %p)
 ; CHECK: Attributes {{.*}} are incompatible
 
-declare void @c(i64* sret(i64) inalloca %p)
+declare void @c(i64* sret(i64) inalloca(i64) %p)
 ; CHECK: Attributes {{.*}} are incompatible
 
-declare void @d(i64* nest inalloca %p)
+declare void @d(i64* nest inalloca(i64) %p)
 ; CHECK: Attributes {{.*}} are incompatible
 
-declare void @e(i64* readonly inalloca %p)
+declare void @e(i64* readonly inalloca(i64) %p)
 ; CHECK: Attributes {{.*}} are incompatible
 
-declare void @f(void ()* inalloca %p)
+declare void @f(void ()* inalloca(void()) %p)
 ; CHECK: do not support unsized types
 
-declare void @g(i32* inalloca %p, i32 %p2)
+declare void @g(i32* inalloca(i32) %p, i32 %p2)
 ; CHECK: inalloca isn't on the last parameter!
+
+; CHECK: Attribute 'inalloca' type does not match parameter!
+; CHECK-NEXT: void (i32*)* @inalloca_mismatched_pointee_type0
+define void @inalloca_mismatched_pointee_type0(i32* inalloca(i8)) {
+  ret void
+}
+
+; CHECK: Wrong types for attribute:
+; CHECK-NEXT: void (i8)* @inalloca_not_pointer
+define void @inalloca_not_pointer(i8 byref(i8)) {
+  ret void
+}

diff  --git a/llvm/test/Verifier/inalloca2.ll b/llvm/test/Verifier/inalloca2.ll
index 12a4549992857..21fc2517cd0a7 100644
--- a/llvm/test/Verifier/inalloca2.ll
+++ b/llvm/test/Verifier/inalloca2.ll
@@ -2,21 +2,21 @@
 ; doesn't reject it.
 ; RUN: llvm-as %s -o /dev/null
 
-declare void @doit(i64* inalloca %a)
+declare void @doit(i64* inalloca(i64) %a)
 
 define void @a() {
 entry:
   %a = alloca inalloca [2 x i32]
   %b = bitcast [2 x i32]* %a to i64*
-  call void @doit(i64* inalloca %b)
+  call void @doit(i64* inalloca(i64) %b)
   ret void
 }
 
 define void @b() {
 entry:
   %a = alloca inalloca i64
-  call void @doit(i64* inalloca %a)
-  call void @doit(i64* inalloca %a)
+  call void @doit(i64* inalloca(i64) %a)
+  call void @doit(i64* inalloca(i64) %a)
   ret void
 }
 
@@ -34,6 +34,6 @@ else:
 
 call:
   %args = phi i64* [ %a, %if ], [ %b, %else ]
-  call void @doit(i64* inalloca %args)
+  call void @doit(i64* inalloca(i64) %args)
   ret void
 }

diff  --git a/llvm/test/Verifier/inalloca3.ll b/llvm/test/Verifier/inalloca3.ll
index c09ce100849b5..28cdbfef97857 100644
--- a/llvm/test/Verifier/inalloca3.ll
+++ b/llvm/test/Verifier/inalloca3.ll
@@ -1,13 +1,13 @@
 ; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
 
 
-declare void @doit(i64* inalloca %a)
+declare void @doit(i64* inalloca(i64) %a)
 
 define void @a() {
 entry:
   %a = alloca [2 x i32]
   %b = bitcast [2 x i32]* %a to i64*
-  call void @doit(i64* inalloca %b)
+  call void @doit(i64* inalloca(i64) %b)
 ; CHECK: inalloca argument for call has mismatched alloca
   ret void
 }

diff  --git a/llvm/test/Verifier/noundef.ll b/llvm/test/Verifier/noundef.ll
index 7b199cd6d2dee..2ece2dd1a9ac1 100644
--- a/llvm/test/Verifier/noundef.ll
+++ b/llvm/test/Verifier/noundef.ll
@@ -1,6 +1,6 @@
 ; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
 
-; CHECK: Wrong types for attribute: inalloca nest noalias nocapture noundef nonnull readnone readonly signext zeroext byref(void) byval(void) preallocated(void) sret(void) align 1 dereferenceable(1) dereferenceable_or_null(1)
+; CHECK: Wrong types for attribute: nest noalias nocapture noundef nonnull readnone readonly signext zeroext byref(void) byval(void) inalloca(void) preallocated(void) sret(void) align 1 dereferenceable(1) dereferenceable_or_null(1)
 ; CHECK-NEXT: @noundef_void
 define noundef void @noundef_void() {
   ret void

diff  --git a/llvm/unittests/IR/AttributesTest.cpp b/llvm/unittests/IR/AttributesTest.cpp
index 2c191264a892e..11b1598979896 100644
--- a/llvm/unittests/IR/AttributesTest.cpp
+++ b/llvm/unittests/IR/AttributesTest.cpp
@@ -180,9 +180,6 @@ TEST(Attributes, StringRepresentation) {
   Attribute A = Attribute::getWithByValType(C, Ty);
   EXPECT_EQ(A.getAsString(), "byval(%mystruct)");
 
-  A = Attribute::getWithByValType(C, nullptr);
-  EXPECT_EQ(A.getAsString(), "byval");
-
   A = Attribute::getWithByValType(C, Type::getInt32Ty(C));
   EXPECT_EQ(A.getAsString(), "byval(i32)");
 }

diff  --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp
index 6bab80215c0b1..34802b63aae84 100644
--- a/llvm/unittests/Transforms/Utils/CloningTest.cpp
+++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp
@@ -718,10 +718,10 @@ TEST(CloneFunction, CloneEmptyFunction) {
 
 TEST(CloneFunction, CloneFunctionWithInalloca) {
   StringRef ImplAssembly = R"(
-    declare void @a(i32* inalloca)
+    declare void @a(i32* inalloca(i32))
     define void @foo() {
       %a = alloca inalloca i32
-      call void @a(i32* inalloca %a)
+      call void @a(i32* inalloca(i32) %a)
       ret void
     }
     declare void @bar()


        


More information about the cfe-commits mailing list