Skip to content

Commit

Permalink
[CIR][CIRGen] Add initial CIRGen support for local temporary material…
Browse files Browse the repository at this point in the history
…ization (#820)

This PR adds initial support for temporary materialization of local
temporaries with trivial cleanups.

Materialization of global temporaries and local temporaries with
non-trivial cleanups is far more trickier that I initially thought and I
decide to submit this easy part first.
  • Loading branch information
Lancern authored Sep 9, 2024
1 parent 987f1e1 commit 97357e1
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 8 deletions.
28 changes: 22 additions & 6 deletions clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2146,8 +2146,22 @@ static Address createReferenceTemporary(CIRGenFunction &CGF,
(Ty->isArrayType() || Ty->isRecordType()) &&
CGF.CGM.isTypeConstant(Ty, /*ExcludeCtor=*/true, /*ExcludeDtor=*/false))
assert(0 && "NYI");

// The temporary memory should be created in the same scope as the extending
// declaration of the temporary materialization expression.
mlir::cir::AllocaOp extDeclAlloca;
if (const clang::ValueDecl *extDecl = M->getExtendingDecl()) {
auto extDeclAddrIter = CGF.LocalDeclMap.find(extDecl);
if (extDeclAddrIter != CGF.LocalDeclMap.end()) {
extDeclAlloca = dyn_cast_if_present<mlir::cir::AllocaOp>(
extDeclAddrIter->second.getDefiningOp());
}
}
mlir::OpBuilder::InsertPoint ip;
if (extDeclAlloca)
ip = {extDeclAlloca->getBlock(), extDeclAlloca->getIterator()};
return CGF.CreateMemTemp(Ty, CGF.getLoc(M->getSourceRange()),
CGF.getCounterRefTmpAsString(), Alloca);
CGF.getCounterRefTmpAsString(), Alloca, ip);
}
case SD_Thread:
case SD_Static:
Expand Down Expand Up @@ -2245,7 +2259,7 @@ LValue CIRGenFunction::buildMaterializeTemporaryExpr(
} else {
switch (M->getStorageDuration()) {
case SD_Automatic:
assert(0 && "NYI");
assert(!MissingFeatures::shouldEmitLifetimeMarkers());
break;

case SD_FullExpression: {
Expand Down Expand Up @@ -2932,18 +2946,20 @@ void CIRGenFunction::buildUnreachable(SourceLocation Loc) {
//===----------------------------------------------------------------------===//

Address CIRGenFunction::CreateMemTemp(QualType Ty, mlir::Location Loc,
const Twine &Name, Address *Alloca) {
const Twine &Name, Address *Alloca,
mlir::OpBuilder::InsertPoint ip) {
// FIXME: Should we prefer the preferred type alignment here?
return CreateMemTemp(Ty, getContext().getTypeAlignInChars(Ty), Loc, Name,
Alloca);
Alloca, ip);
}

Address CIRGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
mlir::Location Loc, const Twine &Name,
Address *Alloca) {
Address *Alloca,
mlir::OpBuilder::InsertPoint ip) {
Address Result =
CreateTempAlloca(getTypes().convertTypeForMem(Ty), Align, Loc, Name,
/*ArraySize=*/nullptr, Alloca);
/*ArraySize=*/nullptr, Alloca, ip);
if (Ty->isConstantMatrixType()) {
assert(0 && "NYI");
}
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2215,9 +2215,11 @@ class CIRGenFunction : public CIRGenTypeCache {
/// appropriate alignmen and cast it to the default address space. Returns
/// the original alloca instruction by \p Alloca if it is not nullptr.
Address CreateMemTemp(QualType T, mlir::Location Loc,
const Twine &Name = "tmp", Address *Alloca = nullptr);
const Twine &Name = "tmp", Address *Alloca = nullptr,
mlir::OpBuilder::InsertPoint ip = {});
Address CreateMemTemp(QualType T, CharUnits Align, mlir::Location Loc,
const Twine &Name = "tmp", Address *Alloca = nullptr);
const Twine &Name = "tmp", Address *Alloca = nullptr,
mlir::OpBuilder::InsertPoint ip = {});

/// Create a temporary memory object of the given type, with
/// appropriate alignment without casting it to the default address space.
Expand Down
43 changes: 43 additions & 0 deletions clang/test/CIR/CodeGen/temporary-materialization.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

int make_int();

int test() {
const int &x = make_int();
return x;
}

// CHECK: cir.func @_Z4testv()
// CHECK-NEXT: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
// CHECK-NEXT: %[[#TEMP_SLOT:]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init] {alignment = 4 : i64}
// CHECK-NEXT: %[[#x:]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["x", init] {alignment = 8 : i64}
// CHECK-NEXT: cir.scope {
// CHECK-NEXT: %[[#TEMP_VALUE:]] = cir.call @_Z8make_intv() : () -> !s32i
// CHECK-NEXT: cir.store %[[#TEMP_VALUE]], %[[#TEMP_SLOT]] : !s32i, !cir.ptr<!s32i>
// CHECK-NEXT: }
// CHECK-NEXT: cir.store %[[#TEMP_SLOT]], %[[#x]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CHECK: }

int test_scoped() {
int x = make_int();
{
const int &y = make_int();
x = y;
}
return x;
}

// CHECK: cir.func @_Z11test_scopedv()
// CHECK-NEXT: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
// CHECK-NEXT: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
// CHECK: cir.scope {
// CHECK-NEXT: %[[#TEMP_SLOT:]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init] {alignment = 4 : i64}
// CHECK-NEXT: %[[#y:]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["y", init] {alignment = 8 : i64}
// CHECK-NEXT: cir.scope {
// CHECK-NEXT: %[[#TEMP_VALUE:]] = cir.call @_Z8make_intv() : () -> !s32i
// CHECK-NEXT: cir.store %[[#TEMP_VALUE]], %[[#TEMP_SLOT]] : !s32i, !cir.ptr<!s32i>
// CHECK-NEXT: }
// CHECK-NEXT: cir.store %[[#TEMP_SLOT]], %[[#y]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CHECK: }
// CHECK: }

0 comments on commit 97357e1

Please sign in to comment.