llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen Author: None (Sirraide) <details> <summary>Changes</summary> This implements codegen for expansion statements and adds some codegen tests. --- Patch is 134.02 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169687.diff 7 Files Affected: - (modified) clang/lib/CodeGen/CGStmt.cpp (+46) - (modified) clang/lib/CodeGen/CodeGenFunction.h (+3) - (added) clang/test/CodeGenCXX/cxx2c-destructuring-expansion-stmt.cpp (+471) - (added) clang/test/CodeGenCXX/cxx2c-enumerating-expansion-statements.cpp (+1518) - (added) clang/test/CodeGenCXX/cxx2c-expansion-stmts-control-flow.cpp (+429) - (added) clang/test/CodeGenCXX/cxx2c-expansion-stmts-templates.cpp (+208) - (added) clang/test/CodeGenCXX/cxx2c-iterating-expansion-stmt.cpp (+474) ``````````diff 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 +// CHEC... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/169687 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
