[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 8) (PR #169687)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Nov 26 09:13:14 PST 2025
https://github.com/Sirraide created https://github.com/llvm/llvm-project/pull/169687
None
>From c93a2795129214893e8e32164e74d25019b80774 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 26 Nov 2025 17:15:21 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 8)
---
clang/lib/CodeGen/CGStmt.cpp | 46 +
clang/lib/CodeGen/CodeGenFunction.h | 3 +
.../cxx2c-destructuring-expansion-stmt.cpp | 471 +++++
...cxx2c-enumerating-expansion-statements.cpp | 1518 +++++++++++++++++
.../cxx2c-expansion-stmts-control-flow.cpp | 429 +++++
.../cxx2c-expansion-stmts-templates.cpp | 208 +++
.../cxx2c-iterating-expansion-stmt.cpp | 474 +++++
7 files changed, 3149 insertions(+)
create mode 100644 clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp
create mode 100644 clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp
create mode 100644 clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp
create mode 100644 clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp
create mode 100644 clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 36be3295950b8..d6c6d159a5438 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -204,6 +204,14 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
case Stmt::CXXForRangeStmtClass:
EmitCXXForRangeStmt(cast<CXXForRangeStmt>(*S), Attrs);
break;
+ case Stmt::CXXEnumeratingExpansionStmtPatternClass:
+ case Stmt::CXXIteratingExpansionStmtPatternClass:
+ case Stmt::CXXDestructuringExpansionStmtPatternClass:
+ case Stmt::CXXDependentExpansionStmtPatternClass:
+ llvm_unreachable("unexpanded expansion statements should not be emitted");
+ case Stmt::CXXExpansionStmtInstantiationClass:
+ EmitCXXExpansionStmtInstantiation(cast<CXXExpansionStmtInstantiation>(*S));
+ break;
case Stmt::SEHTryStmtClass:
EmitSEHTryStmt(cast<SEHTryStmt>(*S));
break;
@@ -1556,6 +1564,44 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S,
}
}
+void CodeGenFunction::EmitCXXExpansionStmtInstantiation(
+ const CXXExpansionStmtInstantiation &S) {
+ // FIXME: For reasons beyond my understanding, two scopes are required to emit
+ // the destructors of lifetime-extended temporaries in the right place, but
+ // only in some templates. There are some other issues with lifetime-extended
+ // temporaries currently (https://github.com/llvm/llvm-project/issues/165182);
+ // perhaps resolving those will allow us to remove the second scope here
+ // because there really ought to be a better way of doing this.
+ LexicalScope Scope(*this, S.getSourceRange());
+ LexicalScope Scope2(*this, S.getSourceRange());
+
+ for (const Stmt *DS : S.getSharedStmts())
+ EmitStmt(DS);
+
+ if (S.getInstantiations().empty() || !HaveInsertPoint())
+ return;
+
+ JumpDest ExpandExit = getJumpDestInCurrentScope("expand.end");
+ JumpDest ContinueDest;
+ for (auto [N, Inst] : enumerate(S.getInstantiations())) {
+ if (!HaveInsertPoint()) {
+ EmitBlock(ExpandExit.getBlock(), true);
+ return;
+ }
+
+ if (N == S.getInstantiations().size() - 1)
+ ContinueDest = ExpandExit;
+ else
+ ContinueDest = getJumpDestInCurrentScope("expand.next");
+
+ LexicalScope ExpansionScope(*this, S.getSourceRange());
+ BreakContinueStack.push_back(BreakContinue(S, ExpandExit, ContinueDest));
+ EmitStmt(Inst);
+ BreakContinueStack.pop_back();
+ EmitBlock(ContinueDest.getBlock(), true);
+ }
+}
+
void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
if (RV.isScalar()) {
Builder.CreateStore(RV.getScalarVal(), ReturnValue);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 8c4c1c8c2dc95..a895f187f3946 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3690,6 +3690,9 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = {});
+ void
+ EmitCXXExpansionStmtInstantiation(const CXXExpansionStmtInstantiation &S);
+
/// Controls insertion of cancellation exit blocks in worksharing constructs.
class OMPCancelStackRAII {
CodeGenFunction &CGF;
diff --git a/clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp b/clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp
new file mode 100644
index 0000000000000..16d8c370a9d3f
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp
@@ -0,0 +1,471 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+struct A {};
+struct B { int x = 1; };
+struct C { int a = 1, b = 2, c = 3; };
+
+void g(int);
+
+int references_destructuring() {
+ C c;
+ template for (auto& x : c) { ++x; }
+ template for (auto&& x : c) { ++x; }
+ return c.a + c.b + c.c;
+}
+
+template <auto v>
+int destructure() {
+ int sum = 0;
+ template for (auto x : v) sum += x;
+ template for (constexpr auto x : v) sum += x;
+ return sum;
+}
+
+void f() {
+ destructure<B{10}>();
+ destructure<C{}>();
+ destructure<C{3, 4, 5}>();
+}
+
+void empty() {
+ static constexpr A a;
+ template for (auto x : A()) g(x);
+ template for (auto& x : a) g(x);
+ template for (auto&& x : A()) g(x);
+ template for (constexpr auto x : a) g(x);
+}
+
+namespace apply_lifetime_extension {
+struct T {
+ int& x;
+ T(int& x) noexcept : x(x) {}
+ ~T() noexcept { x = 42; }
+};
+
+const T& f(const T& t) noexcept { return t; }
+T g(int& x) noexcept { return T(x); }
+
+// CWG 3043:
+//
+// Lifetime extension only applies to destructuring expansion statements
+// (enumerating statements don't have a range variable, and the range variable
+// of iterating statements is constexpr).
+int lifetime_extension() {
+ int x = 5;
+ int sum = 0;
+ template for (auto e : f(g(x))) {
+ sum += x;
+ }
+ return sum + x;
+}
+
+template <typename T>
+int lifetime_extension_instantiate_expansions() {
+ int x = 5;
+ int sum = 0;
+ template for (T e : f(g(x))) {
+ sum += x;
+ }
+ return sum + x;
+}
+
+template <typename T>
+int lifetime_extension_dependent_expansion_stmt() {
+ int x = 5;
+ int sum = 0;
+ template for (int e : f(g((T&)x))) {
+ sum += x;
+ }
+ return sum + x;
+}
+
+template <typename U>
+struct foo {
+ template <typename T>
+ int lifetime_extension_multiple_instantiations() {
+ int x = 5;
+ int sum = 0;
+ template for (T e : f(g((U&)x))) {
+ sum += x;
+ }
+ return sum + x;
+ }
+};
+
+void instantiate() {
+ lifetime_extension_instantiate_expansions<int>();
+ lifetime_extension_dependent_expansion_stmt<int>();
+ foo<int>().lifetime_extension_multiple_instantiations<int>();
+}
+}
+
+// CHECK: @_ZZ5emptyvE1a = internal constant %struct.A zeroinitializer, align 1
+// CHECK: @_ZTAXtl1BLi10EEE = {{.*}} constant %struct.B { i32 10 }, comdat
+// CHECK: @_ZTAXtl1CLi1ELi2ELi3EEE = {{.*}} constant %struct.C { i32 1, i32 2, i32 3 }, comdat
+// CHECK: @_ZTAXtl1CLi3ELi4ELi5EEE = {{.*}} constant %struct.C { i32 3, i32 4, i32 5 }, comdat
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z24references_destructuringv()
+// CHECK: entry:
+// CHECK-NEXT: %c = alloca %struct.C, align 4
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca ptr, align 8
+// CHECK-NEXT: %x1 = alloca ptr, align 8
+// CHECK-NEXT: %x4 = alloca ptr, align 8
+// CHECK-NEXT: %1 = alloca ptr, align 8
+// CHECK-NEXT: %x7 = alloca ptr, align 8
+// CHECK-NEXT: %x11 = alloca ptr, align 8
+// CHECK-NEXT: %x15 = alloca ptr, align 8
+// CHECK-NEXT: call void @_ZN1CC1Ev(ptr {{.*}} %c)
+// CHECK-NEXT: store ptr %c, ptr %0, align 8
+// CHECK-NEXT: %2 = load ptr, ptr %0, align 8
+// CHECK-NEXT: %a = getelementptr inbounds nuw %struct.C, ptr %2, i32 0, i32 0
+// CHECK-NEXT: store ptr %a, ptr %x, align 8
+// CHECK-NEXT: %3 = load ptr, ptr %x, align 8
+// CHECK-NEXT: %4 = load i32, ptr %3, align 4
+// CHECK-NEXT: %inc = add nsw i32 %4, 1
+// CHECK-NEXT: store i32 %inc, ptr %3, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: %5 = load ptr, ptr %0, align 8
+// CHECK-NEXT: %b = getelementptr inbounds nuw %struct.C, ptr %5, i32 0, i32 1
+// CHECK-NEXT: store ptr %b, ptr %x1, align 8
+// CHECK-NEXT: %6 = load ptr, ptr %x1, align 8
+// CHECK-NEXT: %7 = load i32, ptr %6, align 4
+// CHECK-NEXT: %inc2 = add nsw i32 %7, 1
+// CHECK-NEXT: store i32 %inc2, ptr %6, align 4
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: %8 = load ptr, ptr %0, align 8
+// CHECK-NEXT: %c5 = getelementptr inbounds nuw %struct.C, ptr %8, i32 0, i32 2
+// CHECK-NEXT: store ptr %c5, ptr %x4, align 8
+// CHECK-NEXT: %9 = load ptr, ptr %x4, align 8
+// CHECK-NEXT: %10 = load i32, ptr %9, align 4
+// CHECK-NEXT: %inc6 = add nsw i32 %10, 1
+// CHECK-NEXT: store i32 %inc6, ptr %9, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store ptr %c, ptr %1, align 8
+// CHECK-NEXT: %11 = load ptr, ptr %1, align 8
+// CHECK-NEXT: %a8 = getelementptr inbounds nuw %struct.C, ptr %11, i32 0, i32 0
+// CHECK-NEXT: store ptr %a8, ptr %x7, align 8
+// CHECK-NEXT: %12 = load ptr, ptr %x7, align 8
+// CHECK-NEXT: %13 = load i32, ptr %12, align 4
+// CHECK-NEXT: %inc9 = add nsw i32 %13, 1
+// CHECK-NEXT: store i32 %inc9, ptr %12, align 4
+// CHECK-NEXT: br label %expand.next10
+// CHECK: expand.next10:
+// CHECK-NEXT: %14 = load ptr, ptr %1, align 8
+// CHECK-NEXT: %b12 = getelementptr inbounds nuw %struct.C, ptr %14, i32 0, i32 1
+// CHECK-NEXT: store ptr %b12, ptr %x11, align 8
+// CHECK-NEXT: %15 = load ptr, ptr %x11, align 8
+// CHECK-NEXT: %16 = load i32, ptr %15, align 4
+// CHECK-NEXT: %inc13 = add nsw i32 %16, 1
+// CHECK-NEXT: store i32 %inc13, ptr %15, align 4
+// CHECK-NEXT: br label %expand.next14
+// CHECK: expand.next14:
+// CHECK-NEXT: %17 = load ptr, ptr %1, align 8
+// CHECK-NEXT: %c16 = getelementptr inbounds nuw %struct.C, ptr %17, i32 0, i32 2
+// CHECK-NEXT: store ptr %c16, ptr %x15, align 8
+// CHECK-NEXT: %18 = load ptr, ptr %x15, align 8
+// CHECK-NEXT: %19 = load i32, ptr %18, align 4
+// CHECK-NEXT: %inc17 = add nsw i32 %19, 1
+// CHECK-NEXT: store i32 %inc17, ptr %18, align 4
+// CHECK-NEXT: br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT: %a19 = getelementptr inbounds nuw %struct.C, ptr %c, i32 0, i32 0
+// CHECK-NEXT: %20 = load i32, ptr %a19, align 4
+// CHECK-NEXT: %b20 = getelementptr inbounds nuw %struct.C, ptr %c, i32 0, i32 1
+// CHECK-NEXT: %21 = load i32, ptr %b20, align 4
+// CHECK-NEXT: %add = add nsw i32 %20, %21
+// CHECK-NEXT: %c21 = getelementptr inbounds nuw %struct.C, ptr %c, i32 0, i32 2
+// CHECK-NEXT: %22 = load i32, ptr %c21, align 4
+// CHECK-NEXT: %add22 = add nsw i32 %add, %22
+// CHECK-NEXT: ret i32 %add22
+
+
+// CHECK-LABEL: define {{.*}} void @_Z1fv()
+// CHECK: entry:
+// CHECK-NEXT: %call = call {{.*}} i32 @_Z11destructureITnDaXtl1BLi10EEEEiv()
+// CHECK-NEXT: %call1 = call {{.*}} i32 @_Z11destructureITnDaXtl1CLi1ELi2ELi3EEEEiv()
+// CHECK-NEXT: %call2 = call {{.*}} i32 @_Z11destructureITnDaXtl1CLi3ELi4ELi5EEEEiv()
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z11destructureITnDaXtl1BLi10EEEEiv()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %1 = alloca ptr, align 8
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZTAXtl1BLi10EEE, ptr %0, align 8
+// CHECK-NEXT: store i32 10, ptr %x, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x, align 4
+// CHECK-NEXT: %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %3, %2
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store ptr @_ZTAXtl1BLi10EEE, ptr %1, align 8
+// CHECK-NEXT: store i32 10, ptr %x1, align 4
+// CHECK-NEXT: %4 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %4, 10
+// CHECK-NEXT: store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end3
+// CHECK: expand.end3:
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %5
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z11destructureITnDaXtl1CLi1ELi2ELi3EEEEiv()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: %1 = alloca ptr, align 8
+// CHECK-NEXT: %x6 = alloca i32, align 4
+// CHECK-NEXT: %x9 = alloca i32, align 4
+// CHECK-NEXT: %x12 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZTAXtl1CLi1ELi2ELi3EEE, ptr %0, align 8
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x, align 4
+// CHECK-NEXT: %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %3, %2
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 2, ptr %x1, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x1, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store i32 3, ptr %x4, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x4, align 4
+// CHECK-NEXT: %7 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add5 = add nsw i32 %7, %6
+// CHECK-NEXT: store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store ptr @_ZTAXtl1CLi1ELi2ELi3EEE, ptr %1, align 8
+// CHECK-NEXT: store i32 1, ptr %x6, align 4
+// CHECK-NEXT: %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add7 = add nsw i32 %8, 1
+// CHECK-NEXT: store i32 %add7, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: store i32 2, ptr %x9, align 4
+// CHECK-NEXT: %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add10 = add nsw i32 %9, 2
+// CHECK-NEXT: store i32 %add10, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: store i32 3, ptr %x12, align 4
+// CHECK-NEXT: %10 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add13 = add nsw i32 %10, 3
+// CHECK-NEXT: store i32 %add13, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT: %11 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %11
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z11destructureITnDaXtl1CLi3ELi4ELi5EEEEiv()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: %1 = alloca ptr, align 8
+// CHECK-NEXT: %x6 = alloca i32, align 4
+// CHECK-NEXT: %x9 = alloca i32, align 4
+// CHECK-NEXT: %x12 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZTAXtl1CLi3ELi4ELi5EEE, ptr %0, align 8
+// CHECK-NEXT: store i32 3, ptr %x, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x, align 4
+// CHECK-NEXT: %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %3, %2
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 4, ptr %x1, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x1, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store i32 5, ptr %x4, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x4, align 4
+// CHECK-NEXT: %7 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add5 = add nsw i32 %7, %6
+// CHECK-NEXT: store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store ptr @_ZTAXtl1CLi3ELi4ELi5EEE, ptr %1, align 8
+// CHECK-NEXT: store i32 3, ptr %x6, align 4
+// CHECK-NEXT: %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add7 = add nsw i32 %8, 3
+// CHECK-NEXT: store i32 %add7, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: store i32 4, ptr %x9, align 4
+// CHECK-NEXT: %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add10 = add nsw i32 %9, 4
+// CHECK-NEXT: store i32 %add10, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: store i32 5, ptr %x12, align 4
+// CHECK-NEXT: %10 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add13 = add nsw i32 %10, 5
+// CHECK-NEXT: store i32 %add13, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT: %11 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %11
+
+
+// CHECK-LABEL: define {{.*}} void @_Z5emptyv()
+// CHECK: entry:
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK-NEXT: %ref.tmp = alloca %struct.A, align 1
+// CHECK-NEXT: %1 = alloca ptr, align 8
+// CHECK-NEXT: %2 = alloca ptr, align 8
+// CHECK-NEXT: %ref.tmp1 = alloca %struct.A, align 1
+// CHECK-NEXT: %3 = alloca ptr, align 8
+// CHECK-NEXT: store ptr %ref.tmp, ptr %0, align 8
+// CHECK-NEXT: store ptr @_ZZ5emptyvE1a, ptr %1, align 8
+// CHECK-NEXT: store ptr %ref.tmp1, ptr %2, align 8
+// CHECK-NEXT: store ptr @_ZZ5emptyvE1a, ptr %3, align 8
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN24apply_lifetime_extension18lifetime_extensionEv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK: %ref.tmp = alloca %"struct.apply_lifetime_extension::T", align 8
+// CHECK-NEXT: %e = alloca i32, align 4
+// CHECK-NEXT: store i32 5, ptr %x, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK: call void @_ZN24apply_lifetime_extension1gERi(ptr dead_on_unwind writable sret(%"struct.apply_lifetime_extension::T") align 8 %ref.tmp, ptr {{.*}} %x)
+// CHECK-NEXT: %call = call {{.*}} ptr @_ZN24apply_lifetime_extension1fERKNS_1TE(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: store ptr %call, ptr %0, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %0, align 8
+// CHECK: %x1 = getelementptr inbounds nuw %"struct.apply_lifetime_extension::T", ptr %1, i32 0, i32 0
+// CHECK-NEXT: %2 = load ptr, ptr %x1, align 8
+// CHECK-NEXT: %3 = load i32, ptr %2, align 4
+// CHECK-NEXT: store i32 %3, ptr %e, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: call void @_ZN24apply_lifetime_extension1TD1Ev(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: %6 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %7 = load i32, ptr %x, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %6, %7
+// CHECK-NEXT: ret i32 %add2
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN24apply_lifetime_extension41lifetime_extension_instantiate_expansionsIiEEiv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK: %ref.tmp = alloca %"struct.apply_lifetime_extension::T", align 8
+// CHECK-NEXT: %e = alloca i32, align 4
+// CHECK-NEXT: store i32 5, ptr %x, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK: call void @_ZN24apply_lifetime_extension1gERi(ptr dead_on_unwind writable sret(%"struct.apply_lifetime_extension::T") align 8 %ref.tmp, ptr {{.*}} %x)
+// CHECK-NEXT: %call = call {{.*}} ptr @_ZN24apply_lifetime_extension1fERKNS_1TE(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: store ptr %call, ptr %0, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %0, align 8
+// CHECK: %x1 = getelementptr inbounds nuw %"struct.apply_lifetime_extension::T", ptr %1, i32 0, i32 0
+// CHECK-NEXT: %2 = load ptr, ptr %x1, align 8
+// CHECK-NEXT: %3 = load i32, ptr %2, align 4
+// CHECK-NEXT: store i32 %3, ptr %e, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: call void @_ZN24apply_lifetime_extension1TD1Ev(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: %6 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %7 = load i32, ptr %x, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %6, %7
+// CHECK-NEXT: ret i32 %add2
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN24apply_lifetime_extension43lifetime_extension_dependent_expansion_stmtIiEEiv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK: %ref.tmp = alloca %"struct.apply_lifetime_extension::T", align 8
+// CHECK-NEXT: %e = alloca i32, align 4
+// CHECK-NEXT: store i32 5, ptr %x, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK: call void @_ZN24apply_lifetime_extension1gERi(ptr dead_on_unwind writable sret(%"struct.apply_lifetime_extension::T") align 8 %ref.tmp, ptr {{.*}} %x)
+// CHECK-NEXT: %call = call {{.*}} ptr @_ZN24apply_lifetime_extension1fERKNS_1TE(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: store ptr %call, ptr %0, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %0, align 8
+// CHECK: %x1 = getelementptr inbounds nuw %"struct.apply_lifetime_extension::T", ptr %1, i32 0, i32 0
+// CHECK-NEXT: %2 = load ptr, ptr %x1, align 8
+// CHECK-NEXT: %3 = load i32, ptr %2, align 4
+// CHECK-NEXT: store i32 %3, ptr %e, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: call void @_ZN24apply_lifetime_extension1TD1Ev(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: %6 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %7 = load i32, ptr %x, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %6, %7
+// CHECK-NEXT: ret i32 %add2
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN24apply_lifetime_extension3fooIiE42lifetime_extension_multiple_instantiationsIiEEiv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK: %ref.tmp = alloca %"struct.apply_lifetime_extension::T", align 8
+// CHECK-NEXT: %e = alloca i32, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i32 5, ptr %x, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK: call void @_ZN24apply_lifetime_extension1gERi(ptr dead_on_unwind writable sret(%"struct.apply_lifetime_extension::T") align 8 %ref.tmp, ptr {{.*}} %x)
+// CHECK-NEXT: %call = call {{.*}} ptr @_ZN24apply_lifetime_extension1fERKNS_1TE(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: store ptr %call, ptr %0, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %0, align 8
+// CHECK: %x2 = getelementptr inbounds nuw %"struct.apply_lifetime_extension::T", ptr %1, i32 0, i32 0
+// CHECK-NEXT: %2 = load ptr, ptr %x2, align 8
+// CHECK-NEXT: %3 = load i32, ptr %2, align 4
+// CHECK-NEXT: store i32 %3, ptr %e, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: call void @_ZN24apply_lifetime_extension1TD1Ev(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: %6 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %7 = load i32, ptr %x, align 4
+// CHECK-NEXT: %add3 = add nsw i32 %6, %7
+// CHECK-NEXT: ret i32 %add3
diff --git a/clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp b/clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp
new file mode 100644
index 0000000000000..c82b345de206b
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp
@@ -0,0 +1,1518 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+struct S {
+ int x;
+ constexpr S(int x) : x{x} {}
+};
+
+void g(int);
+void g(long);
+void g(const char*);
+void g(S);
+
+template <int n> constexpr int tg() { return n; }
+
+void h(int, int);
+
+void f1() {
+ template for (auto x : {1, 2, 3}) g(x);
+}
+
+void f2() {
+ template for (auto x : {1, "123", S(45)}) g(x);
+}
+
+void f3() {
+ template for (auto x : {}) g(x);
+}
+
+void f4() {
+ template for (auto x : {1, 2})
+ template for (auto y : {3, 4})
+ h(x, y);
+}
+
+void f5() {
+ template for (auto x : {}) static_assert(false, "discarded");
+ template for (constexpr auto x : {}) static_assert(false, "discarded");
+ template for (auto x : {1}) g(x);
+ template for (auto x : {2, 3, 4}) g(x);
+ template for (constexpr auto x : {5}) g(x);
+ template for (constexpr auto x : {6, 7, 8}) g(x);
+ template for (constexpr auto x : {9}) tg<x>();
+ template for (constexpr auto x : {10, 11, 12})
+ static_assert(tg<x>());
+
+ template for (int x : {13, 14, 15}) g(x);
+ template for (S x : {16, 17, 18}) g(x.x);
+ template for (constexpr S x : {19, 20, 21}) tg<x.x>();
+}
+
+template <typename T>
+void t1() {
+ template for (T x : {}) g(x);
+ template for (constexpr T x : {}) g(x);
+ template for (auto x : {}) g(x);
+ template for (constexpr auto x : {}) g(x);
+ template for (T x : {1, 2}) g(x);
+ template for (T x : {T(3), T(4)}) g(x);
+ template for (auto x : {T(5), T(6)}) g(x);
+ template for (constexpr T x : {T(7), T(8)}) static_assert(tg<x>());
+ template for (constexpr auto x : {T(9), T(10)}) static_assert(tg<x>());
+}
+
+template <typename U>
+struct s1 {
+ template <typename T>
+ void tf() {
+ template for (T x : {}) g(x);
+ template for (constexpr T x : {}) g(x);
+ template for (U x : {}) g(x);
+ template for (constexpr U x : {}) g(x);
+ template for (auto x : {}) g(x);
+ template for (constexpr auto x : {}) g(x);
+ template for (T x : {1, 2}) g(x);
+ template for (U x : {3, 4}) g(x);
+ template for (U x : {T(5), T(6)}) g(x);
+ template for (T x : {U(7), U(8)}) g(x);
+ template for (auto x : {T(9), T(10)}) g(x);
+ template for (auto x : {U(11), T(12)}) g(x);
+ template for (constexpr U x : {T(13), T(14)}) static_assert(tg<x>());
+ template for (constexpr T x : {U(15), U(16)}) static_assert(tg<x>());
+ template for (constexpr auto x : {T(17), U(18)}) static_assert(tg<x>());
+ }
+};
+
+template <typename T>
+void t2() {
+ template for (T x : {}) g(x);
+}
+
+void f6() {
+ t1<int>();
+ t1<long>();
+ s1<long>().tf<long>();
+ s1<int>().tf<int>();
+ s1<int>().tf<long>();
+ s1<long>().tf<int>();
+ t2<S>();
+ t2<S[1231]>();
+ t2<S***>();
+}
+
+struct X {
+ int a, b, c;
+};
+
+template <typename ...Ts>
+void t3(Ts... ts) {
+ template for (auto x : {ts...}) g(x);
+ template for (auto x : {1, ts..., 2, ts..., 3}) g(x);
+ template for (auto x : {4, ts..., ts..., 5}) g(x);
+ template for (X x : {{ts...}, {ts...}, {6, 7, 8}}) g(x.a);
+ template for (X x : {X{ts...}}) g(x.a);
+}
+
+template <int ...is>
+void t4() {
+ template for (constexpr auto x : {is...}) {
+ g(x);
+ tg<x>();
+ }
+
+ template for (constexpr auto x : {1, is..., 2, is..., 3}) {
+ g(x);
+ tg<x>();
+ }
+
+ template for (constexpr auto x : {4, is..., is..., 5}) {
+ g(x);
+ tg<x>();
+ }
+
+ template for (constexpr X x : {{is...}, {is...}, {6, 7, 8}}) {
+ g(x.a);
+ tg<x.a>();
+ }
+
+ template for (constexpr X x : {X{is...}}) {
+ g(x.a);
+ tg<x.a>();
+ }
+}
+
+template <int ...is>
+struct s2 {
+ template <int ...js>
+ void tf() {
+ template for (auto x : {is..., js...}) g(x);
+ template for (X x : {{is...}, {js...}}) g(x.a);
+ template for (constexpr auto x : {is..., js...}) tg<x>();
+ template for (constexpr X x : {{is...}, {js...}}) tg<x.a>();
+ }
+};
+
+void f7() {
+ t3(42, 43, 44);
+ t4<42, 43, 44>();
+ s2<1, 2, 3>().tf<4, 5, 6>();
+}
+
+template <int ...is>
+void t5() {
+ ([] {
+ template for (constexpr auto x : {is}) {
+ g(x);
+ tg<x>();
+ }
+ }(), ...);
+}
+
+void f8() {
+ t5<1, 2, 3>();
+}
+
+int references_enumerating() {
+ int x = 1, y = 2, z = 3;
+ template for (auto& v : {x, y, z}) { ++v; }
+ template for (auto&& v : {x, y, z}) { ++v; }
+ return x + y + z;
+}
+
+// CHECK-LABEL: define {{.*}} void @_Z2f1v()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x3 = alloca i32, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 2, ptr %x1, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x1, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.next2
+// CHECK: expand.next2:
+// CHECK-NEXT: store i32 3, ptr %x3, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x3, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f2v()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca ptr, align 8
+// CHECK-NEXT: %x3 = alloca %struct.S, align 4
+// CHECK-NEXT: %agg.tmp = alloca %struct.S, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store ptr @.str, ptr %x1, align 8
+// CHECK-NEXT: %1 = load ptr, ptr %x1, align 8
+// CHECK-NEXT: call void @_Z1gPKc(ptr {{.*}} %1)
+// CHECK-NEXT: br label %expand.next2
+// CHECK: expand.next2:
+// CHECK-NEXT: call void @_ZN1SC1Ei(ptr {{.*}} %x3, i32 {{.*}} 45)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %x3, i64 4, i1 false)
+// CHECK-NEXT: %coerce.dive = getelementptr inbounds nuw %struct.S, ptr %agg.tmp, i32 0, i32 0
+// CHECK-NEXT: %2 = load i32, ptr %coerce.dive, align 4
+// CHECK-NEXT: call void @_Z1g1S(i32 %2)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f3v()
+// CHECK: entry:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f4v()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %y = alloca i32, align 4
+// CHECK-NEXT: %y1 = alloca i32, align 4
+// CHECK-NEXT: %x3 = alloca i32, align 4
+// CHECK-NEXT: %y4 = alloca i32, align 4
+// CHECK-NEXT: %y6 = alloca i32, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: store i32 3, ptr %y, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: %1 = load i32, ptr %y, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} %0, i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 4, ptr %y1, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x, align 4
+// CHECK-NEXT: %3 = load i32, ptr %y1, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} %2, i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: br label %expand.next2
+// CHECK: expand.next2:
+// CHECK-NEXT: store i32 2, ptr %x3, align 4
+// CHECK-NEXT: store i32 3, ptr %y4, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x3, align 4
+// CHECK-NEXT: %5 = load i32, ptr %y4, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} %4, i32 {{.*}} %5)
+// CHECK-NEXT: br label %expand.next5
+// CHECK: expand.next5:
+// CHECK-NEXT: store i32 4, ptr %y6, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x3, align 4
+// CHECK-NEXT: %7 = load i32, ptr %y6, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} %6, i32 {{.*}} %7)
+// CHECK-NEXT: br label %expand.end7
+// CHECK: expand.end7:
+// CHECK-NEXT: br label %expand.end8
+// CHECK: expand.end8:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f5v()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x2 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: %x6 = alloca i32, align 4
+// CHECK-NEXT: %x8 = alloca i32, align 4
+// CHECK-NEXT: %x10 = alloca i32, align 4
+// CHECK-NEXT: %x12 = alloca i32, align 4
+// CHECK-NEXT: %x14 = alloca i32, align 4
+// CHECK-NEXT: %x16 = alloca i32, align 4
+// CHECK-NEXT: %x18 = alloca i32, align 4
+// CHECK-NEXT: %x20 = alloca i32, align 4
+// CHECK-NEXT: %x22 = alloca i32, align 4
+// CHECK-NEXT: %x24 = alloca i32, align 4
+// CHECK-NEXT: %x26 = alloca i32, align 4
+// CHECK-NEXT: %x28 = alloca %struct.S, align 4
+// CHECK-NEXT: %x31 = alloca %struct.S, align 4
+// CHECK-NEXT: %x34 = alloca %struct.S, align 4
+// CHECK-NEXT: %x37 = alloca %struct.S, align 4
+// CHECK-NEXT: %x40 = alloca %struct.S, align 4
+// CHECK-NEXT: %x43 = alloca %struct.S, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i32 2, ptr %x1, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x1, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 3, ptr %x2, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x2, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store i32 4, ptr %x4, align 4
+// CHECK-NEXT: %3 = load i32, ptr %x4, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end5
+// CHECK: expand.end5:
+// CHECK-NEXT: store i32 5, ptr %x6, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 5)
+// CHECK-NEXT: br label %expand.end7
+// CHECK: expand.end7:
+// CHECK-NEXT: store i32 6, ptr %x8, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 6)
+// CHECK-NEXT: br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT: store i32 7, ptr %x10, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 7)
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: store i32 8, ptr %x12, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 8)
+// CHECK-NEXT: br label %expand.end13
+// CHECK: expand.end13:
+// CHECK-NEXT: store i32 9, ptr %x14, align 4
+// CHECK-NEXT: %call = call {{.*}} i32 @_Z2tgILi9EEiv()
+// CHECK-NEXT: br label %expand.end15
+// CHECK: expand.end15:
+// CHECK-NEXT: store i32 10, ptr %x16, align 4
+// CHECK-NEXT: br label %expand.next17
+// CHECK: expand.next17:
+// CHECK-NEXT: store i32 11, ptr %x18, align 4
+// CHECK-NEXT: br label %expand.next19
+// CHECK: expand.next19:
+// CHECK-NEXT: store i32 12, ptr %x20, align 4
+// CHECK-NEXT: br label %expand.end21
+// CHECK: expand.end21:
+// CHECK-NEXT: store i32 13, ptr %x22, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x22, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT: br label %expand.next23
+// CHECK: expand.next23:
+// CHECK-NEXT: store i32 14, ptr %x24, align 4
+// CHECK-NEXT: %5 = load i32, ptr %x24, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT: br label %expand.next25
+// CHECK: expand.next25:
+// CHECK-NEXT: store i32 15, ptr %x26, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x26, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT: br label %expand.end27
+// CHECK: expand.end27:
+// CHECK-NEXT: call void @_ZN1SC1Ei(ptr {{.*}} %x28, i32 {{.*}} 16)
+// CHECK-NEXT: %x29 = getelementptr inbounds nuw %struct.S, ptr %x28, i32 0, i32 0
+// CHECK-NEXT: %7 = load i32, ptr %x29, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %7)
+// CHECK-NEXT: br label %expand.next30
+// CHECK: expand.next30:
+// CHECK-NEXT: call void @_ZN1SC1Ei(ptr {{.*}} %x31, i32 {{.*}} 17)
+// CHECK-NEXT: %x32 = getelementptr inbounds nuw %struct.S, ptr %x31, i32 0, i32 0
+// CHECK-NEXT: %8 = load i32, ptr %x32, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %8)
+// CHECK-NEXT: br label %expand.next33
+// CHECK: expand.next33:
+// CHECK-NEXT: call void @_ZN1SC1Ei(ptr {{.*}} %x34, i32 {{.*}} 18)
+// CHECK-NEXT: %x35 = getelementptr inbounds nuw %struct.S, ptr %x34, i32 0, i32 0
+// CHECK-NEXT: %9 = load i32, ptr %x35, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %9)
+// CHECK-NEXT: br label %expand.end36
+// CHECK: expand.end36:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x37, ptr align 4 @__const._Z2f5v.x, i64 4, i1 false)
+// CHECK-NEXT: %call38 = call {{.*}} i32 @_Z2tgILi19EEiv()
+// CHECK-NEXT: br label %expand.next39
+// CHECK: expand.next39:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x40, ptr align 4 @__const._Z2f5v.x.1, i64 4, i1 false)
+// CHECK-NEXT: %call41 = call {{.*}} i32 @_Z2tgILi20EEiv()
+// CHECK-NEXT: br label %expand.next42
+// CHECK: expand.next42:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x43, ptr align 4 @__const._Z2f5v.x.2, i64 4, i1 false)
+// CHECK-NEXT: %call44 = call {{.*}} i32 @_Z2tgILi21EEiv()
+// CHECK-NEXT: br label %expand.end45
+// CHECK: expand.end45:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f6v()
+// CHECK: entry:
+// CHECK-NEXT: %ref.tmp = alloca %struct.s1, align 1
+// CHECK-NEXT: %ref.tmp1 = alloca %struct.s1.0, align 1
+// CHECK-NEXT: %ref.tmp2 = alloca %struct.s1.0, align 1
+// CHECK-NEXT: %ref.tmp3 = alloca %struct.s1, align 1
+// CHECK-NEXT: call void @_Z2t1IiEvv()
+// CHECK-NEXT: call void @_Z2t1IlEvv()
+// CHECK-NEXT: call void @_ZN2s1IlE2tfIlEEvv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: call void @_ZN2s1IiE2tfIiEEvv(ptr {{.*}} %ref.tmp1)
+// CHECK-NEXT: call void @_ZN2s1IiE2tfIlEEvv(ptr {{.*}} %ref.tmp2)
+// CHECK-NEXT: call void @_ZN2s1IlE2tfIiEEvv(ptr {{.*}} %ref.tmp3)
+// CHECK-NEXT: call void @_Z2t2I1SEvv()
+// CHECK-NEXT: call void @_Z2t2IA1231_1SEvv()
+// CHECK-NEXT: call void @_Z2t2IPPP1SEvv()
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2t1IiEvv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x2 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: %x6 = alloca i32, align 4
+// CHECK-NEXT: %x8 = alloca i32, align 4
+// CHECK-NEXT: %x10 = alloca i32, align 4
+// CHECK-NEXT: %x12 = alloca i32, align 4
+// CHECK-NEXT: %x14 = alloca i32, align 4
+// CHECK-NEXT: %x16 = alloca i32, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 2, ptr %x1, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x1, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i32 3, ptr %x2, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x2, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store i32 4, ptr %x4, align 4
+// CHECK-NEXT: %3 = load i32, ptr %x4, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end5
+// CHECK: expand.end5:
+// CHECK-NEXT: store i32 5, ptr %x6, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x6, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT: br label %expand.next7
+// CHECK: expand.next7:
+// CHECK-NEXT: store i32 6, ptr %x8, align 4
+// CHECK-NEXT: %5 = load i32, ptr %x8, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT: br label %expand.end9
+// CHECK: expand.end9:
+// CHECK-NEXT: store i32 7, ptr %x10, align 4
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: store i32 8, ptr %x12, align 4
+// CHECK-NEXT: br label %expand.end13
+// CHECK: expand.end13:
+// CHECK-NEXT: store i32 9, ptr %x14, align 4
+// CHECK-NEXT: br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT: store i32 10, ptr %x16, align 4
+// CHECK-NEXT: br label %expand.end17
+// CHECK: expand.end17:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2t1IlEvv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i64, align 8
+// CHECK-NEXT: %x1 = alloca i64, align 8
+// CHECK-NEXT: %x2 = alloca i64, align 8
+// CHECK-NEXT: %x4 = alloca i64, align 8
+// CHECK-NEXT: %x6 = alloca i64, align 8
+// CHECK-NEXT: %x8 = alloca i64, align 8
+// CHECK-NEXT: %x10 = alloca i64, align 8
+// CHECK-NEXT: %x12 = alloca i64, align 8
+// CHECK-NEXT: %x14 = alloca i64, align 8
+// CHECK-NEXT: %x16 = alloca i64, align 8
+// CHECK-NEXT: store i64 1, ptr %x, align 8
+// CHECK-NEXT: %0 = load i64, ptr %x, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i64 2, ptr %x1, align 8
+// CHECK-NEXT: %1 = load i64, ptr %x1, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %1)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i64 3, ptr %x2, align 8
+// CHECK-NEXT: %2 = load i64, ptr %x2, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %2)
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store i64 4, ptr %x4, align 8
+// CHECK-NEXT: %3 = load i64, ptr %x4, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end5
+// CHECK: expand.end5:
+// CHECK-NEXT: store i64 5, ptr %x6, align 8
+// CHECK-NEXT: %4 = load i64, ptr %x6, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %4)
+// CHECK-NEXT: br label %expand.next7
+// CHECK: expand.next7:
+// CHECK-NEXT: store i64 6, ptr %x8, align 8
+// CHECK-NEXT: %5 = load i64, ptr %x8, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %5)
+// CHECK-NEXT: br label %expand.end9
+// CHECK: expand.end9:
+// CHECK-NEXT: store i64 7, ptr %x10, align 8
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: store i64 8, ptr %x12, align 8
+// CHECK-NEXT: br label %expand.end13
+// CHECK: expand.end13:
+// CHECK-NEXT: store i64 9, ptr %x14, align 8
+// CHECK-NEXT: br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT: store i64 10, ptr %x16, align 8
+// CHECK-NEXT: br label %expand.end17
+// CHECK: expand.end17:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s1IlE2tfIlEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i64, align 8
+// CHECK-NEXT: %x2 = alloca i64, align 8
+// CHECK-NEXT: %x3 = alloca i64, align 8
+// CHECK-NEXT: %x5 = alloca i64, align 8
+// CHECK-NEXT: %x7 = alloca i64, align 8
+// CHECK-NEXT: %x9 = alloca i64, align 8
+// CHECK-NEXT: %x11 = alloca i64, align 8
+// CHECK-NEXT: %x13 = alloca i64, align 8
+// CHECK-NEXT: %x15 = alloca i64, align 8
+// CHECK-NEXT: %x17 = alloca i64, align 8
+// CHECK-NEXT: %x19 = alloca i64, align 8
+// CHECK-NEXT: %x21 = alloca i64, align 8
+// CHECK-NEXT: %x23 = alloca i64, align 8
+// CHECK-NEXT: %x25 = alloca i64, align 8
+// CHECK-NEXT: %x27 = alloca i64, align 8
+// CHECK-NEXT: %x29 = alloca i64, align 8
+// CHECK-NEXT: %x31 = alloca i64, align 8
+// CHECK-NEXT: %x33 = alloca i64, align 8
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i64 1, ptr %x, align 8
+// CHECK-NEXT: %0 = load i64, ptr %x, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i64 2, ptr %x2, align 8
+// CHECK-NEXT: %1 = load i64, ptr %x2, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %1)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i64 3, ptr %x3, align 8
+// CHECK-NEXT: %2 = load i64, ptr %x3, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %2)
+// CHECK-NEXT: br label %expand.next4
+// CHECK: expand.next4:
+// CHECK-NEXT: store i64 4, ptr %x5, align 8
+// CHECK-NEXT: %3 = load i64, ptr %x5, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end6
+// CHECK: expand.end6:
+// CHECK-NEXT: store i64 5, ptr %x7, align 8
+// CHECK-NEXT: %4 = load i64, ptr %x7, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %4)
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: store i64 6, ptr %x9, align 8
+// CHECK-NEXT: %5 = load i64, ptr %x9, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %5)
+// CHECK-NEXT: br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT: store i64 7, ptr %x11, align 8
+// CHECK-NEXT: %6 = load i64, ptr %x11, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %6)
+// CHECK-NEXT: br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT: store i64 8, ptr %x13, align 8
+// CHECK-NEXT: %7 = load i64, ptr %x13, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %7)
+// CHECK-NEXT: br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT: store i64 9, ptr %x15, align 8
+// CHECK-NEXT: %8 = load i64, ptr %x15, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %8)
+// CHECK-NEXT: br label %expand.next16
+// CHECK: expand.next16:
+// CHECK-NEXT: store i64 10, ptr %x17, align 8
+// CHECK-NEXT: %9 = load i64, ptr %x17, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %9)
+// CHECK-NEXT: br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT: store i64 11, ptr %x19, align 8
+// CHECK-NEXT: %10 = load i64, ptr %x19, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %10)
+// CHECK-NEXT: br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT: store i64 12, ptr %x21, align 8
+// CHECK-NEXT: %11 = load i64, ptr %x21, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %11)
+// CHECK-NEXT: br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT: store i64 13, ptr %x23, align 8
+// CHECK-NEXT: br label %expand.next24
+// CHECK: expand.next24:
+// CHECK-NEXT: store i64 14, ptr %x25, align 8
+// CHECK-NEXT: br label %expand.end26
+// CHECK: expand.end26:
+// CHECK-NEXT: store i64 15, ptr %x27, align 8
+// CHECK-NEXT: br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT: store i64 16, ptr %x29, align 8
+// CHECK-NEXT: br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT: store i64 17, ptr %x31, align 8
+// CHECK-NEXT: br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT: store i64 18, ptr %x33, align 8
+// CHECK-NEXT: br label %expand.end34
+// CHECK: expand.end34:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s1IiE2tfIiEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x2 = alloca i32, align 4
+// CHECK-NEXT: %x3 = alloca i32, align 4
+// CHECK-NEXT: %x5 = alloca i32, align 4
+// CHECK-NEXT: %x7 = alloca i32, align 4
+// CHECK-NEXT: %x9 = alloca i32, align 4
+// CHECK-NEXT: %x11 = alloca i32, align 4
+// CHECK-NEXT: %x13 = alloca i32, align 4
+// CHECK-NEXT: %x15 = alloca i32, align 4
+// CHECK-NEXT: %x17 = alloca i32, align 4
+// CHECK-NEXT: %x19 = alloca i32, align 4
+// CHECK-NEXT: %x21 = alloca i32, align 4
+// CHECK-NEXT: %x23 = alloca i32, align 4
+// CHECK-NEXT: %x25 = alloca i32, align 4
+// CHECK-NEXT: %x27 = alloca i32, align 4
+// CHECK-NEXT: %x29 = alloca i32, align 4
+// CHECK-NEXT: %x31 = alloca i32, align 4
+// CHECK-NEXT: %x33 = alloca i32, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 2, ptr %x2, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x2, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i32 3, ptr %x3, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x3, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT: br label %expand.next4
+// CHECK: expand.next4:
+// CHECK-NEXT: store i32 4, ptr %x5, align 4
+// CHECK-NEXT: %3 = load i32, ptr %x5, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end6
+// CHECK: expand.end6:
+// CHECK-NEXT: store i32 5, ptr %x7, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x7, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: store i32 6, ptr %x9, align 4
+// CHECK-NEXT: %5 = load i32, ptr %x9, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT: br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT: store i32 7, ptr %x11, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x11, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT: br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT: store i32 8, ptr %x13, align 4
+// CHECK-NEXT: %7 = load i32, ptr %x13, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %7)
+// CHECK-NEXT: br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT: store i32 9, ptr %x15, align 4
+// CHECK-NEXT: %8 = load i32, ptr %x15, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %8)
+// CHECK-NEXT: br label %expand.next16
+// CHECK: expand.next16:
+// CHECK-NEXT: store i32 10, ptr %x17, align 4
+// CHECK-NEXT: %9 = load i32, ptr %x17, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %9)
+// CHECK-NEXT: br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT: store i32 11, ptr %x19, align 4
+// CHECK-NEXT: %10 = load i32, ptr %x19, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %10)
+// CHECK-NEXT: br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT: store i32 12, ptr %x21, align 4
+// CHECK-NEXT: %11 = load i32, ptr %x21, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %11)
+// CHECK-NEXT: br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT: store i32 13, ptr %x23, align 4
+// CHECK-NEXT: br label %expand.next24
+// CHECK: expand.next24:
+// CHECK-NEXT: store i32 14, ptr %x25, align 4
+// CHECK-NEXT: br label %expand.end26
+// CHECK: expand.end26:
+// CHECK-NEXT: store i32 15, ptr %x27, align 4
+// CHECK-NEXT: br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT: store i32 16, ptr %x29, align 4
+// CHECK-NEXT: br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT: store i32 17, ptr %x31, align 4
+// CHECK-NEXT: br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT: store i32 18, ptr %x33, align 4
+// CHECK-NEXT: br label %expand.end34
+// CHECK: expand.end34:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s1IiE2tfIlEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i64, align 8
+// CHECK-NEXT: %x2 = alloca i64, align 8
+// CHECK-NEXT: %x3 = alloca i32, align 4
+// CHECK-NEXT: %x5 = alloca i32, align 4
+// CHECK-NEXT: %x7 = alloca i32, align 4
+// CHECK-NEXT: %x9 = alloca i32, align 4
+// CHECK-NEXT: %x11 = alloca i64, align 8
+// CHECK-NEXT: %x13 = alloca i64, align 8
+// CHECK-NEXT: %x15 = alloca i64, align 8
+// CHECK-NEXT: %x17 = alloca i64, align 8
+// CHECK-NEXT: %x19 = alloca i32, align 4
+// CHECK-NEXT: %x21 = alloca i64, align 8
+// CHECK-NEXT: %x23 = alloca i32, align 4
+// CHECK-NEXT: %x25 = alloca i32, align 4
+// CHECK-NEXT: %x27 = alloca i64, align 8
+// CHECK-NEXT: %x29 = alloca i64, align 8
+// CHECK-NEXT: %x31 = alloca i64, align 8
+// CHECK-NEXT: %x33 = alloca i32, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i64 1, ptr %x, align 8
+// CHECK-NEXT: %0 = load i64, ptr %x, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i64 2, ptr %x2, align 8
+// CHECK-NEXT: %1 = load i64, ptr %x2, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %1)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i32 3, ptr %x3, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x3, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT: br label %expand.next4
+// CHECK: expand.next4:
+// CHECK-NEXT: store i32 4, ptr %x5, align 4
+// CHECK-NEXT: %3 = load i32, ptr %x5, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end6
+// CHECK: expand.end6:
+// CHECK-NEXT: store i32 5, ptr %x7, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x7, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: store i32 6, ptr %x9, align 4
+// CHECK-NEXT: %5 = load i32, ptr %x9, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT: br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT: store i64 7, ptr %x11, align 8
+// CHECK-NEXT: %6 = load i64, ptr %x11, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %6)
+// CHECK-NEXT: br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT: store i64 8, ptr %x13, align 8
+// CHECK-NEXT: %7 = load i64, ptr %x13, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %7)
+// CHECK-NEXT: br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT: store i64 9, ptr %x15, align 8
+// CHECK-NEXT: %8 = load i64, ptr %x15, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %8)
+// CHECK-NEXT: br label %expand.next16
+// CHECK: expand.next16:
+// CHECK-NEXT: store i64 10, ptr %x17, align 8
+// CHECK-NEXT: %9 = load i64, ptr %x17, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %9)
+// CHECK-NEXT: br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT: store i32 11, ptr %x19, align 4
+// CHECK-NEXT: %10 = load i32, ptr %x19, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %10)
+// CHECK-NEXT: br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT: store i64 12, ptr %x21, align 8
+// CHECK-NEXT: %11 = load i64, ptr %x21, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %11)
+// CHECK-NEXT: br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT: store i32 13, ptr %x23, align 4
+// CHECK-NEXT: br label %expand.next24
+// CHECK: expand.next24:
+// CHECK-NEXT: store i32 14, ptr %x25, align 4
+// CHECK-NEXT: br label %expand.end26
+// CHECK: expand.end26:
+// CHECK-NEXT: store i64 15, ptr %x27, align 8
+// CHECK-NEXT: br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT: store i64 16, ptr %x29, align 8
+// CHECK-NEXT: br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT: store i64 17, ptr %x31, align 8
+// CHECK-NEXT: br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT: store i32 18, ptr %x33, align 4
+// CHECK-NEXT: br label %expand.end34
+// CHECK: expand.end34:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s1IlE2tfIiEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x2 = alloca i32, align 4
+// CHECK-NEXT: %x3 = alloca i64, align 8
+// CHECK-NEXT: %x5 = alloca i64, align 8
+// CHECK-NEXT: %x7 = alloca i64, align 8
+// CHECK-NEXT: %x9 = alloca i64, align 8
+// CHECK-NEXT: %x11 = alloca i32, align 4
+// CHECK-NEXT: %x13 = alloca i32, align 4
+// CHECK-NEXT: %x15 = alloca i32, align 4
+// CHECK-NEXT: %x17 = alloca i32, align 4
+// CHECK-NEXT: %x19 = alloca i64, align 8
+// CHECK-NEXT: %x21 = alloca i32, align 4
+// CHECK-NEXT: %x23 = alloca i64, align 8
+// CHECK-NEXT: %x25 = alloca i64, align 8
+// CHECK-NEXT: %x27 = alloca i32, align 4
+// CHECK-NEXT: %x29 = alloca i32, align 4
+// CHECK-NEXT: %x31 = alloca i32, align 4
+// CHECK-NEXT: %x33 = alloca i64, align 8
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 2, ptr %x2, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x2, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i64 3, ptr %x3, align 8
+// CHECK-NEXT: %2 = load i64, ptr %x3, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %2)
+// CHECK-NEXT: br label %expand.next4
+// CHECK: expand.next4:
+// CHECK-NEXT: store i64 4, ptr %x5, align 8
+// CHECK-NEXT: %3 = load i64, ptr %x5, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end6
+// CHECK: expand.end6:
+// CHECK-NEXT: store i64 5, ptr %x7, align 8
+// CHECK-NEXT: %4 = load i64, ptr %x7, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %4)
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: store i64 6, ptr %x9, align 8
+// CHECK-NEXT: %5 = load i64, ptr %x9, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %5)
+// CHECK-NEXT: br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT: store i32 7, ptr %x11, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x11, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT: br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT: store i32 8, ptr %x13, align 4
+// CHECK-NEXT: %7 = load i32, ptr %x13, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %7)
+// CHECK-NEXT: br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT: store i32 9, ptr %x15, align 4
+// CHECK-NEXT: %8 = load i32, ptr %x15, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %8)
+// CHECK-NEXT: br label %expand.next16
+// CHECK: expand.next16:
+// CHECK-NEXT: store i32 10, ptr %x17, align 4
+// CHECK-NEXT: %9 = load i32, ptr %x17, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %9)
+// CHECK-NEXT: br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT: store i64 11, ptr %x19, align 8
+// CHECK-NEXT: %10 = load i64, ptr %x19, align 8
+// CHECK-NEXT: call void @_Z1gl(i64 {{.*}} %10)
+// CHECK-NEXT: br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT: store i32 12, ptr %x21, align 4
+// CHECK-NEXT: %11 = load i32, ptr %x21, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %11)
+// CHECK-NEXT: br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT: store i64 13, ptr %x23, align 8
+// CHECK-NEXT: br label %expand.next24
+// CHECK: expand.next24:
+// CHECK-NEXT: store i64 14, ptr %x25, align 8
+// CHECK-NEXT: br label %expand.end26
+// CHECK: expand.end26:
+// CHECK-NEXT: store i32 15, ptr %x27, align 4
+// CHECK-NEXT: br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT: store i32 16, ptr %x29, align 4
+// CHECK-NEXT: br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT: store i32 17, ptr %x31, align 4
+// CHECK-NEXT: br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT: store i64 18, ptr %x33, align 8
+// CHECK-NEXT: br label %expand.end34
+// CHECK: expand.end34:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f7v()
+// CHECK: entry:
+// CHECK-NEXT: %ref.tmp = alloca %struct.s2, align 1
+// CHECK-NEXT: call void @_Z2t3IJiiiEEvDpT_(i32 {{.*}} 42, i32 {{.*}} 43, i32 {{.*}} 44)
+// CHECK-NEXT: call void @_Z2t4IJLi42ELi43ELi44EEEvv()
+// CHECK-NEXT: call void @_ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: ret void
+
+// CHECK-LABEL: define {{.*}} void @_Z2t3IJiiiEEvDpT_(i32 {{.*}} %ts, i32 {{.*}} %ts1, i32 {{.*}} %ts3)
+// CHECK: entry:
+// CHECK-NEXT: %ts.addr = alloca i32, align 4
+// CHECK-NEXT: %ts.addr2 = alloca i32, align 4
+// CHECK-NEXT: %ts.addr4 = alloca i32, align 4
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x5 = alloca i32, align 4
+// CHECK-NEXT: %x7 = alloca i32, align 4
+// CHECK-NEXT: %x8 = alloca i32, align 4
+// CHECK-NEXT: %x10 = alloca i32, align 4
+// CHECK-NEXT: %x12 = alloca i32, align 4
+// CHECK-NEXT: %x14 = alloca i32, align 4
+// CHECK-NEXT: %x16 = alloca i32, align 4
+// CHECK-NEXT: %x18 = alloca i32, align 4
+// CHECK-NEXT: %x20 = alloca i32, align 4
+// CHECK-NEXT: %x22 = alloca i32, align 4
+// CHECK-NEXT: %x24 = alloca i32, align 4
+// CHECK-NEXT: %x26 = alloca i32, align 4
+// CHECK-NEXT: %x28 = alloca i32, align 4
+// CHECK-NEXT: %x30 = alloca i32, align 4
+// CHECK-NEXT: %x32 = alloca i32, align 4
+// CHECK-NEXT: %x34 = alloca i32, align 4
+// CHECK-NEXT: %x36 = alloca i32, align 4
+// CHECK-NEXT: %x38 = alloca i32, align 4
+// CHECK-NEXT: %x40 = alloca i32, align 4
+// CHECK-NEXT: %x42 = alloca %struct.X, align 4
+// CHECK-NEXT: %x45 = alloca %struct.X, align 4
+// CHECK-NEXT: %x51 = alloca %struct.X, align 4
+// CHECK-NEXT: %x54 = alloca %struct.X, align 4
+// CHECK-NEXT: store i32 %ts, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %ts1, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %ts3, ptr %ts.addr4, align 4
+// CHECK-NEXT: %0 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %0, ptr %x, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: %2 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %2, ptr %x5, align 4
+// CHECK-NEXT: %3 = load i32, ptr %x5, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.next6
+// CHECK: expand.next6:
+// CHECK-NEXT: %4 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT: store i32 %4, ptr %x7, align 4
+// CHECK-NEXT: %5 = load i32, ptr %x7, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i32 1, ptr %x8, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x8, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT: br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT: %7 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %7, ptr %x10, align 4
+// CHECK-NEXT: %8 = load i32, ptr %x10, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %8)
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: %9 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %9, ptr %x12, align 4
+// CHECK-NEXT: %10 = load i32, ptr %x12, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %10)
+// CHECK-NEXT: br label %expand.next13
+// CHECK: expand.next13:
+// CHECK-NEXT: %11 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT: store i32 %11, ptr %x14, align 4
+// CHECK-NEXT: %12 = load i32, ptr %x14, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %12)
+// CHECK-NEXT: br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT: store i32 2, ptr %x16, align 4
+// CHECK-NEXT: %13 = load i32, ptr %x16, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %13)
+// CHECK-NEXT: br label %expand.next17
+// CHECK: expand.next17:
+// CHECK-NEXT: %14 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %14, ptr %x18, align 4
+// CHECK-NEXT: %15 = load i32, ptr %x18, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %15)
+// CHECK-NEXT: br label %expand.next19
+// CHECK: expand.next19:
+// CHECK-NEXT: %16 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %16, ptr %x20, align 4
+// CHECK-NEXT: %17 = load i32, ptr %x20, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %17)
+// CHECK-NEXT: br label %expand.next21
+// CHECK: expand.next21:
+// CHECK-NEXT: %18 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT: store i32 %18, ptr %x22, align 4
+// CHECK-NEXT: %19 = load i32, ptr %x22, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %19)
+// CHECK-NEXT: br label %expand.next23
+// CHECK: expand.next23:
+// CHECK-NEXT: store i32 3, ptr %x24, align 4
+// CHECK-NEXT: %20 = load i32, ptr %x24, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %20)
+// CHECK-NEXT: br label %expand.end25
+// CHECK: expand.end25:
+// CHECK-NEXT: store i32 4, ptr %x26, align 4
+// CHECK-NEXT: %21 = load i32, ptr %x26, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %21)
+// CHECK-NEXT: br label %expand.next27
+// CHECK: expand.next27:
+// CHECK-NEXT: %22 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %22, ptr %x28, align 4
+// CHECK-NEXT: %23 = load i32, ptr %x28, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %23)
+// CHECK-NEXT: br label %expand.next29
+// CHECK: expand.next29:
+// CHECK-NEXT: %24 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %24, ptr %x30, align 4
+// CHECK-NEXT: %25 = load i32, ptr %x30, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %25)
+// CHECK-NEXT: br label %expand.next31
+// CHECK: expand.next31:
+// CHECK-NEXT: %26 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT: store i32 %26, ptr %x32, align 4
+// CHECK-NEXT: %27 = load i32, ptr %x32, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %27)
+// CHECK-NEXT: br label %expand.next33
+// CHECK: expand.next33:
+// CHECK-NEXT: %28 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %28, ptr %x34, align 4
+// CHECK-NEXT: %29 = load i32, ptr %x34, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %29)
+// CHECK-NEXT: br label %expand.next35
+// CHECK: expand.next35:
+// CHECK-NEXT: %30 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %30, ptr %x36, align 4
+// CHECK-NEXT: %31 = load i32, ptr %x36, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %31)
+// CHECK-NEXT: br label %expand.next37
+// CHECK: expand.next37:
+// CHECK-NEXT: %32 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT: store i32 %32, ptr %x38, align 4
+// CHECK-NEXT: %33 = load i32, ptr %x38, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %33)
+// CHECK-NEXT: br label %expand.next39
+// CHECK: expand.next39:
+// CHECK-NEXT: store i32 5, ptr %x40, align 4
+// CHECK-NEXT: %34 = load i32, ptr %x40, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %34)
+// CHECK-NEXT: br label %expand.end41
+// CHECK: expand.end41:
+// CHECK-NEXT: %a = getelementptr inbounds nuw %struct.X, ptr %x42, i32 0, i32 0
+// CHECK-NEXT: %35 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %35, ptr %a, align 4
+// CHECK-NEXT: %b = getelementptr inbounds nuw %struct.X, ptr %x42, i32 0, i32 1
+// CHECK-NEXT: %36 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %36, ptr %b, align 4
+// CHECK-NEXT: %c = getelementptr inbounds nuw %struct.X, ptr %x42, i32 0, i32 2
+// CHECK-NEXT: %37 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT: store i32 %37, ptr %c, align 4
+// CHECK-NEXT: %a43 = getelementptr inbounds nuw %struct.X, ptr %x42, i32 0, i32 0
+// CHECK-NEXT: %38 = load i32, ptr %a43, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %38)
+// CHECK-NEXT: br label %expand.next44
+// CHECK: expand.next44:
+// CHECK-NEXT: %a46 = getelementptr inbounds nuw %struct.X, ptr %x45, i32 0, i32 0
+// CHECK-NEXT: %39 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %39, ptr %a46, align 4
+// CHECK-NEXT: %b47 = getelementptr inbounds nuw %struct.X, ptr %x45, i32 0, i32 1
+// CHECK-NEXT: %40 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %40, ptr %b47, align 4
+// CHECK-NEXT: %c48 = getelementptr inbounds nuw %struct.X, ptr %x45, i32 0, i32 2
+// CHECK-NEXT: %41 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT: store i32 %41, ptr %c48, align 4
+// CHECK-NEXT: %a49 = getelementptr inbounds nuw %struct.X, ptr %x45, i32 0, i32 0
+// CHECK-NEXT: %42 = load i32, ptr %a49, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %42)
+// CHECK-NEXT: br label %expand.next50
+// CHECK: expand.next50:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x51, ptr align 4 @__const._Z2t3IJiiiEEvDpT_.x, i64 12, i1 false)
+// CHECK-NEXT: %a52 = getelementptr inbounds nuw %struct.X, ptr %x51, i32 0, i32 0
+// CHECK-NEXT: %43 = load i32, ptr %a52, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %43)
+// CHECK-NEXT: br label %expand.end53
+// CHECK: expand.end53:
+// CHECK-NEXT: %a55 = getelementptr inbounds nuw %struct.X, ptr %x54, i32 0, i32 0
+// CHECK-NEXT: %44 = load i32, ptr %ts.addr, align 4
+// CHECK-NEXT: store i32 %44, ptr %a55, align 4
+// CHECK-NEXT: %b56 = getelementptr inbounds nuw %struct.X, ptr %x54, i32 0, i32 1
+// CHECK-NEXT: %45 = load i32, ptr %ts.addr2, align 4
+// CHECK-NEXT: store i32 %45, ptr %b56, align 4
+// CHECK-NEXT: %c57 = getelementptr inbounds nuw %struct.X, ptr %x54, i32 0, i32 2
+// CHECK-NEXT: %46 = load i32, ptr %ts.addr4, align 4
+// CHECK-NEXT: store i32 %46, ptr %c57, align 4
+// CHECK-NEXT: %a58 = getelementptr inbounds nuw %struct.X, ptr %x54, i32 0, i32 0
+// CHECK-NEXT: %47 = load i32, ptr %a58, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %47)
+// CHECK-NEXT: br label %expand.end59
+// CHECK: expand.end59:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2t4IJLi42ELi43ELi44EEEvv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: %x6 = alloca i32, align 4
+// CHECK-NEXT: %x9 = alloca i32, align 4
+// CHECK-NEXT: %x12 = alloca i32, align 4
+// CHECK-NEXT: %x15 = alloca i32, align 4
+// CHECK-NEXT: %x18 = alloca i32, align 4
+// CHECK-NEXT: %x21 = alloca i32, align 4
+// CHECK-NEXT: %x24 = alloca i32, align 4
+// CHECK-NEXT: %x27 = alloca i32, align 4
+// CHECK-NEXT: %x30 = alloca i32, align 4
+// CHECK-NEXT: %x33 = alloca i32, align 4
+// CHECK-NEXT: %x36 = alloca i32, align 4
+// CHECK-NEXT: %x39 = alloca i32, align 4
+// CHECK-NEXT: %x42 = alloca i32, align 4
+// CHECK-NEXT: %x45 = alloca i32, align 4
+// CHECK-NEXT: %x48 = alloca i32, align 4
+// CHECK-NEXT: %x51 = alloca i32, align 4
+// CHECK-NEXT: %x54 = alloca i32, align 4
+// CHECK-NEXT: %x57 = alloca %struct.X, align 4
+// CHECK-NEXT: %x60 = alloca %struct.X, align 4
+// CHECK-NEXT: %x63 = alloca %struct.X, align 4
+// CHECK-NEXT: %x66 = alloca %struct.X, align 4
+// CHECK-NEXT: store i32 42, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT: %call = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 43, ptr %x1, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT: %call2 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store i32 44, ptr %x4, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT: %call5 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i32 1, ptr %x6, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 1)
+// CHECK-NEXT: %call7 = call {{.*}} i32 @_Z2tgILi1EEiv()
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: store i32 42, ptr %x9, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT: %call10 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: store i32 43, ptr %x12, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT: %call13 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT: br label %expand.next14
+// CHECK: expand.next14:
+// CHECK-NEXT: store i32 44, ptr %x15, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT: %call16 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT: br label %expand.next17
+// CHECK: expand.next17:
+// CHECK-NEXT: store i32 2, ptr %x18, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 2)
+// CHECK-NEXT: %call19 = call {{.*}} i32 @_Z2tgILi2EEiv()
+// CHECK-NEXT: br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT: store i32 42, ptr %x21, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT: %call22 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT: br label %expand.next23
+// CHECK: expand.next23:
+// CHECK-NEXT: store i32 43, ptr %x24, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT: %call25 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT: br label %expand.next26
+// CHECK: expand.next26:
+// CHECK-NEXT: store i32 44, ptr %x27, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT: %call28 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT: br label %expand.next29
+// CHECK: expand.next29:
+// CHECK-NEXT: store i32 3, ptr %x30, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 3)
+// CHECK-NEXT: %call31 = call {{.*}} i32 @_Z2tgILi3EEiv()
+// CHECK-NEXT: br label %expand.end32
+// CHECK: expand.end32:
+// CHECK-NEXT: store i32 4, ptr %x33, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 4)
+// CHECK-NEXT: %call34 = call {{.*}} i32 @_Z2tgILi4EEiv()
+// CHECK-NEXT: br label %expand.next35
+// CHECK: expand.next35:
+// CHECK-NEXT: store i32 42, ptr %x36, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT: %call37 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT: br label %expand.next38
+// CHECK: expand.next38:
+// CHECK-NEXT: store i32 43, ptr %x39, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT: %call40 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT: br label %expand.next41
+// CHECK: expand.next41:
+// CHECK-NEXT: store i32 44, ptr %x42, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT: %call43 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT: br label %expand.next44
+// CHECK: expand.next44:
+// CHECK-NEXT: store i32 42, ptr %x45, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT: %call46 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT: br label %expand.next47
+// CHECK: expand.next47:
+// CHECK-NEXT: store i32 43, ptr %x48, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 43)
+// CHECK-NEXT: %call49 = call {{.*}} i32 @_Z2tgILi43EEiv()
+// CHECK-NEXT: br label %expand.next50
+// CHECK: expand.next50:
+// CHECK-NEXT: store i32 44, ptr %x51, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 44)
+// CHECK-NEXT: %call52 = call {{.*}} i32 @_Z2tgILi44EEiv()
+// CHECK-NEXT: br label %expand.next53
+// CHECK: expand.next53:
+// CHECK-NEXT: store i32 5, ptr %x54, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 5)
+// CHECK-NEXT: %call55 = call {{.*}} i32 @_Z2tgILi5EEiv()
+// CHECK-NEXT: br label %expand.end56
+// CHECK: expand.end56:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x57, ptr align 4 @__const._Z2t4IJLi42ELi43ELi44EEEvv.x, i64 12, i1 false)
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT: %call58 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT: br label %expand.next59
+// CHECK: expand.next59:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x60, ptr align 4 @__const._Z2t4IJLi42ELi43ELi44EEEvv.x.3, i64 12, i1 false)
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT: %call61 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT: br label %expand.next62
+// CHECK: expand.next62:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x63, ptr align 4 @__const._Z2t4IJLi42ELi43ELi44EEEvv.x.4, i64 12, i1 false)
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 6)
+// CHECK-NEXT: %call64 = call {{.*}} i32 @_Z2tgILi6EEiv()
+// CHECK-NEXT: br label %expand.end65
+// CHECK: expand.end65:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x66, ptr align 4 @__const._Z2t4IJLi42ELi43ELi44EEEvv.x.5, i64 12, i1 false)
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 42)
+// CHECK-NEXT: %call67 = call {{.*}} i32 @_Z2tgILi42EEiv()
+// CHECK-NEXT: br label %expand.end68
+// CHECK: expand.end68:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x2 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: %x6 = alloca i32, align 4
+// CHECK-NEXT: %x8 = alloca i32, align 4
+// CHECK-NEXT: %x10 = alloca i32, align 4
+// CHECK-NEXT: %x11 = alloca %struct.X, align 4
+// CHECK-NEXT: %x13 = alloca %struct.X, align 4
+// CHECK-NEXT: %x16 = alloca i32, align 4
+// CHECK-NEXT: %x18 = alloca i32, align 4
+// CHECK-NEXT: %x21 = alloca i32, align 4
+// CHECK-NEXT: %x24 = alloca i32, align 4
+// CHECK-NEXT: %x27 = alloca i32, align 4
+// CHECK-NEXT: %x30 = alloca i32, align 4
+// CHECK-NEXT: %x33 = alloca %struct.X, align 4
+// CHECK-NEXT: %x36 = alloca %struct.X, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %0)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 2, ptr %x2, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x2, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store i32 3, ptr %x4, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x4, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %2)
+// CHECK-NEXT: br label %expand.next5
+// CHECK: expand.next5:
+// CHECK-NEXT: store i32 4, ptr %x6, align 4
+// CHECK-NEXT: %3 = load i32, ptr %x6, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.next7
+// CHECK: expand.next7:
+// CHECK-NEXT: store i32 5, ptr %x8, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x8, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %4)
+// CHECK-NEXT: br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT: store i32 6, ptr %x10, align 4
+// CHECK-NEXT: %5 = load i32, ptr %x10, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %5)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x11, ptr align 4 @__const._ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv.x, i64 12, i1 false)
+// CHECK-NEXT: %a = getelementptr inbounds nuw %struct.X, ptr %x11, i32 0, i32 0
+// CHECK-NEXT: %6 = load i32, ptr %a, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %6)
+// CHECK-NEXT: br label %expand.next12
+// CHECK: expand.next12:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x13, ptr align 4 @__const._ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv.x.6, i64 12, i1 false)
+// CHECK-NEXT: %a14 = getelementptr inbounds nuw %struct.X, ptr %x13, i32 0, i32 0
+// CHECK-NEXT: %7 = load i32, ptr %a14, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} %7)
+// CHECK-NEXT: br label %expand.end15
+// CHECK: expand.end15:
+// CHECK-NEXT: store i32 1, ptr %x16, align 4
+// CHECK-NEXT: %call = call {{.*}} i32 @_Z2tgILi1EEiv()
+// CHECK-NEXT: br label %expand.next17
+// CHECK: expand.next17:
+// CHECK-NEXT: store i32 2, ptr %x18, align 4
+// CHECK-NEXT: %call19 = call {{.*}} i32 @_Z2tgILi2EEiv()
+// CHECK-NEXT: br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT: store i32 3, ptr %x21, align 4
+// CHECK-NEXT: %call22 = call {{.*}} i32 @_Z2tgILi3EEiv()
+// CHECK-NEXT: br label %expand.next23
+// CHECK: expand.next23:
+// CHECK-NEXT: store i32 4, ptr %x24, align 4
+// CHECK-NEXT: %call25 = call {{.*}} i32 @_Z2tgILi4EEiv()
+// CHECK-NEXT: br label %expand.next26
+// CHECK: expand.next26:
+// CHECK-NEXT: store i32 5, ptr %x27, align 4
+// CHECK-NEXT: %call28 = call {{.*}} i32 @_Z2tgILi5EEiv()
+// CHECK-NEXT: br label %expand.next29
+// CHECK: expand.next29:
+// CHECK-NEXT: store i32 6, ptr %x30, align 4
+// CHECK-NEXT: %call31 = call {{.*}} i32 @_Z2tgILi6EEiv()
+// CHECK-NEXT: br label %expand.end32
+// CHECK: expand.end32:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x33, ptr align 4 @__const._ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv.x.7, i64 12, i1 false)
+// CHECK-NEXT: %call34 = call {{.*}} i32 @_Z2tgILi1EEiv()
+// CHECK-NEXT: br label %expand.next35
+// CHECK: expand.next35:
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x36, ptr align 4 @__const._ZN2s2IJLi1ELi2ELi3EEE2tfIJLi4ELi5ELi6EEEEvv.x.8, i64 12, i1 false)
+// CHECK-NEXT: %call37 = call {{.*}} i32 @_Z2tgILi4EEiv()
+// CHECK-NEXT: br label %expand.end38
+// CHECK: expand.end38:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2f8v()
+// CHECK: entry:
+// CHECK-NEXT: call void @_Z2t5IJLi1ELi2ELi3EEEvv()
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z2t5IJLi1ELi2ELi3EEEvv()
+// CHECK: entry:
+// CHECK-NEXT: %ref.tmp = alloca %class.anon, align 1
+// CHECK-NEXT: %ref.tmp1 = alloca %class.anon.1, align 1
+// CHECK-NEXT: %ref.tmp2 = alloca %class.anon.3, align 1
+// CHECK-NEXT: call void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE1_clEv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: call void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE0_clEv(ptr {{.*}} %ref.tmp1)
+// CHECK-NEXT: call void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE_clEv(ptr {{.*}} %ref.tmp2)
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z22references_enumeratingv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %y = alloca i32, align 4
+// CHECK-NEXT: %z = alloca i32, align 4
+// CHECK-NEXT: %v = alloca ptr, align 8
+// CHECK-NEXT: %v1 = alloca ptr, align 8
+// CHECK-NEXT: %v4 = alloca ptr, align 8
+// CHECK-NEXT: %v6 = alloca ptr, align 8
+// CHECK-NEXT: %v9 = alloca ptr, align 8
+// CHECK-NEXT: %v12 = alloca ptr, align 8
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: store i32 2, ptr %y, align 4
+// CHECK-NEXT: store i32 3, ptr %z, align 4
+// CHECK-NEXT: store ptr %x, ptr %v, align 8
+// CHECK-NEXT: %0 = load ptr, ptr %v, align 8
+// CHECK-NEXT: %1 = load i32, ptr %0, align 4
+// CHECK-NEXT: %inc = add nsw i32 %1, 1
+// CHECK-NEXT: store i32 %inc, ptr %0, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store ptr %y, ptr %v1, align 8
+// CHECK-NEXT: %2 = load ptr, ptr %v1, align 8
+// CHECK-NEXT: %3 = load i32, ptr %2, align 4
+// CHECK-NEXT: %inc2 = add nsw i32 %3, 1
+// CHECK-NEXT: store i32 %inc2, ptr %2, align 4
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store ptr %z, ptr %v4, align 8
+// CHECK-NEXT: %4 = load ptr, ptr %v4, align 8
+// CHECK-NEXT: %5 = load i32, ptr %4, align 4
+// CHECK-NEXT: %inc5 = add nsw i32 %5, 1
+// CHECK-NEXT: store i32 %inc5, ptr %4, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store ptr %x, ptr %v6, align 8
+// CHECK-NEXT: %6 = load ptr, ptr %v6, align 8
+// CHECK-NEXT: %7 = load i32, ptr %6, align 4
+// CHECK-NEXT: %inc7 = add nsw i32 %7, 1
+// CHECK-NEXT: store i32 %inc7, ptr %6, align 4
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: store ptr %y, ptr %v9, align 8
+// CHECK-NEXT: %8 = load ptr, ptr %v9, align 8
+// CHECK-NEXT: %9 = load i32, ptr %8, align 4
+// CHECK-NEXT: %inc10 = add nsw i32 %9, 1
+// CHECK-NEXT: store i32 %inc10, ptr %8, align 4
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: store ptr %z, ptr %v12, align 8
+// CHECK-NEXT: %10 = load ptr, ptr %v12, align 8
+// CHECK-NEXT: %11 = load i32, ptr %10, align 4
+// CHECK-NEXT: %inc13 = add nsw i32 %11, 1
+// CHECK-NEXT: store i32 %inc13, ptr %10, align 4
+// CHECK-NEXT: br label %expand.end14
+// CHECK: expand.end14:
+// CHECK-NEXT: %12 = load i32, ptr %x, align 4
+// CHECK-NEXT: %13 = load i32, ptr %y, align 4
+// CHECK-NEXT: %add = add nsw i32 %12, %13
+// CHECK-NEXT: %14 = load i32, ptr %z, align 4
+// CHECK-NEXT: %add15 = add nsw i32 %add, %14
+// CHECK-NEXT: ret i32 %add15
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE1_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 1)
+// CHECK-NEXT: %call = call {{.*}} i32 @_Z2tgILi1EEiv()
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE0_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i32 2, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 2)
+// CHECK-NEXT: %call = call {{.*}} i32 @_Z2tgILi2EEiv()
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ2t5IJLi1ELi2ELi3EEEvvENKUlvE_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: store i32 3, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1gi(i32 {{.*}} 3)
+// CHECK-NEXT: %call = call {{.*}} i32 @_Z2tgILi3EEiv()
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: ret void
diff --git a/clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp b/clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp
new file mode 100644
index 0000000000000..f94b580290500
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp
@@ -0,0 +1,429 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+void h(int, int);
+
+void break_continue() {
+ template for (auto x : {1, 2}) {
+ break;
+ h(1, x);
+ }
+
+ template for (auto x : {3, 4}) {
+ continue;
+ h(2, x);
+ }
+
+ template for (auto x : {5, 6}) {
+ if (x == 2) break;
+ h(3, x);
+ }
+
+ template for (auto x : {7, 8}) {
+ if (x == 2) continue;
+ h(4, x);
+ }
+}
+
+int break_continue_nested() {
+ int sum = 0;
+
+ template for (auto x : {1, 2}) {
+ template for (auto y : {3, 4}) {
+ if (x == 2) break;
+ sum += y;
+ }
+ sum += x;
+ }
+
+ template for (auto x : {5, 6}) {
+ template for (auto y : {7, 8}) {
+ if (x == 6) continue;
+ sum += y;
+ }
+ sum += x;
+ }
+
+ return sum;
+}
+
+void label() {
+ // Only local labels are allowed in expansion statements.
+ template for (auto x : {1, 2, 3}) {
+ __label__ a;
+ if (x == 1) goto a;
+ h(1, x);
+ a:;
+ }
+}
+
+void nested_label() {
+ template for (auto x : {1, 2}) {
+ __label__ a;
+ template for (auto y : {3, 4}) {
+ if (y == 3) goto a;
+ if (y == 4) goto end;
+ h(x, y);
+ }
+ a:;
+ }
+ end:
+}
+
+
+// CHECK-LABEL: define {{.*}} void @_Z14break_continuev()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x2 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: %x6 = alloca i32, align 4
+// CHECK-NEXT: %x11 = alloca i32, align 4
+// CHECK-NEXT: %x16 = alloca i32, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store i32 3, ptr %x1, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 4, ptr %x2, align 4
+// CHECK-NEXT: br label %expand.end3
+// CHECK: expand.end3:
+// CHECK-NEXT: store i32 5, ptr %x4, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x4, align 4
+// CHECK-NEXT: %cmp = icmp eq i32 %0, 2
+// CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
+// CHECK: if.then:
+// CHECK-NEXT: br label %expand.end10
+// CHECK: if.end:
+// CHECK-NEXT: %1 = load i32, ptr %x4, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} 3, i32 {{.*}} %1)
+// CHECK-NEXT: br label %expand.next5
+// CHECK: expand.next5:
+// CHECK-NEXT: store i32 6, ptr %x6, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x6, align 4
+// CHECK-NEXT: %cmp7 = icmp eq i32 %2, 2
+// CHECK-NEXT: br i1 %cmp7, label %if.then8, label %if.end9
+// CHECK: if.then8:
+// CHECK-NEXT: br label %expand.end10
+// CHECK: if.end9:
+// CHECK-NEXT: %3 = load i32, ptr %x6, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} 3, i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.end10
+// CHECK: expand.end10:
+// CHECK-NEXT: store i32 7, ptr %x11, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x11, align 4
+// CHECK-NEXT: %cmp12 = icmp eq i32 %4, 2
+// CHECK-NEXT: br i1 %cmp12, label %if.then13, label %if.end14
+// CHECK: if.then13:
+// CHECK-NEXT: br label %expand.next15
+// CHECK: if.end14:
+// CHECK-NEXT: %5 = load i32, ptr %x11, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} 4, i32 {{.*}} %5)
+// CHECK-NEXT: br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT: store i32 8, ptr %x16, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x16, align 4
+// CHECK-NEXT: %cmp17 = icmp eq i32 %6, 2
+// CHECK-NEXT: br i1 %cmp17, label %if.then18, label %if.end19
+// CHECK: if.then18:
+// CHECK-NEXT: br label %expand.end20
+// CHECK: if.end19:
+// CHECK-NEXT: %7 = load i32, ptr %x16, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} 4, i32 {{.*}} %7)
+// CHECK-NEXT: br label %expand.end20
+// CHECK: expand.end20:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z21break_continue_nestedv()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %y = alloca i32, align 4
+// CHECK-NEXT: %y1 = alloca i32, align 4
+// CHECK-NEXT: %x8 = alloca i32, align 4
+// CHECK-NEXT: %y9 = alloca i32, align 4
+// CHECK-NEXT: %y15 = alloca i32, align 4
+// CHECK-NEXT: %x23 = alloca i32, align 4
+// CHECK-NEXT: %y24 = alloca i32, align 4
+// CHECK-NEXT: %y30 = alloca i32, align 4
+// CHECK-NEXT: %x38 = alloca i32, align 4
+// CHECK-NEXT: %y39 = alloca i32, align 4
+// CHECK-NEXT: %y45 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: store i32 3, ptr %y, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: %cmp = icmp eq i32 %0, 2
+// CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
+// CHECK: if.then:
+// CHECK-NEXT: br label %expand.end
+// CHECK: if.end:
+// CHECK-NEXT: %1 = load i32, ptr %y, align 4
+// CHECK-NEXT: %2 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %2, %1
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 4, ptr %y1, align 4
+// CHECK-NEXT: %3 = load i32, ptr %x, align 4
+// CHECK-NEXT: %cmp2 = icmp eq i32 %3, 2
+// CHECK-NEXT: br i1 %cmp2, label %if.then3, label %if.end4
+// CHECK: if.then3:
+// CHECK-NEXT: br label %expand.end
+// CHECK: if.end4:
+// CHECK-NEXT: %4 = load i32, ptr %y1, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add5 = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: %6 = load i32, ptr %x, align 4
+// CHECK-NEXT: %7 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add6 = add nsw i32 %7, %6
+// CHECK-NEXT: store i32 %add6, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next7
+// CHECK: expand.next7:
+// CHECK-NEXT: store i32 2, ptr %x8, align 4
+// CHECK-NEXT: store i32 3, ptr %y9, align 4
+// CHECK-NEXT: %8 = load i32, ptr %x8, align 4
+// CHECK-NEXT: %cmp10 = icmp eq i32 %8, 2
+// CHECK-NEXT: br i1 %cmp10, label %if.then11, label %if.end12
+// CHECK: if.then11:
+// CHECK-NEXT: br label %expand.end20
+// CHECK: if.end12:
+// CHECK-NEXT: %9 = load i32, ptr %y9, align 4
+// CHECK-NEXT: %10 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add13 = add nsw i32 %10, %9
+// CHECK-NEXT: store i32 %add13, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next14
+// CHECK: expand.next14:
+// CHECK-NEXT: store i32 4, ptr %y15, align 4
+// CHECK-NEXT: %11 = load i32, ptr %x8, align 4
+// CHECK-NEXT: %cmp16 = icmp eq i32 %11, 2
+// CHECK-NEXT: br i1 %cmp16, label %if.then17, label %if.end18
+// CHECK: if.then17:
+// CHECK-NEXT: br label %expand.end20
+// CHECK: if.end18:
+// CHECK-NEXT: %12 = load i32, ptr %y15, align 4
+// CHECK-NEXT: %13 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add19 = add nsw i32 %13, %12
+// CHECK-NEXT: store i32 %add19, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end20
+// CHECK: expand.end20:
+// CHECK-NEXT: %14 = load i32, ptr %x8, align 4
+// CHECK-NEXT: %15 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add21 = add nsw i32 %15, %14
+// CHECK-NEXT: store i32 %add21, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end22
+// CHECK: expand.end22:
+// CHECK-NEXT: store i32 5, ptr %x23, align 4
+// CHECK-NEXT: store i32 7, ptr %y24, align 4
+// CHECK-NEXT: %16 = load i32, ptr %x23, align 4
+// CHECK-NEXT: %cmp25 = icmp eq i32 %16, 6
+// CHECK-NEXT: br i1 %cmp25, label %if.then26, label %if.end27
+// CHECK: if.then26:
+// CHECK-NEXT: br label %expand.next29
+// CHECK: if.end27:
+// CHECK-NEXT: %17 = load i32, ptr %y24, align 4
+// CHECK-NEXT: %18 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add28 = add nsw i32 %18, %17
+// CHECK-NEXT: store i32 %add28, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next29
+// CHECK: expand.next29:
+// CHECK-NEXT: store i32 8, ptr %y30, align 4
+// CHECK-NEXT: %19 = load i32, ptr %x23, align 4
+// CHECK-NEXT: %cmp31 = icmp eq i32 %19, 6
+// CHECK-NEXT: br i1 %cmp31, label %if.then32, label %if.end33
+// CHECK: if.then32:
+// CHECK-NEXT: br label %expand.end35
+// CHECK: if.end33:
+// CHECK-NEXT: %20 = load i32, ptr %y30, align 4
+// CHECK-NEXT: %21 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add34 = add nsw i32 %21, %20
+// CHECK-NEXT: store i32 %add34, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end35
+// CHECK: expand.end35:
+// CHECK-NEXT: %22 = load i32, ptr %x23, align 4
+// CHECK-NEXT: %23 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add36 = add nsw i32 %23, %22
+// CHECK-NEXT: store i32 %add36, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next37
+// CHECK: expand.next37:
+// CHECK-NEXT: store i32 6, ptr %x38, align 4
+// CHECK-NEXT: store i32 7, ptr %y39, align 4
+// CHECK-NEXT: %24 = load i32, ptr %x38, align 4
+// CHECK-NEXT: %cmp40 = icmp eq i32 %24, 6
+// CHECK-NEXT: br i1 %cmp40, label %if.then41, label %if.end42
+// CHECK: if.then41:
+// CHECK-NEXT: br label %expand.next44
+// CHECK: if.end42:
+// CHECK-NEXT: %25 = load i32, ptr %y39, align 4
+// CHECK-NEXT: %26 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add43 = add nsw i32 %26, %25
+// CHECK-NEXT: store i32 %add43, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next44
+// CHECK: expand.next44:
+// CHECK-NEXT: store i32 8, ptr %y45, align 4
+// CHECK-NEXT: %27 = load i32, ptr %x38, align 4
+// CHECK-NEXT: %cmp46 = icmp eq i32 %27, 6
+// CHECK-NEXT: br i1 %cmp46, label %if.then47, label %if.end48
+// CHECK: if.then47:
+// CHECK-NEXT: br label %expand.end50
+// CHECK: if.end48:
+// CHECK-NEXT: %28 = load i32, ptr %y45, align 4
+// CHECK-NEXT: %29 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add49 = add nsw i32 %29, %28
+// CHECK-NEXT: store i32 %add49, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end50
+// CHECK: expand.end50:
+// CHECK-NEXT: %30 = load i32, ptr %x38, align 4
+// CHECK-NEXT: %31 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add51 = add nsw i32 %31, %30
+// CHECK-NEXT: store i32 %add51, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end52
+// CHECK: expand.end52:
+// CHECK-NEXT: %32 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %32
+
+
+// CHECK-LABEL: define {{.*}} void @_Z5labelv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x7 = alloca i32, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: %cmp = icmp eq i32 %0, 1
+// CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
+// CHECK: if.then:
+// CHECK-NEXT: br label %a
+// CHECK: if.end:
+// CHECK-NEXT: %1 = load i32, ptr %x, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} 1, i32 {{.*}} %1)
+// CHECK-NEXT: br label %a
+// CHECK: a:
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 2, ptr %x1, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x1, align 4
+// CHECK-NEXT: %cmp2 = icmp eq i32 %2, 1
+// CHECK-NEXT: br i1 %cmp2, label %if.then3, label %if.end4
+// CHECK: if.then3:
+// CHECK-NEXT: br label %a5
+// CHECK: if.end4:
+// CHECK-NEXT: %3 = load i32, ptr %x1, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} 1, i32 {{.*}} %3)
+// CHECK-NEXT: br label %a5
+// CHECK: a5:
+// CHECK-NEXT: br label %expand.next6
+// CHECK: expand.next6:
+// CHECK-NEXT: store i32 3, ptr %x7, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x7, align 4
+// CHECK-NEXT: %cmp8 = icmp eq i32 %4, 1
+// CHECK-NEXT: br i1 %cmp8, label %if.then9, label %if.end10
+// CHECK: if.then9:
+// CHECK-NEXT: br label %a11
+// CHECK: if.end10:
+// CHECK-NEXT: %5 = load i32, ptr %x7, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} 1, i32 {{.*}} %5)
+// CHECK-NEXT: br label %a11
+// CHECK: a11:
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_Z12nested_labelv()
+// CHECK: entry:
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %y = alloca i32, align 4
+// CHECK-NEXT: %y4 = alloca i32, align 4
+// CHECK-NEXT: %x12 = alloca i32, align 4
+// CHECK-NEXT: %y13 = alloca i32, align 4
+// CHECK-NEXT: %y21 = alloca i32, align 4
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: store i32 3, ptr %y, align 4
+// CHECK-NEXT: %0 = load i32, ptr %y, align 4
+// CHECK-NEXT: %cmp = icmp eq i32 %0, 3
+// CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
+// CHECK: if.then:
+// CHECK-NEXT: br label %a
+// CHECK: if.end:
+// CHECK-NEXT: %1 = load i32, ptr %y, align 4
+// CHECK-NEXT: %cmp1 = icmp eq i32 %1, 4
+// CHECK-NEXT: br i1 %cmp1, label %if.then2, label %if.end3
+// CHECK: if.then2:
+// CHECK-NEXT: br label %end
+// CHECK: if.end3:
+// CHECK-NEXT: %2 = load i32, ptr %x, align 4
+// CHECK-NEXT: %3 = load i32, ptr %y, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} %2, i32 {{.*}} %3)
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 4, ptr %y4, align 4
+// CHECK-NEXT: %4 = load i32, ptr %y4, align 4
+// CHECK-NEXT: %cmp5 = icmp eq i32 %4, 3
+// CHECK-NEXT: br i1 %cmp5, label %if.then6, label %if.end7
+// CHECK: if.then6:
+// CHECK-NEXT: br label %a
+// CHECK: if.end7:
+// CHECK-NEXT: %5 = load i32, ptr %y4, align 4
+// CHECK-NEXT: %cmp8 = icmp eq i32 %5, 4
+// CHECK-NEXT: br i1 %cmp8, label %if.then9, label %if.end10
+// CHECK: if.then9:
+// CHECK-NEXT: br label %end
+// CHECK: if.end10:
+// CHECK-NEXT: %6 = load i32, ptr %x, align 4
+// CHECK-NEXT: %7 = load i32, ptr %y4, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} %6, i32 {{.*}} %7)
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: br label %a
+// CHECK: a:
+// CHECK-NEXT: br label %expand.next11
+// CHECK: expand.next11:
+// CHECK-NEXT: store i32 2, ptr %x12, align 4
+// CHECK-NEXT: store i32 3, ptr %y13, align 4
+// CHECK-NEXT: %8 = load i32, ptr %y13, align 4
+// CHECK-NEXT: %cmp14 = icmp eq i32 %8, 3
+// CHECK-NEXT: br i1 %cmp14, label %if.then15, label %if.end16
+// CHECK: if.then15:
+// CHECK-NEXT: br label %a29
+// CHECK: if.end16:
+// CHECK-NEXT: %9 = load i32, ptr %y13, align 4
+// CHECK-NEXT: %cmp17 = icmp eq i32 %9, 4
+// CHECK-NEXT: br i1 %cmp17, label %if.then18, label %if.end19
+// CHECK: if.then18:
+// CHECK-NEXT: br label %end
+// CHECK: if.end19:
+// CHECK-NEXT: %10 = load i32, ptr %x12, align 4
+// CHECK-NEXT: %11 = load i32, ptr %y13, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} %10, i32 {{.*}} %11)
+// CHECK-NEXT: br label %expand.next20
+// CHECK: expand.next20:
+// CHECK-NEXT: store i32 4, ptr %y21, align 4
+// CHECK-NEXT: %12 = load i32, ptr %y21, align 4
+// CHECK-NEXT: %cmp22 = icmp eq i32 %12, 3
+// CHECK-NEXT: br i1 %cmp22, label %if.then23, label %if.end24
+// CHECK: if.then23:
+// CHECK-NEXT: br label %a29
+// CHECK: if.end24:
+// CHECK-NEXT: %13 = load i32, ptr %y21, align 4
+// CHECK-NEXT: %cmp25 = icmp eq i32 %13, 4
+// CHECK-NEXT: br i1 %cmp25, label %if.then26, label %if.end27
+// CHECK: if.then26:
+// CHECK-NEXT: br label %end
+// CHECK: if.end27:
+// CHECK-NEXT: %14 = load i32, ptr %x12, align 4
+// CHECK-NEXT: %15 = load i32, ptr %y21, align 4
+// CHECK-NEXT: call void @_Z1hii(i32 {{.*}} %14, i32 {{.*}} %15)
+// CHECK-NEXT: br label %expand.end28
+// CHECK: expand.end28:
+// CHECK-NEXT: br label %a29
+// CHECK: a29:
+// CHECK-NEXT: br label %expand.end30
+// CHECK: expand.end30:
+// CHECK-NEXT: br label %end
+// CHECK: end:
+// CHECK-NEXT: ret void
diff --git a/clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp b/clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp
new file mode 100644
index 0000000000000..e0de7ced5baee
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp
@@ -0,0 +1,208 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+struct E {
+ int x, y;
+ constexpr E(int x, int y) : x{x}, y{y} {}
+};
+
+template <typename ...Es>
+int unexpanded_pack_good(Es ...es) {
+ int sum = 0;
+ ([&] {
+ template for (auto x : es) sum += x;
+ template for (Es e : {{5, 6}, {7, 8}}) sum += e.x + e.y;
+ }(), ...);
+ return sum;
+}
+
+int unexpanded_pack() {
+ return unexpanded_pack_good(E{1, 2}, E{3, 4});
+}
+
+
+// CHECK: %struct.E = type { i32, i32 }
+// CHECK: %class.anon = type { ptr, ptr }
+// CHECK: %class.anon.0 = type { ptr, ptr }
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z15unexpanded_packv()
+// CHECK: entry:
+// CHECK-NEXT: %agg.tmp = alloca %struct.E, align 4
+// CHECK-NEXT: %agg.tmp1 = alloca %struct.E, align 4
+// CHECK-NEXT: call void @_ZN1EC1Eii(ptr {{.*}} %agg.tmp, i32 {{.*}} 1, i32 {{.*}} 2)
+// CHECK-NEXT: call void @_ZN1EC1Eii(ptr {{.*}} %agg.tmp1, i32 {{.*}} 3, i32 {{.*}} 4)
+// CHECK-NEXT: %0 = load i64, ptr %agg.tmp, align 4
+// CHECK-NEXT: %1 = load i64, ptr %agg.tmp1, align 4
+// CHECK-NEXT: %call = call {{.*}} i32 @_Z20unexpanded_pack_goodIJ1ES0_EEiDpT_(i64 %0, i64 %1)
+// CHECK-NEXT: ret i32 %call
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z20unexpanded_pack_goodIJ1ES0_EEiDpT_(i64 %es.coerce, i64 %es.coerce2)
+// CHECK: entry:
+// CHECK-NEXT: %es = alloca %struct.E, align 4
+// CHECK-NEXT: %es3 = alloca %struct.E, align 4
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %ref.tmp = alloca %class.anon, align 8
+// CHECK-NEXT: %ref.tmp4 = alloca %class.anon.0, align 8
+// CHECK-NEXT: store i64 %es.coerce, ptr %es, align 4
+// CHECK-NEXT: store i64 %es.coerce2, ptr %es3, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: %0 = getelementptr inbounds nuw %class.anon, ptr %ref.tmp, i32 0, i32 0
+// CHECK-NEXT: store ptr %es, ptr %0, align 8
+// CHECK-NEXT: %1 = getelementptr inbounds nuw %class.anon, ptr %ref.tmp, i32 0, i32 1
+// CHECK-NEXT: store ptr %sum, ptr %1, align 8
+// CHECK-NEXT: call void @_ZZ20unexpanded_pack_goodIJ1ES0_EEiDpT_ENKUlvE0_clEv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: %2 = getelementptr inbounds nuw %class.anon.0, ptr %ref.tmp4, i32 0, i32 0
+// CHECK-NEXT: store ptr %es3, ptr %2, align 8
+// CHECK-NEXT: %3 = getelementptr inbounds nuw %class.anon.0, ptr %ref.tmp4, i32 0, i32 1
+// CHECK-NEXT: store ptr %sum, ptr %3, align 8
+// CHECK-NEXT: call void @_ZZ20unexpanded_pack_goodIJ1ES0_EEiDpT_ENKUlvE_clEv(ptr {{.*}} %ref.tmp4)
+// CHECK-NEXT: %4 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %4
+
+
+// CHECK-LABEL: define {{.*}} void @_ZN1EC1Eii(ptr {{.*}} %this, i32 {{.*}} %x, i32 {{.*}} %y) {{.*}}
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %x.addr = alloca i32, align 4
+// CHECK-NEXT: %y.addr = alloca i32, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: store i32 %x, ptr %x.addr, align 4
+// CHECK-NEXT: store i32 %y, ptr %y.addr, align 4
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: %0 = load i32, ptr %x.addr, align 4
+// CHECK-NEXT: %1 = load i32, ptr %y.addr, align 4
+// CHECK-NEXT: call void @_ZN1EC2Eii(ptr {{.*}} %this1, i32 {{.*}} %0, i32 {{.*}} %1)
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ20unexpanded_pack_goodIJ1ES0_EEiDpT_ENKUlvE0_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x3 = alloca i32, align 4
+// CHECK-NEXT: %e = alloca %struct.E, align 4
+// CHECK-NEXT: %e10 = alloca %struct.E, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: %1 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 0
+// CHECK-NEXT: %2 = load ptr, ptr %1, align 8
+// CHECK-NEXT: store ptr %2, ptr %0, align 8
+// CHECK-NEXT: %3 = load ptr, ptr %0, align 8
+// CHECK-NEXT: %x2 = getelementptr inbounds nuw %struct.E, ptr %3, i32 0, i32 0
+// CHECK-NEXT: %4 = load i32, ptr %x2, align 4
+// CHECK-NEXT: store i32 %4, ptr %x, align 4
+// CHECK-NEXT: %5 = load i32, ptr %x, align 4
+// CHECK-NEXT: %6 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %7 = load ptr, ptr %6, align 8
+// CHECK-NEXT: %8 = load i32, ptr %7, align 4
+// CHECK-NEXT: %add = add nsw i32 %8, %5
+// CHECK-NEXT: store i32 %add, ptr %7, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: %9 = load ptr, ptr %0, align 8
+// CHECK-NEXT: %y = getelementptr inbounds nuw %struct.E, ptr %9, i32 0, i32 1
+// CHECK-NEXT: %10 = load i32, ptr %y, align 4
+// CHECK-NEXT: store i32 %10, ptr %x3, align 4
+// CHECK-NEXT: %11 = load i32, ptr %x3, align 4
+// CHECK-NEXT: %12 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %13 = load ptr, ptr %12, align 8
+// CHECK-NEXT: %14 = load i32, ptr %13, align 4
+// CHECK-NEXT: %add4 = add nsw i32 %14, %11
+// CHECK-NEXT: store i32 %add4, ptr %13, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: call void @_ZN1EC1Eii(ptr {{.*}} %e, i32 {{.*}} 5, i32 {{.*}} 6)
+// CHECK-NEXT: %x5 = getelementptr inbounds nuw %struct.E, ptr %e, i32 0, i32 0
+// CHECK-NEXT: %15 = load i32, ptr %x5, align 4
+// CHECK-NEXT: %y6 = getelementptr inbounds nuw %struct.E, ptr %e, i32 0, i32 1
+// CHECK-NEXT: %16 = load i32, ptr %y6, align 4
+// CHECK-NEXT: %add7 = add nsw i32 %15, %16
+// CHECK-NEXT: %17 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %18 = load ptr, ptr %17, align 8
+// CHECK-NEXT: %19 = load i32, ptr %18, align 4
+// CHECK-NEXT: %add8 = add nsw i32 %19, %add7
+// CHECK-NEXT: store i32 %add8, ptr %18, align 4
+// CHECK-NEXT: br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT: call void @_ZN1EC1Eii(ptr {{.*}} %e10, i32 {{.*}} 7, i32 {{.*}} 8)
+// CHECK-NEXT: %x11 = getelementptr inbounds nuw %struct.E, ptr %e10, i32 0, i32 0
+// CHECK-NEXT: %20 = load i32, ptr %x11, align 4
+// CHECK-NEXT: %y12 = getelementptr inbounds nuw %struct.E, ptr %e10, i32 0, i32 1
+// CHECK-NEXT: %21 = load i32, ptr %y12, align 4
+// CHECK-NEXT: %add13 = add nsw i32 %20, %21
+// CHECK-NEXT: %22 = getelementptr inbounds nuw %class.anon, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %23 = load ptr, ptr %22, align 8
+// CHECK-NEXT: %24 = load i32, ptr %23, align 4
+// CHECK-NEXT: %add14 = add nsw i32 %24, %add13
+// CHECK-NEXT: store i32 %add14, ptr %23, align 4
+// CHECK-NEXT: br label %expand.end15
+// CHECK: expand.end15:
+// CHECK-NEXT: ret void
+
+
+// CHECK-LABEL: define {{.*}} void @_ZZ20unexpanded_pack_goodIJ1ES0_EEiDpT_ENKUlvE_clEv(ptr {{.*}} %this)
+// CHECK: entry:
+// CHECK-NEXT: %this.addr = alloca ptr, align 8
+// CHECK-NEXT: %0 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x3 = alloca i32, align 4
+// CHECK-NEXT: %e = alloca %struct.E, align 4
+// CHECK-NEXT: %e10 = alloca %struct.E, align 4
+// CHECK-NEXT: store ptr %this, ptr %this.addr, align 8
+// CHECK-NEXT: %this1 = load ptr, ptr %this.addr, align 8
+// CHECK-NEXT: %1 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 0
+// CHECK-NEXT: %2 = load ptr, ptr %1, align 8
+// CHECK-NEXT: store ptr %2, ptr %0, align 8
+// CHECK-NEXT: %3 = load ptr, ptr %0, align 8
+// CHECK-NEXT: %x2 = getelementptr inbounds nuw %struct.E, ptr %3, i32 0, i32 0
+// CHECK-NEXT: %4 = load i32, ptr %x2, align 4
+// CHECK-NEXT: store i32 %4, ptr %x, align 4
+// CHECK-NEXT: %5 = load i32, ptr %x, align 4
+// CHECK-NEXT: %6 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %7 = load ptr, ptr %6, align 8
+// CHECK-NEXT: %8 = load i32, ptr %7, align 4
+// CHECK-NEXT: %add = add nsw i32 %8, %5
+// CHECK-NEXT: store i32 %add, ptr %7, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: %9 = load ptr, ptr %0, align 8
+// CHECK-NEXT: %y = getelementptr inbounds nuw %struct.E, ptr %9, i32 0, i32 1
+// CHECK-NEXT: %10 = load i32, ptr %y, align 4
+// CHECK-NEXT: store i32 %10, ptr %x3, align 4
+// CHECK-NEXT: %11 = load i32, ptr %x3, align 4
+// CHECK-NEXT: %12 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %13 = load ptr, ptr %12, align 8
+// CHECK-NEXT: %14 = load i32, ptr %13, align 4
+// CHECK-NEXT: %add4 = add nsw i32 %14, %11
+// CHECK-NEXT: store i32 %add4, ptr %13, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: call void @_ZN1EC1Eii(ptr {{.*}} %e, i32 {{.*}} 5, i32 {{.*}} 6)
+// CHECK-NEXT: %x5 = getelementptr inbounds nuw %struct.E, ptr %e, i32 0, i32 0
+// CHECK-NEXT: %15 = load i32, ptr %x5, align 4
+// CHECK-NEXT: %y6 = getelementptr inbounds nuw %struct.E, ptr %e, i32 0, i32 1
+// CHECK-NEXT: %16 = load i32, ptr %y6, align 4
+// CHECK-NEXT: %add7 = add nsw i32 %15, %16
+// CHECK-NEXT: %17 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %18 = load ptr, ptr %17, align 8
+// CHECK-NEXT: %19 = load i32, ptr %18, align 4
+// CHECK-NEXT: %add8 = add nsw i32 %19, %add7
+// CHECK-NEXT: store i32 %add8, ptr %18, align 4
+// CHECK-NEXT: br label %expand.next9
+// CHECK: expand.next9:
+// CHECK-NEXT: call void @_ZN1EC1Eii(ptr {{.*}} %e10, i32 {{.*}} 7, i32 {{.*}} 8)
+// CHECK-NEXT: %x11 = getelementptr inbounds nuw %struct.E, ptr %e10, i32 0, i32 0
+// CHECK-NEXT: %20 = load i32, ptr %x11, align 4
+// CHECK-NEXT: %y12 = getelementptr inbounds nuw %struct.E, ptr %e10, i32 0, i32 1
+// CHECK-NEXT: %21 = load i32, ptr %y12, align 4
+// CHECK-NEXT: %add13 = add nsw i32 %20, %21
+// CHECK-NEXT: %22 = getelementptr inbounds nuw %class.anon.0, ptr %this1, i32 0, i32 1
+// CHECK-NEXT: %23 = load ptr, ptr %22, align 8
+// CHECK-NEXT: %24 = load i32, ptr %23, align 4
+// CHECK-NEXT: %add14 = add nsw i32 %24, %add13
+// CHECK-NEXT: store i32 %add14, ptr %23, align 4
+// CHECK-NEXT: br label %expand.end15
+// CHECK: expand.end15:
+// CHECK-NEXT: ret void
diff --git a/clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp b/clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp
new file mode 100644
index 0000000000000..ad73972740749
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp
@@ -0,0 +1,474 @@
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+template <typename T, __SIZE_TYPE__ size>
+struct Array {
+ T data[size]{};
+ constexpr const T* begin() const { return data; }
+ constexpr const T* end() const { return data + size; }
+};
+
+int f1() {
+ static constexpr Array<int, 3> integers{1, 2, 3};
+ int sum = 0;
+ template for (auto x : integers) sum += x;
+ return sum;
+}
+
+int f2() {
+ static constexpr Array<int, 3> integers{1, 2, 3};
+ int sum = 0;
+ template for (constexpr auto x : integers) sum += x;
+ return sum;
+}
+
+int f3() {
+ static constexpr Array<int, 0> integers{};
+ int sum = 0;
+ template for (constexpr auto x : integers) {
+ static_assert(false, "not expanded");
+ sum += x;
+ }
+ return sum;
+}
+
+int f4() {
+ static constexpr Array<int, 2> a{1, 2};
+ static constexpr Array<int, 2> b{3, 4};
+ int sum = 0;
+
+ template for (auto x : a)
+ template for (auto y : b)
+ sum += x + y;
+
+ template for (constexpr auto x : a)
+ template for (constexpr auto y : b)
+ sum += x + y;
+
+ return sum;
+}
+
+struct Private {
+ static constexpr Array<int, 3> integers{1, 2, 3};
+ friend constexpr int friend_func();
+
+private:
+ constexpr const int* begin() const { return integers.begin(); }
+ constexpr const int* end() const { return integers.end(); }
+
+public:
+ static int member_func();
+};
+
+int Private::member_func() {
+ int sum = 0;
+ static constexpr Private p1;
+ template for (auto x : p1) sum += x;
+ return sum;
+}
+
+struct CustomIterator {
+ struct iterator {
+ int n;
+
+ constexpr iterator operator+(int m) const {
+ return {n + m};
+ }
+
+ constexpr int operator*() const {
+ return n;
+ }
+
+ // FIXME: Should be '!=' once we support that properly.
+ friend constexpr __PTRDIFF_TYPE__ operator-(iterator a, iterator b) {
+ return a.n - b.n;
+ }
+ };
+
+ constexpr iterator begin() const { return iterator(1); }
+ constexpr iterator end() const { return iterator(5); }
+};
+
+int custom_iterator() {
+ static constexpr CustomIterator c;
+ int sum = 0;
+ template for (auto x : c) sum += x;
+ template for (constexpr auto x : c) sum += x;
+ return sum;
+}
+
+// CHECK: @_ZZ2f1vE8integers = internal constant %struct.Array { [3 x i32] [i32 1, i32 2, i32 3] }, align 4
+// CHECK: @_ZZ2f2vE8integers = internal constant %struct.Array { [3 x i32] [i32 1, i32 2, i32 3] }, align 4
+// CHECK: @_ZZ2f3vE8integers = internal constant %struct.Array.0 zeroinitializer, align 4
+// CHECK: @_ZZ2f4vE1a = internal constant %struct.Array.1 { [2 x i32] [i32 1, i32 2] }, align 4
+// CHECK: @_ZZ2f4vE1b = internal constant %struct.Array.1 { [2 x i32] [i32 3, i32 4] }, align 4
+// CHECK: @_ZZN7Private11member_funcEvE2p1 = internal constant %struct.Private zeroinitializer, align 1
+// CHECK: @_ZN7Private8integersE = {{.*}} constant %struct.Array { [3 x i32] [i32 1, i32 2, i32 3] }, comdat, align 4
+// CHECK: @_ZZ15custom_iteratorvE1c = internal constant %struct.CustomIterator zeroinitializer, align 1
+// CHECK: @__const._Z15custom_iteratorv.__begin1 = private {{.*}} constant %"struct.CustomIterator::iterator" { i32 1 }, align 4
+// CHECK: @__const._Z15custom_iteratorv.__end1 = private {{.*}} constant %"struct.CustomIterator::iterator" { i32 5 }, align 4
+// CHECK: @__const._Z15custom_iteratorv.__begin1.1 = private {{.*}} constant %"struct.CustomIterator::iterator" { i32 1 }, align 4
+// CHECK: @__const._Z15custom_iteratorv.__end1.2 = private {{.*}} constant %"struct.CustomIterator::iterator" { i32 5 }, align 4
+
+// CHECK-LABEL: define {{.*}} i32 @_Z2f1v()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %__range1 = alloca ptr, align 8
+// CHECK-NEXT: %__begin1 = alloca ptr, align 8
+// CHECK-NEXT: %__end1 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZZ2f1vE8integers, ptr %__range1, align 8
+// CHECK-NEXT: store ptr @_ZZ2f1vE8integers, ptr %__begin1, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZZ2f1vE8integers, i64 12), ptr %__end1, align 8
+// CHECK-NEXT: %0 = load i32, ptr @_ZZ2f1vE8integers, align 4
+// CHECK-NEXT: store i32 %0, ptr %x, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x, align 4
+// CHECK-NEXT: %2 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %2, %1
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: %3 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f1vE8integers, i64 1), align 4
+// CHECK-NEXT: store i32 %3, ptr %x1, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x1, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: %6 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f1vE8integers, i64 2), align 4
+// CHECK-NEXT: store i32 %6, ptr %x4, align 4
+// CHECK-NEXT: %7 = load i32, ptr %x4, align 4
+// CHECK-NEXT: %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add5 = add nsw i32 %8, %7
+// CHECK-NEXT: store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %9
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z2f2v()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %__range1 = alloca ptr, align 8
+// CHECK-NEXT: %__begin1 = alloca ptr, align 8
+// CHECK-NEXT: %__end1 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZZ2f2vE8integers, ptr %__range1, align 8
+// CHECK-NEXT: store ptr @_ZZ2f2vE8integers, ptr %__begin1, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZZ2f2vE8integers, i64 12), ptr %__end1, align 8
+// CHECK-NEXT: store i32 1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %0, 1
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: store i32 2, ptr %x1, align 4
+// CHECK-NEXT: %1 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %1, 2
+// CHECK-NEXT: store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: store i32 3, ptr %x4, align 4
+// CHECK-NEXT: %2 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add5 = add nsw i32 %2, 3
+// CHECK-NEXT: store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %3
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z2f3v()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %__range1 = alloca ptr, align 8
+// CHECK-NEXT: %__begin1 = alloca ptr, align 8
+// CHECK-NEXT: %__end1 = alloca ptr, align 8
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZZ2f3vE8integers, ptr %__range1, align 8
+// CHECK-NEXT: store ptr @_ZZ2f3vE8integers, ptr %__begin1, align 8
+// CHECK-NEXT: store ptr @_ZZ2f3vE8integers, ptr %__end1, align 8
+// CHECK-NEXT: %0 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %0
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z2f4v()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %__range1 = alloca ptr, align 8
+// CHECK-NEXT: %__begin1 = alloca ptr, align 8
+// CHECK-NEXT: %__end1 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %__range2 = alloca ptr, align 8
+// CHECK-NEXT: %__begin2 = alloca ptr, align 8
+// CHECK-NEXT: %__end2 = alloca ptr, align 8
+// CHECK-NEXT: %y = alloca i32, align 4
+// CHECK-NEXT: %y2 = alloca i32, align 4
+// CHECK-NEXT: %x6 = alloca i32, align 4
+// CHECK-NEXT: %__range27 = alloca ptr, align 8
+// CHECK-NEXT: %__begin28 = alloca ptr, align 8
+// CHECK-NEXT: %__end29 = alloca ptr, align 8
+// CHECK-NEXT: %y10 = alloca i32, align 4
+// CHECK-NEXT: %y14 = alloca i32, align 4
+// CHECK-NEXT: %__range119 = alloca ptr, align 8
+// CHECK-NEXT: %__begin120 = alloca ptr, align 8
+// CHECK-NEXT: %__end121 = alloca ptr, align 8
+// CHECK-NEXT: %x22 = alloca i32, align 4
+// CHECK-NEXT: %__range223 = alloca ptr, align 8
+// CHECK-NEXT: %__begin224 = alloca ptr, align 8
+// CHECK-NEXT: %__end225 = alloca ptr, align 8
+// CHECK-NEXT: %y26 = alloca i32, align 4
+// CHECK-NEXT: %y29 = alloca i32, align 4
+// CHECK-NEXT: %x33 = alloca i32, align 4
+// CHECK-NEXT: %__range234 = alloca ptr, align 8
+// CHECK-NEXT: %__begin235 = alloca ptr, align 8
+// CHECK-NEXT: %__end236 = alloca ptr, align 8
+// CHECK-NEXT: %y37 = alloca i32, align 4
+// CHECK-NEXT: %y40 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZZ2f4vE1a, ptr %__range1, align 8
+// CHECK-NEXT: store ptr @_ZZ2f4vE1a, ptr %__begin1, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZZ2f4vE1a, i64 8), ptr %__end1, align 8
+// CHECK-NEXT: %0 = load i32, ptr @_ZZ2f4vE1a, align 4
+// CHECK-NEXT: store i32 %0, ptr %x, align 4
+// CHECK-NEXT: store ptr @_ZZ2f4vE1b, ptr %__range2, align 8
+// CHECK-NEXT: store ptr @_ZZ2f4vE1b, ptr %__begin2, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZZ2f4vE1b, i64 8), ptr %__end2, align 8
+// CHECK-NEXT: %1 = load i32, ptr @_ZZ2f4vE1b, align 4
+// CHECK-NEXT: store i32 %1, ptr %y, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x, align 4
+// CHECK-NEXT: %3 = load i32, ptr %y, align 4
+// CHECK-NEXT: %add = add nsw i32 %2, %3
+// CHECK-NEXT: %4 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add1 = add nsw i32 %4, %add
+// CHECK-NEXT: store i32 %add1, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: %5 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f4vE1b, i64 1), align 4
+// CHECK-NEXT: store i32 %5, ptr %y2, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x, align 4
+// CHECK-NEXT: %7 = load i32, ptr %y2, align 4
+// CHECK-NEXT: %add3 = add nsw i32 %6, %7
+// CHECK-NEXT: %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add4 = add nsw i32 %8, %add3
+// CHECK-NEXT: store i32 %add4, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: br label %expand.next5
+// CHECK: expand.next5:
+// CHECK-NEXT: %9 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f4vE1a, i64 1), align 4
+// CHECK-NEXT: store i32 %9, ptr %x6, align 4
+// CHECK-NEXT: store ptr @_ZZ2f4vE1b, ptr %__range27, align 8
+// CHECK-NEXT: store ptr @_ZZ2f4vE1b, ptr %__begin28, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZZ2f4vE1b, i64 8), ptr %__end29, align 8
+// CHECK-NEXT: %10 = load i32, ptr @_ZZ2f4vE1b, align 4
+// CHECK-NEXT: store i32 %10, ptr %y10, align 4
+// CHECK-NEXT: %11 = load i32, ptr %x6, align 4
+// CHECK-NEXT: %12 = load i32, ptr %y10, align 4
+// CHECK-NEXT: %add11 = add nsw i32 %11, %12
+// CHECK-NEXT: %13 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add12 = add nsw i32 %13, %add11
+// CHECK-NEXT: store i32 %add12, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next13
+// CHECK: expand.next13:
+// CHECK-NEXT: %14 = load i32, ptr getelementptr inbounds (i32, ptr @_ZZ2f4vE1b, i64 1), align 4
+// CHECK-NEXT: store i32 %14, ptr %y14, align 4
+// CHECK-NEXT: %15 = load i32, ptr %x6, align 4
+// CHECK-NEXT: %16 = load i32, ptr %y14, align 4
+// CHECK-NEXT: %add15 = add nsw i32 %15, %16
+// CHECK-NEXT: %17 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add16 = add nsw i32 %17, %add15
+// CHECK-NEXT: store i32 %add16, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end17
+// CHECK: expand.end17:
+// CHECK-NEXT: br label %expand.end18
+// CHECK: expand.end18:
+// CHECK-NEXT: store ptr @_ZZ2f4vE1a, ptr %__range119, align 8
+// CHECK-NEXT: store ptr @_ZZ2f4vE1a, ptr %__begin120, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZZ2f4vE1a, i64 8), ptr %__end121, align 8
+// CHECK-NEXT: store i32 1, ptr %x22, align 4
+// CHECK-NEXT: store ptr @_ZZ2f4vE1b, ptr %__range223, align 8
+// CHECK-NEXT: store ptr @_ZZ2f4vE1b, ptr %__begin224, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZZ2f4vE1b, i64 8), ptr %__end225, align 8
+// CHECK-NEXT: store i32 3, ptr %y26, align 4
+// CHECK-NEXT: %18 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add27 = add nsw i32 %18, 4
+// CHECK-NEXT: store i32 %add27, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next28
+// CHECK: expand.next28:
+// CHECK-NEXT: store i32 4, ptr %y29, align 4
+// CHECK-NEXT: %19 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add30 = add nsw i32 %19, 5
+// CHECK-NEXT: store i32 %add30, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end31
+// CHECK: expand.end31:
+// CHECK-NEXT: br label %expand.next32
+// CHECK: expand.next32:
+// CHECK-NEXT: store i32 2, ptr %x33, align 4
+// CHECK-NEXT: store ptr @_ZZ2f4vE1b, ptr %__range234, align 8
+// CHECK-NEXT: store ptr @_ZZ2f4vE1b, ptr %__begin235, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZZ2f4vE1b, i64 8), ptr %__end236, align 8
+// CHECK-NEXT: store i32 3, ptr %y37, align 4
+// CHECK-NEXT: %20 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add38 = add nsw i32 %20, 5
+// CHECK-NEXT: store i32 %add38, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next39
+// CHECK: expand.next39:
+// CHECK-NEXT: store i32 4, ptr %y40, align 4
+// CHECK-NEXT: %21 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add41 = add nsw i32 %21, 6
+// CHECK-NEXT: store i32 %add41, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end42
+// CHECK: expand.end42:
+// CHECK-NEXT: br label %expand.end43
+// CHECK: expand.end43:
+// CHECK-NEXT: %22 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %22
+
+
+// CHECK-LABEL: define {{.*}} i32 @_ZN7Private11member_funcEv()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %__range1 = alloca ptr, align 8
+// CHECK-NEXT: %__begin1 = alloca ptr, align 8
+// CHECK-NEXT: %__end1 = alloca ptr, align 8
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK-NEXT: %x1 = alloca i32, align 4
+// CHECK-NEXT: %x4 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZZN7Private11member_funcEvE2p1, ptr %__range1, align 8
+// CHECK-NEXT: store ptr @_ZN7Private8integersE, ptr %__begin1, align 8
+// CHECK-NEXT: store ptr getelementptr (i8, ptr @_ZN7Private8integersE, i64 12), ptr %__end1, align 8
+// CHECK-NEXT: %0 = load i32, ptr @_ZN7Private8integersE, align 4
+// CHECK-NEXT: store i32 %0, ptr %x, align 4
+// CHECK-NEXT: %1 = load i32, ptr %x, align 4
+// CHECK-NEXT: %2 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %2, %1
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: %3 = load i32, ptr getelementptr inbounds (i32, ptr @_ZN7Private8integersE, i64 1), align 4
+// CHECK-NEXT: store i32 %3, ptr %x1, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x1, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add2 = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add2, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next3
+// CHECK: expand.next3:
+// CHECK-NEXT: %6 = load i32, ptr getelementptr inbounds (i32, ptr @_ZN7Private8integersE, i64 2), align 4
+// CHECK-NEXT: store i32 %6, ptr %x4, align 4
+// CHECK-NEXT: %7 = load i32, ptr %x4, align 4
+// CHECK-NEXT: %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add5 = add nsw i32 %8, %7
+// CHECK-NEXT: store i32 %add5, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %9
+
+
+// CHECK-LABEL: define {{.*}} i32 @_Z15custom_iteratorv()
+// CHECK: entry:
+// CHECK-NEXT: %sum = alloca i32, align 4
+// CHECK-NEXT: %__range1 = alloca ptr, align 8
+// CHECK: %__begin1 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK: %__end1 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT: %x = alloca i32, align 4
+// CHECK: %ref.tmp = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT: %x2 = alloca i32, align 4
+// CHECK: %ref.tmp3 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT: %x9 = alloca i32, align 4
+// CHECK: %ref.tmp10 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT: %x16 = alloca i32, align 4
+// CHECK: %ref.tmp17 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT: %__range122 = alloca ptr, align 8
+// CHECK: %__begin123 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK: %__end124 = alloca %"struct.CustomIterator::iterator", align 4
+// CHECK-NEXT: %x25 = alloca i32, align 4
+// CHECK-NEXT: %x28 = alloca i32, align 4
+// CHECK-NEXT: %x31 = alloca i32, align 4
+// CHECK-NEXT: %x34 = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %sum, align 4
+// CHECK-NEXT: store ptr @_ZZ15custom_iteratorvE1c, ptr %__range1, align 8
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %__begin1, ptr align 4 @__const._Z15custom_iteratorv.__begin1, i64 4, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %__end1, ptr align 4 @__const._Z15custom_iteratorv.__end1, i64 4, i1 false)
+// CHECK-NEXT: %call = call i32 @_ZNK14CustomIterator8iteratorplEi(ptr {{.*}} %__begin1, i32 {{.*}} 0)
+// CHECK: %coerce.dive = getelementptr inbounds nuw %"struct.CustomIterator::iterator", ptr %ref.tmp, i32 0, i32 0
+// CHECK-NEXT: store i32 %call, ptr %coerce.dive, align 4
+// CHECK-NEXT: %call1 = call {{.*}} i32 @_ZNK14CustomIterator8iteratordeEv(ptr {{.*}} %ref.tmp)
+// CHECK-NEXT: store i32 %call1, ptr %x, align 4
+// CHECK-NEXT: %0 = load i32, ptr %x, align 4
+// CHECK-NEXT: %1 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add = add nsw i32 %1, %0
+// CHECK-NEXT: store i32 %add, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next
+// CHECK: expand.next:
+// CHECK-NEXT: %call4 = call i32 @_ZNK14CustomIterator8iteratorplEi(ptr {{.*}} %__begin1, i32 {{.*}} 1)
+// CHECK: %coerce.dive5 = getelementptr inbounds nuw %"struct.CustomIterator::iterator", ptr %ref.tmp3, i32 0, i32 0
+// CHECK-NEXT: store i32 %call4, ptr %coerce.dive5, align 4
+// CHECK-NEXT: %call6 = call {{.*}} i32 @_ZNK14CustomIterator8iteratordeEv(ptr {{.*}} %ref.tmp3)
+// CHECK-NEXT: store i32 %call6, ptr %x2, align 4
+// CHECK-NEXT: %2 = load i32, ptr %x2, align 4
+// CHECK-NEXT: %3 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add7 = add nsw i32 %3, %2
+// CHECK-NEXT: store i32 %add7, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next8
+// CHECK: expand.next8:
+// CHECK-NEXT: %call11 = call i32 @_ZNK14CustomIterator8iteratorplEi(ptr {{.*}} %__begin1, i32 {{.*}} 2)
+// CHECK: %coerce.dive12 = getelementptr inbounds nuw %"struct.CustomIterator::iterator", ptr %ref.tmp10, i32 0, i32 0
+// CHECK-NEXT: store i32 %call11, ptr %coerce.dive12, align 4
+// CHECK-NEXT: %call13 = call {{.*}} i32 @_ZNK14CustomIterator8iteratordeEv(ptr {{.*}} %ref.tmp10)
+// CHECK-NEXT: store i32 %call13, ptr %x9, align 4
+// CHECK-NEXT: %4 = load i32, ptr %x9, align 4
+// CHECK-NEXT: %5 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add14 = add nsw i32 %5, %4
+// CHECK-NEXT: store i32 %add14, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next15
+// CHECK: expand.next15:
+// CHECK-NEXT: %call18 = call i32 @_ZNK14CustomIterator8iteratorplEi(ptr {{.*}} %__begin1, i32 {{.*}} 3)
+// CHECK: %coerce.dive19 = getelementptr inbounds nuw %"struct.CustomIterator::iterator", ptr %ref.tmp17, i32 0, i32 0
+// CHECK-NEXT: store i32 %call18, ptr %coerce.dive19, align 4
+// CHECK-NEXT: %call20 = call {{.*}} i32 @_ZNK14CustomIterator8iteratordeEv(ptr {{.*}} %ref.tmp17)
+// CHECK-NEXT: store i32 %call20, ptr %x16, align 4
+// CHECK-NEXT: %6 = load i32, ptr %x16, align 4
+// CHECK-NEXT: %7 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add21 = add nsw i32 %7, %6
+// CHECK-NEXT: store i32 %add21, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end
+// CHECK: expand.end:
+// CHECK-NEXT: store ptr @_ZZ15custom_iteratorvE1c, ptr %__range122, align 8
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %__begin123, ptr align 4 @__const._Z15custom_iteratorv.__begin1.1, i64 4, i1 false)
+// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %__end124, ptr align 4 @__const._Z15custom_iteratorv.__end1.2, i64 4, i1 false)
+// CHECK-NEXT: store i32 1, ptr %x25, align 4
+// CHECK-NEXT: %8 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add26 = add nsw i32 %8, 1
+// CHECK-NEXT: store i32 %add26, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next27
+// CHECK: expand.next27:
+// CHECK-NEXT: store i32 2, ptr %x28, align 4
+// CHECK-NEXT: %9 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add29 = add nsw i32 %9, 2
+// CHECK-NEXT: store i32 %add29, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next30
+// CHECK: expand.next30:
+// CHECK-NEXT: store i32 3, ptr %x31, align 4
+// CHECK-NEXT: %10 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add32 = add nsw i32 %10, 3
+// CHECK-NEXT: store i32 %add32, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.next33
+// CHECK: expand.next33:
+// CHECK-NEXT: store i32 4, ptr %x34, align 4
+// CHECK-NEXT: %11 = load i32, ptr %sum, align 4
+// CHECK-NEXT: %add35 = add nsw i32 %11, 4
+// CHECK-NEXT: store i32 %add35, ptr %sum, align 4
+// CHECK-NEXT: br label %expand.end36
+// CHECK: expand.end36:
+// CHECK-NEXT: %12 = load i32, ptr %sum, align 4
+// CHECK-NEXT: ret i32 %12
More information about the llvm-branch-commits
mailing list