[clang] [CIR] Set dead_on_return for non-byval indirect arguments (PR #234773)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 22 14:48:07 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Andy Kaylor (andykaylor)
<details>
<summary>Changes</summary>
This change updates the CIR calling convention rewrite context to set the dead_on_return attribute when lowering non-byval indirect arguments to match the behavior of classic codegen.
Assisted-by: Cursor / various models
---
Patch is 47.48 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/234773.diff
9 Files Affected:
- (modified) clang/include/clang/CIR/MissingFeatures.h (-1)
- (modified) clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp (+18-9)
- (modified) clang/test/CIR/CodeGen/attr-noundef.cpp (+6-8)
- (modified) clang/test/CIR/CodeGen/call-conv-lowering-x86_64-non-byval.cpp (+2-3)
- (modified) clang/test/CIR/CodeGen/call-conv-lowering-x86_64-vptr.cpp (+18-26)
- (modified) clang/test/CIR/Transforms/abi-lowering/byval-sret-arg-attr-lowering.cir (+2-2)
- (modified) clang/test/CIR/Transforms/abi-lowering/indirect-byval.cir (+13-13)
- (modified) clang/test/CIR/Transforms/abi-lowering/indirect-non-byval-forward-param.cir (+37-37)
- (modified) clang/test/CIR/Transforms/abi-lowering/x86_64-vptr.cir (+2-2)
``````````diff
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index 570660038982a0..9bd951999b1e31 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -217,7 +217,6 @@ struct MissingFeatures {
static bool hipModuleCtor() { return false; }
static bool dataLayoutTypeAllocSize() { return false; }
static bool dataLayoutPtrHandlingBasedOnLangAS() { return false; }
- static bool deadOnReturnAttr() { return false; }
static bool noaliasOnByvalAttr() { return false; }
static bool deferredCXXGlobalInit() { return false; }
static bool deleteArray() { return false; }
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp
index 46e06b814776f3..c85f5421c21050 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp
@@ -17,6 +17,7 @@
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/Attributes.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <array>
@@ -218,7 +219,7 @@ static bool needsArgAttrUpdate(const FunctionClassification &fc) {
/// of an Expand argument an empty dict. Direct and Extend slots keep their
/// other existing attributes. \p origArgTypes provides the pre-rewrite type
/// for each arg slot.
-mlir::ArrayAttr updateArgAttrs(mlir::MLIRContext *ctx,
+mlir::ArrayAttr updateArgAttrs(mlir::MLIRContext *ctx, mlir::ModuleOp module,
ArrayRef<mlir::Type> origArgTypes,
mlir::ArrayAttr existingArgAttrs,
const FunctionClassification &fc,
@@ -279,12 +280,19 @@ mlir::ArrayAttr updateArgAttrs(mlir::MLIRContext *ctx,
} else {
// llvm.nofreeobj says the object cannot be freed while the callee
// runs, which holds because the caller owns it across the call.
- // Classic adds llvm.dead_on_return when the object's lifetime ends in
- // the callee, which needs the destructor's triviality from
- // cir.record_layout's has_trivial_dtor.
- assert(!cir::MissingFeatures::deadOnReturnAttr());
attrs.set(mlir::LLVM::LLVMDialect::getNoFreeObjAttrName(),
builder.getUnitAttr());
+ // llvm.dead_on_return says the object's lifetime ends in the callee,
+ // which holds unless the caller still has a destructor to run on it.
+ // A record with no layout entry has no destructor.
+ auto recTy = mlir::dyn_cast<cir::RecordType>(pointeeTy);
+ cir::RecordLayoutAttr layout =
+ recTy ? cir::tryGetRecordLayout(module, recTy.getName())
+ : cir::RecordLayoutAttr();
+ if (!layout || layout.getHasTrivialDtor())
+ attrs.set(mlir::LLVM::LLVMDialect::getDeadOnReturnAttrName(),
+ builder.getI64IntegerAttr(static_cast<int64_t>(
+ llvm::DeadOnReturnInfo().toIntValue())));
attrs.set(mlir::LLVM::LLVMDialect::getDereferenceableAttrName(),
builder.getI64IntegerAttr(
dl.getTypeSize(pointeeTy).getFixedValue()));
@@ -1568,7 +1576,8 @@ mlir::LogicalResult rewriteIndirectReturnCall(
// every argument classification.
mlir::ArrayAttr argAttrs = call->getAttrOfType<mlir::ArrayAttr>("arg_attrs");
if (needsArgAttrUpdate(fc))
- argAttrs = updateArgAttrs(ctx, origCallArgTypes, argAttrs, fc, dl);
+ argAttrs = updateArgAttrs(ctx, call->getParentOfType<mlir::ModuleOp>(),
+ origCallArgTypes, argAttrs, fc, dl);
applySretSlotAttrs(newCall, argAttrs, origRetTy, sretAlign, builder);
if (reuseStore) {
@@ -1920,7 +1929,7 @@ mlir::LogicalResult CIRABIRewriteContext::rewriteFunctionDefinition(
if (hasSRet || needsArgAttrUpdate(fc)) {
auto existing = funcOp->getAttrOfType<mlir::ArrayAttr>("arg_attrs");
mlir::ArrayAttr updated =
- updateArgAttrs(ctx, oldArgTypes, existing, fc, dl);
+ updateArgAttrs(ctx, module, oldArgTypes, existing, fc, dl);
if (hasSRet) {
// Prepend the sret slot's attribute dict (slot 0); the per-argument
// dicts shift to slots 1..N. noalias is valid only on the callee's
@@ -2227,8 +2236,8 @@ CIRABIRewriteContext::rewriteCallSite(mlir::Operation *callOp,
if (needsArgAttrUpdate(fc)) {
auto existing = call->getAttrOfType<mlir::ArrayAttr>("arg_attrs");
- newCall->setAttr("arg_attrs",
- updateArgAttrs(ctx, origCallArgTypes, existing, fc, dl));
+ newCall->setAttr("arg_attrs", updateArgAttrs(ctx, module, origCallArgTypes,
+ existing, fc, dl));
}
// Add llvm.signext / llvm.zeroext to an Extend return, and drop llvm.noundef
// from a coerced Direct return that passes undefined bits.
diff --git a/clang/test/CIR/CodeGen/attr-noundef.cpp b/clang/test/CIR/CodeGen/attr-noundef.cpp
index 3600d0105c19eb..0ab9639b7dca62 100644
--- a/clang/test/CIR/CodeGen/attr-noundef.cpp
+++ b/clang/test/CIR/CodeGen/attr-noundef.cpp
@@ -1,9 +1,9 @@
// RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
// RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -fclangir -emit-llvm %s -o %t-cir.ll
-// RUN: FileCheck --check-prefixes=LLVM,LLVMCIR --input-file=%t-cir.ll %s
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
// RUN: %clang_cc1 -triple x86_64-gnu-linux -x c++ -emit-llvm %s -o %t.ll
-// RUN: FileCheck --check-prefixes=LLVM,OGCG --input-file=%t.ll %s
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
// All cases from CodeGen/attr-noundef.cpp (x86_64 only).
// Tests noundef placement on structs, unions, this pointers, vectors,
@@ -32,11 +32,10 @@ NoCopy ret_nocopy() { return {}; }
void pass_nocopy(NoCopy e) {}
// CIR-LABEL: cir.func {{.*}} @_ZN13check_structs10ret_nocopyEv
-// CIR-LABEL: cir.func {{.*}} @_ZN13check_structs11pass_nocopyENS_6NoCopyE(%arg0: !cir.ptr<!rec_check_structs3A3ANoCopy> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, llvm.nofreeobj, llvm.noundef}
+// CIR-LABEL: cir.func {{.*}} @_ZN13check_structs11pass_nocopyENS_6NoCopyE(%arg0: !cir.ptr<!rec_check_structs3A3ANoCopy> {llvm.align = 4 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 4 : i64, llvm.nofreeobj, llvm.noundef}
// LLVM: define dso_local void @_ZN13check_structs10ret_nocopyEv(ptr dead_on_unwind noalias writable sret(%"struct.check_structs::NoCopy") align 4 %
-// LLVMCIR: define dso_local void @_ZN13check_structs11pass_nocopyENS_6NoCopyE(ptr nofreeobj noundef align 4 dereferenceable(4) %
-// OGCG: define dso_local void @_ZN13check_structs11pass_nocopyENS_6NoCopyE(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(4) %
+// LLVM: define dso_local void @_ZN13check_structs11pass_nocopyENS_6NoCopyE(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(4) %
struct Huge {
int a[1024];
@@ -74,11 +73,10 @@ NoCopy ret_nocopy() { return {}; }
void pass_nocopy(NoCopy e) {}
// CIR-LABEL: cir.func {{.*}} @_ZN12check_unions10ret_nocopyEv
-// CIR-LABEL: cir.func {{.*}} @_ZN12check_unions11pass_nocopyENS_6NoCopyE(%arg0: !cir.ptr<!rec_check_unions3A3ANoCopy> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, llvm.nofreeobj, llvm.noundef}
+// CIR-LABEL: cir.func {{.*}} @_ZN12check_unions11pass_nocopyENS_6NoCopyE(%arg0: !cir.ptr<!rec_check_unions3A3ANoCopy> {llvm.align = 4 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 4 : i64, llvm.nofreeobj, llvm.noundef}
// LLVM: define dso_local void @_ZN12check_unions10ret_nocopyEv(ptr dead_on_unwind noalias writable sret(%"union.check_unions::NoCopy") align 4 %
-// LLVMCIR: define dso_local void @_ZN12check_unions11pass_nocopyENS_6NoCopyE(ptr nofreeobj noundef align 4 dereferenceable(4) %
-// OGCG: define dso_local void @_ZN12check_unions11pass_nocopyENS_6NoCopyE(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(4) %
+// LLVM: define dso_local void @_ZN12check_unions11pass_nocopyENS_6NoCopyE(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(4) %
} // namespace check_unions
//************ Passing `this` pointers
diff --git a/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-non-byval.cpp b/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-non-byval.cpp
index 13b1a8ba181c10..9e9ddfc405734f 100644
--- a/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-non-byval.cpp
+++ b/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-non-byval.cpp
@@ -84,13 +84,12 @@ void callCopyCtorNonByval() {
// CIR: cir.call @_ZN12WithCopyCtorC1Ev(%[[C]])
// CIR: cir.call @_ZN12WithCopyCtorC1ERKS_(%[[TMP]], %[[C]])
// CIR-NOT: cir.load
-// CIR: cir.call @_Z20takeCopyCtorNonByval12WithCopyCtor(%[[TMP]]) : (!cir.ptr<!rec_WithCopyCtor> {llvm.align = 4 : i64, llvm.dereferenceable = 4 : i64, llvm.nofreeobj, llvm.noundef}) -> ()
+// CIR: cir.call @_Z20takeCopyCtorNonByval12WithCopyCtor(%[[TMP]]) : (!cir.ptr<!rec_WithCopyCtor> {llvm.align = 4 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 4 : i64, llvm.nofreeobj, llvm.noundef}) -> ()
// LLVM-LABEL: define dso_local void @_Z20callCopyCtorNonByvalv()
// LLVM: call void @_ZN12WithCopyCtorC1Ev(ptr noundef nonnull align 4 dereferenceable(4) %[[C:[^)]+]])
// LLVM: call void @_ZN12WithCopyCtorC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) %[[TMP:[^,]+]], ptr noundef nonnull align 4 dereferenceable(4) %[[C]])
-// LLVM-CIR: call void @_Z20takeCopyCtorNonByval12WithCopyCtor(ptr nofreeobj noundef align 4 dereferenceable(4) %[[TMP]])
-// OGCG: call void @_Z20takeCopyCtorNonByval12WithCopyCtor(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(4) %[[TMP]])
+// LLVM: call void @_Z20takeCopyCtorNonByval12WithCopyCtor(ptr nofreeobj noundef align 4 dead_on_return dereferenceable(4) %[[TMP]])
// The materialized temporary is the operand's storage, so it is handed on as
// the byval pointer with no slot of its own.
diff --git a/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-vptr.cpp b/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-vptr.cpp
index e55fca949bc14d..243dad1508d121 100644
--- a/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-vptr.cpp
+++ b/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-vptr.cpp
@@ -3,9 +3,9 @@
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir \
// RUN: -fclangir-call-conv-lowering -emit-llvm %s -o %t-cir.ll
-// RUN: FileCheck --check-prefixes=LLVM,LLVM-CIR --input-file=%t-cir.ll %s
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm %s -o %t.ll
-// RUN: FileCheck --check-prefixes=LLVM,LLVM-OGCG --input-file=%t.ll %s
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
struct Poly { virtual void f(); };
struct PolyLong { virtual void f(); long x; };
@@ -20,54 +20,47 @@ struct VirtInherit : virtual VBase { long b; };
// passed by invisible reference whatever its eightbytes classify as.
int takePoly(Poly v, int k) { return k; }
-// CIR: cir.func {{.*}}@_Z8takePoly4Polyi(%arg0: !cir.ptr<!rec_Poly> {llvm.align = 8 : i64, llvm.dereferenceable = 8 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}, %arg1: !s32i {{.*}}) -> (!s32i
-// LLVM-CIR: define dso_local noundef i32 @_Z8takePoly4Polyi(ptr nofreeobj noundef align 8 dereferenceable(8) %{{[^,]+}}, i32 noundef %{{[^,)]+}})
-// LLVM-OGCG: define dso_local noundef i32 @_Z8takePoly4Polyi(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(8) %{{[^,]+}}, i32 noundef %{{[^,)]+}})
+// CIR: cir.func {{.*}}@_Z8takePoly4Polyi(%arg0: !cir.ptr<!rec_Poly> {llvm.align = 8 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 8 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}, %arg1: !s32i {{.*}}) -> (!s32i
+// LLVM: define dso_local noundef i32 @_Z8takePoly4Polyi(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(8) %{{[^,]+}}, i32 noundef %{{[^,)]+}})
int takePolyLong(PolyLong v) { return 0; }
-// CIR: cir.func {{.*}}@_Z12takePolyLong8PolyLong(%arg0: !cir.ptr<!rec_PolyLong> {llvm.align = 8 : i64, llvm.dereferenceable = 16 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
-// LLVM-CIR: define dso_local noundef i32 @_Z12takePolyLong8PolyLong(ptr nofreeobj noundef align 8 dereferenceable(16) %{{[^,)]+}})
-// LLVM-OGCG: define dso_local noundef i32 @_Z12takePolyLong8PolyLong(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(16) %{{[^,)]+}})
+// CIR: cir.func {{.*}}@_Z12takePolyLong8PolyLong(%arg0: !cir.ptr<!rec_PolyLong> {llvm.align = 8 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 16 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
+// LLVM: define dso_local noundef i32 @_Z12takePolyLong8PolyLong(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(16) %{{[^,)]+}})
// The copy constructor decides this, so it does not matter what the members
// would have classified as on their own.
int takePolyTwoInt(PolyTwoInt v) { return v.y; }
-// CIR: cir.func {{.*}}@_Z14takePolyTwoInt10PolyTwoInt(%arg0: !cir.ptr<!rec_PolyTwoInt> {llvm.align = 8 : i64, llvm.dereferenceable = 16 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
-// LLVM-CIR: define dso_local noundef i32 @_Z14takePolyTwoInt10PolyTwoInt(ptr nofreeobj noundef align 8 dereferenceable(16) %{{[^,)]+}})
-// LLVM-OGCG: define dso_local noundef i32 @_Z14takePolyTwoInt10PolyTwoInt(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(16) %{{[^,)]+}})
+// CIR: cir.func {{.*}}@_Z14takePolyTwoInt10PolyTwoInt(%arg0: !cir.ptr<!rec_PolyTwoInt> {llvm.align = 8 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 16 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
+// LLVM: define dso_local noundef i32 @_Z14takePolyTwoInt10PolyTwoInt(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(16) %{{[^,)]+}})
// Past two eightbytes SysV says memory on its own, so the two rules agree here.
int takePolyBig(PolyBig v) { return 0; }
-// CIR: cir.func {{.*}}@_Z11takePolyBig7PolyBig(%arg0: !cir.ptr<!rec_PolyBig> {llvm.align = 8 : i64, llvm.dereferenceable = 24 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
-// LLVM-CIR: define dso_local noundef i32 @_Z11takePolyBig7PolyBig(ptr nofreeobj noundef align 8 dereferenceable(24) %{{[^,)]+}})
-// LLVM-OGCG: define dso_local noundef i32 @_Z11takePolyBig7PolyBig(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(24) %{{[^,)]+}})
+// CIR: cir.func {{.*}}@_Z11takePolyBig7PolyBig(%arg0: !cir.ptr<!rec_PolyBig> {llvm.align = 8 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 24 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
+// LLVM: define dso_local noundef i32 @_Z11takePolyBig7PolyBig(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(24) %{{[^,)]+}})
// The vtable pointer is inherited through the base subobject rather than
// declared here.
int takePolyDerived(PolyDerived v) { return 0; }
-// CIR: cir.func {{.*}}@_Z15takePolyDerived11PolyDerived(%arg0: !cir.ptr<!rec_PolyDerived> {llvm.align = 8 : i64, llvm.dereferenceable = 24 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
-// LLVM-CIR: define dso_local noundef i32 @_Z15takePolyDerived11PolyDerived(ptr nofreeobj noundef align 8 dereferenceable(24) %{{[^,)]+}})
-// LLVM-OGCG: define dso_local noundef i32 @_Z15takePolyDerived11PolyDerived(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(24) %{{[^,)]+}})
+// CIR: cir.func {{.*}}@_Z15takePolyDerived11PolyDerived(%arg0: !cir.ptr<!rec_PolyDerived> {llvm.align = 8 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 24 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
+// LLVM: define dso_local noundef i32 @_Z15takePolyDerived11PolyDerived(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(24) %{{[^,)]+}})
// HasPoly declares no virtual function of its own, but its member carries the
// vtable pointer and the non-trivial copy constructor with it.
int takeHasPoly(HasPoly v) { return 0; }
-// CIR: cir.func {{.*}}@_Z11takeHasPoly7HasPoly(%arg0: !cir.ptr<!rec_HasPoly> {llvm.align = 8 : i64, llvm.dereferenceable = 16 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
-// LLVM-CIR: define dso_local noundef i32 @_Z11takeHasPoly7HasPoly(ptr nofreeobj noundef align 8 dereferenceable(16) %{{[^,)]+}})
-// LLVM-OGCG: define dso_local noundef i32 @_Z11takeHasPoly7HasPoly(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(16) %{{[^,)]+}})
+// CIR: cir.func {{.*}}@_Z11takeHasPoly7HasPoly(%arg0: !cir.ptr<!rec_HasPoly> {llvm.align = 8 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 16 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
+// LLVM: define dso_local noundef i32 @_Z11takeHasPoly7HasPoly(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(16) %{{[^,)]+}})
// A virtual base gives the class a vtable pointer for the base offset even
// though it declares no virtual function of its own.
int takeVirtInherit(VirtInherit v) { return 0; }
-// CIR: cir.func {{.*}}@_Z15takeVirtInherit11VirtInherit(%arg0: !cir.ptr<!rec_VirtInherit> {llvm.align = 8 : i64, llvm.dereferenceable = 24 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
-// LLVM-CIR: define dso_local noundef i32 @_Z15takeVirtInherit11VirtInherit(ptr nofreeobj noundef align 8 dereferenceable(24) %{{[^,)]+}})
-// LLVM-OGCG: define dso_local noundef i32 @_Z15takeVirtInherit11VirtInherit(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(24) %{{[^,)]+}})
+// CIR: cir.func {{.*}}@_Z15takeVirtInherit11VirtInherit(%arg0: !cir.ptr<!rec_VirtInherit> {llvm.align = 8 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 24 : i64, llvm.nofreeobj, llvm.noundef}{{.*}}) -> (!s32i
+// LLVM: define dso_local noundef i32 @_Z15takeVirtInherit11VirtInherit(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(24) %{{[^,)]+}})
// Returning the class writes through an sret slot the caller supplies.
PolyLong makePolyLong() {
@@ -87,11 +80,10 @@ int caller(int k) {
// CIR: cir.func {{.*}}@_Z6calleri(%arg0: !s32i {{.*}}) -> (!s32i
// CIR: cir.call @_Z11retPolyLongv(%{{[0-9]+}}) : (!cir.ptr<!rec_PolyLong> {llvm.align = 8 : i64, llvm.dead_on_unwind, llvm.sret = !rec_PolyLong, llvm.writable}) -> ()
-// CIR: cir.call @_Z12takePolyLong8PolyLong(%{{[0-9]+}}) : (!cir.ptr<!rec_PolyLong> {llvm.align = 8 : i64, llvm.dereferenceable = 16 : i64, llvm.nofreeobj, llvm.noundef}) -> (!s32i
+// CIR: cir.call @_Z12takePolyLong8PolyLong(%{{[0-9]+}}) : (!cir.ptr<!rec_PolyLong> {llvm.align = 8 : i64, llvm.dead_on_return = -1 : i64, llvm.dereferenceable = 16 : i64, llvm.nofreeobj, llvm.noundef}) -> (!s32i
// LLVM: define dso_local noundef i32 @_Z6calleri(i32 noundef %{{[^,)]+}})
// LLVM: call void @_Z11retPolyLongv(ptr dead_on_unwind writable sret(%struct.PolyLong) align 8 %{{[^,)]+}})
-// LLVM-CIR: call noundef i32 @_Z12takePolyLong8PolyLong(ptr nofreeobj noundef align 8 dereferenceable(16) %{{[^,)]+}})
-// LLVM-OGCG: call noundef i32 @_Z12takePolyLong8PolyLong(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(16) %{{[^,)]+}})
+// LLVM: call noundef i32 @_Z12takePolyLong8PolyLong(ptr nofreeobj noundef align 8 dead_on_return dereferenceable(16) %{{[^,)]+}})
// Returned, the class uses sret at its declared alignment.
// CIR: cir.func private @_Z11retPolyLongv(!cir.ptr<!rec_PolyLong> {llvm.align = 8 : i64, llvm.dead_on_unwind, llvm.sret = !rec_PolyLong, llvm.writable})
diff --git a/clang/test/CIR/Transforms/abi-lowering/byval-sret-arg-attr-lowering.cir b/clang/test/CIR/Transforms/abi-lowering/byval-sret-arg-attr-lowering.cir
index b0df1caa5416b4..85c0660db03333 100644
--- a/clang/test/CIR/Transforms/abi-lowering/byval-sret-arg-attr-lowering.cir
+++ b/clang/test/CIR/Transforms/abi-lowering/byval-sret-arg-attr-lowering.cir
@@ -61,8 +61,8 @@ module attributes {
cir.return
}
- // CHECK: cir.func{{.*}} @takes_non_byval(%{{.*}}: !cir.ptr<!rec_Big> {{{.*}}llvm.dereferenceable = 24 : i64, llvm.nofreeobj, llvm.noundef{{.*}}})
- // LLVM: define void @takes_non_byval(ptr nof...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/234773
More information about the cfe-commits
mailing list