[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