https://github.com/erichkeane updated 
https://github.com/llvm/llvm-project/pull/197252

>From 583ac7a8f7cd7432301bd5d01b325e62edd43dea Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Tue, 12 May 2026 09:18:56 -0700
Subject: [PATCH 1/2] [CIR] Lower builtin_launder

This patch introduces a cir.launder operation to represent a call to
__builtin_launder, which is an optimization barrier. This cir.launder
lowers directly to the LLVM-IR launder.invariant.group.

This patch also moves the existing check to see if a type needs
laundering to QualType from classic-codegen so it can be shared, however
the CodeGenOpt check is still left in codegen/duplicated between the two
implementations.
---
 clang/include/clang/AST/TypeBase.h            |   4 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  26 ++++
 clang/lib/AST/Type.cpp                        |  32 +++++
 clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp       |  13 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |   8 ++
 clang/lib/CodeGen/CGBuiltin.cpp               |  30 +----
 clang/test/CIR/CodeGen/launder.cpp            | 119 ++++++++++++++++++
 7 files changed, 202 insertions(+), 30 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/launder.cpp

diff --git a/clang/include/clang/AST/TypeBase.h 
b/clang/include/clang/AST/TypeBase.h
index b2887bcc36246..e90aa9fb09012 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -1160,6 +1160,10 @@ class QualType {
   /// Returns true if it is a OverflowBehaviorType of Trap kind.
   bool isTrapType() const;
 
+  /// Returns true if this type requires laundering by checking if it is a
+  /// dynamic class type, or contains a subobject which is a dynamic class 
type.
+  bool requiresBuiltinLaunder(const ASTContext &Context) const;
+
   // Don't promise in the API that anything besides 'const' can be
   // easily added.
 
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 9d9aaec1b275a..6415b19058397 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -8178,4 +8178,30 @@ def CIR_MemChrOp : CIR_Op<"libc.memchr"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// LaunderOp
+//===----------------------------------------------------------------------===//
+
+def CIR_LaunderOp : CIR_Op<"launder", [SameOperandsAndResultType]> {
+  let summary = "Launder operation";
+  let description = [{
+    This operation represents a call to 'launder' in C++,
+    which acts as an optimization boundary that breaks type invariance.
+
+  Example:
+  ```
+    %0 = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>
+    %1 = cir.load align(8) %1 : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
+    %2 = cir.launder(%1) : !cir.ptr<!rec_S>
+  ```
+  }];
+
+  let arguments = (ins CIR_PointerType:$arg);
+  let results = (outs CIR_PointerType:$result);
+
+  let assemblyFormat = [{
+    `(` $arg `)` `:` qualified(type($result)) attr-dict
+  }];
+}
+
 #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index ca13f8f4fcfee..0c987bbf6d731 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -5558,6 +5558,38 @@ QualType::DestructionKind 
QualType::isDestructedTypeImpl(QualType type) {
   return DK_none;
 }
 
+static bool
+requiresBuiltinLaunderImpl(const ASTContext &Context, QualType Ty,
+                           llvm::SmallPtrSetImpl<const Decl *> &Seen) {
+  if (const auto *Arr = Context.getAsArrayType(Ty))
+    Ty = Context.getBaseElementType(Arr);
+
+  const auto *Record = Ty->getAsCXXRecordDecl();
+  if (!Record)
+    return false;
+
+  // We've already checked this type, or are in the process of checking it.
+  if (!Seen.insert(Record).second)
+    return false;
+
+  assert(Record->hasDefinition() &&
+         "Incomplete types should already be diagnosed");
+
+  if (Record->isDynamicClass())
+    return true;
+
+  for (FieldDecl *F : Record->fields()) {
+    if (requiresBuiltinLaunderImpl(Context, F->getType(), Seen))
+      return true;
+  }
+  return false;
+}
+
+bool QualType::requiresBuiltinLaunder(const ASTContext &Context) const {
+  llvm::SmallPtrSet<const Decl *, 16> Seen;
+  return requiresBuiltinLaunderImpl(Context, *this, Seen);
+}
+
 bool MemberPointerType::isSugared() const {
   CXXRecordDecl *D1 = getMostRecentCXXRecordDecl(),
                 *D2 = getQualifier().getAsRecordDecl();
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 868bca404949b..b302f31860047 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1932,7 +1932,18 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
     cir::UnreachableOp::create(builder, loc);
     return RValue::get(nullptr);
   }
-  case Builtin::BI__builtin_launder:
+  case Builtin::BI__builtin_launder: {
+    const Expr *arg = e->getArg(0);
+    QualType argTy = arg->getType()->getPointeeType();
+    mlir::Value ptr = emitScalarExpr(arg);
+
+    if (cgm.getCodeGenOpts().StrictVTablePointers &&
+        argTy.requiresBuiltinLaunder(cgm.getASTContext())) {
+      mlir::Location loc = getLoc(e->getExprLoc());
+      ptr = cir::LaunderOp::create(builder, loc, ptr).getResult();
+    }
+    return RValue::get(ptr);
+  }
   case Builtin::BI__sync_fetch_and_add:
   case Builtin::BI__sync_fetch_and_sub:
   case Builtin::BI__sync_fetch_and_or:
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index dca079eff1752..c6027d08a5879 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5083,6 +5083,14 @@ mlir::LogicalResult 
CIRToLLVMMemChrOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMLaunderOpLowering::matchAndRewrite(
+    cir::LaunderOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  rewriter.replaceOpWithNewOp<mlir::LLVM::LaunderInvariantGroupOp>(
+      op, adaptor.getArg());
+  return mlir::success();
+}
+
 std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
   return std::make_unique<ConvertCIRToLLVMPass>();
 }
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index f29e27818d7ec..877cfb0e4d1d0 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2449,40 +2449,12 @@ EmitCheckedMixedSignMultiply(CodeGenFunction &CGF, 
const clang::Expr *Op1,
   return RValue::get(Overflow);
 }
 
-static bool
-TypeRequiresBuiltinLaunderImp(const ASTContext &Ctx, QualType Ty,
-                              llvm::SmallPtrSetImpl<const Decl *> &Seen) {
-  if (const auto *Arr = Ctx.getAsArrayType(Ty))
-    Ty = Ctx.getBaseElementType(Arr);
-
-  const auto *Record = Ty->getAsCXXRecordDecl();
-  if (!Record)
-    return false;
-
-  // We've already checked this type, or are in the process of checking it.
-  if (!Seen.insert(Record).second)
-    return false;
-
-  assert(Record->hasDefinition() &&
-         "Incomplete types should already be diagnosed");
-
-  if (Record->isDynamicClass())
-    return true;
-
-  for (FieldDecl *F : Record->fields()) {
-    if (TypeRequiresBuiltinLaunderImp(Ctx, F->getType(), Seen))
-      return true;
-  }
-  return false;
-}
-
 /// Determine if the specified type requires laundering by checking if it is a
 /// dynamic class type or contains a subobject which is a dynamic class type.
 static bool TypeRequiresBuiltinLaunder(CodeGenModule &CGM, QualType Ty) {
   if (!CGM.getCodeGenOpts().StrictVTablePointers)
     return false;
-  llvm::SmallPtrSet<const Decl *, 16> Seen;
-  return TypeRequiresBuiltinLaunderImp(CGM.getContext(), Ty, Seen);
+  return Ty.requiresBuiltinLaunder(CGM.getContext());
 }
 
 RValue CodeGenFunction::emitRotate(const CallExpr *E, bool IsRotateRight) {
diff --git a/clang/test/CIR/CodeGen/launder.cpp 
b/clang/test/CIR/CodeGen/launder.cpp
new file mode 100644
index 0000000000000..b76be5c8e6adb
--- /dev/null
+++ b/clang/test/CIR/CodeGen/launder.cpp
@@ -0,0 +1,119 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+// __builtin_launder doesn't actually DO anything unless 
fstrict-vtable-pointers
+// is enabled, so test here to make sure we get that switch correctly done.
+// RUN: %clang_cc1 -fstrict-vtable-pointers -triple x86_64-unknown-linux-gnu 
-fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR-STRICT
+// RUN: %clang_cc1 -fstrict-vtable-pointers -triple x86_64-unknown-linux-gnu 
-fclangir -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM-STRICT
+// RUN: %clang_cc1 -fstrict-vtable-pointers -triple x86_64-unknown-linux-gnu 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG-STRICT
+
+
+struct Base {};
+
+struct Derived : virtual Base {};
+
+struct VirtMem {
+  Derived d;
+};
+
+auto use_derived(Derived *d) {
+  return __builtin_launder(d);
+}
+// CIR-LABEL: cir.func{{.*}}@_Z11use_derivedP7Derived
+// CIR: %[[ARG_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>, ["d", init]
+// CIR: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>, ["__retval"]
+// CIR: %[[ARG_LOAD:.*]] = cir.load align(8) %[[ARG_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_Derived>>, !cir.ptr<!rec_Derived>
+// CIR: cir.store %[[ARG_LOAD]], %[[RET_ALLOCA]] : !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>
+// CIR: %[[RET:.*]] = cir.load %[[RET_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_Derived>>, !cir.ptr<!rec_Derived>
+// CIR: cir.return %[[RET]] : !cir.ptr<!rec_Derived>
+//
+// LLVM-LABEL: define {{.*}}@_Z11use_derivedP7Derived
+// LLVM: %[[ARG_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[RET_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG_ALLOCA]]
+// LLVM: store ptr %[[ARG_LOAD]], ptr %[[RET_ALLOCA]]
+// LLVM: %[[RET:.*]] = load ptr, ptr %[[RET_ALLOCA]]
+// LLVM: ret ptr %[[RET]]
+//
+// OGCG-LABEL: define {{.*}}@_Z11use_derivedP7Derived
+// OGCG: %[[ARG_ALLOCA:.*]] = alloca ptr
+// OGCG: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG_ALLOCA]]
+// OGCG: ret ptr %[[ARG_LOAD]]
+//
+// CIR-STRICT-LABEL: cir.func{{.*}}@_Z11use_derivedP7Derived
+// CIR-STRICT: %[[ARG_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>, ["d", init]
+// CIR-STRICT: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>, ["__retval"]
+// CIR-STRICT: %[[LOAD_ARG:.*]] = cir.load align(8) %[[ARG_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_Derived>>, !cir.ptr<!rec_Derived>
+// CIR-STRICT: %[[LAUNDER:.*]] = cir.launder(%[[LOAD_ARG]]) : 
!cir.ptr<!rec_Derived>
+// CIR-STRICT: cir.store %[[LAUNDER]], %[[RET_ALLOCA]] : 
!cir.ptr<!rec_Derived>, !cir.ptr<!cir.ptr<!rec_Derived>>
+// CIR-STRICT: %[[RET:.*]] = cir.load %[[RET_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_Derived>>, !cir.ptr<!rec_Derived>
+// CIR-STRICT: cir.return %[[RET]] : !cir.ptr<!rec_Derived>
+//
+// LLVM-STRICT-LABEL: define {{.*}}@_Z11use_derivedP7Derived
+// LLVM-STRICT: %[[ARG_ALLOCA:.*]] = alloca ptr
+// LLVM-STRICT: %[[RET_ALLOCA:.*]] = alloca ptr
+// LLVM-STRICT: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG_ALLOCA]]
+// LLVM-STRICT: %[[LAUNDER:.*]] = call ptr 
@llvm.launder.invariant.group.p0(ptr %[[ARG_LOAD]])
+// LLVM-STRICT: store ptr %[[LAUNDER]], ptr %[[RET_ALLOCA]]
+// LLVM-STRICT: %[[RET:.*]] = load ptr, ptr %[[RET_ALLOCA]]
+// LLVM-STRICT: ret ptr %[[RET]]
+//
+//
+// OGCG-STRICT-LABEL: define {{.*}}@_Z11use_derivedP7Derived
+// OGCG-STRICT: %[[ARG_ALLOCA:.*]] = alloca ptr
+// OGCG-STRICT: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG_ALLOCA]]
+// OGCG-STRICT: %[[LAUNDER:.*]] = call ptr 
@llvm.launder.invariant.group.p0(ptr %[[ARG_LOAD]])
+// OGCG-STRICT: ret ptr %[[LAUNDER]]
+
+auto use_vm(VirtMem *vm) {
+  return __builtin_launder(vm);
+}
+// CIR-LABEL: cir.func {{.*}}@_Z6use_vmP7VirtMem
+// CIR: %[[ARG_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_VirtMem>, 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, ["vm", init]
+// CIR: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_VirtMem>, 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, ["__retval"]
+// CIR: cir.store %[[ARG_LOAD]], %[[RET_ALLOCA]] : !cir.ptr<!rec_VirtMem>, 
!cir.ptr<!cir.ptr<!rec_VirtMem>>
+// CIR: %[[RET:.*]] = cir.load %[[RET_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, !cir.ptr<!rec_VirtMem>
+// CIR: cir.return %[[RET]] : !cir.ptr<!rec_VirtMem>
+//
+// LLVM-LABEL: define {{.*}}@_Z6use_vmP7VirtMem
+// LLVM: %[[ARG_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[RET_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG_ALLOCA]]
+// LLVM: store ptr %[[ARG_LOAD]], ptr %[[RET_ALLOCA]]
+// LLVM: %[[RET:.*]] = load ptr, ptr %[[RET_ALLOCA]]
+// LLVM: ret ptr %[[RET]]
+//
+// OGCG-LABEL: define {{.*}}@_Z6use_vmP7VirtMem
+// OGCG: %[[ARG_ALLOCA:.*]] = alloca ptr
+// OGCG: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG_ALLOCA]]
+// OGCG: ret ptr %[[ARG_LOAD]]
+//
+// CIR-STRICT-LABEL: cir.func {{.*}}@_Z6use_vmP7VirtMem
+// CIR-STRICT: %[[ARG_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_VirtMem>, 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, ["vm", init]
+// CIR-STRICT: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_VirtMem>, 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, ["__retval"]
+// CIR-STRICT: %[[LOAD_ARG:.*]] = cir.load align(8) %[[ARG_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, !cir.ptr<!rec_VirtMem>
+// CIR-STRICT: %[[LAUNDER:.*]] = cir.launder(%[[LOAD_ARG]]) : 
!cir.ptr<!rec_VirtMem>
+// CIR-STRICT: cir.store %[[LAUNDER]], %[[RET_ALLOCA]] : 
!cir.ptr<!rec_VirtMem>, !cir.ptr<!cir.ptr<!rec_VirtMem>>
+// CIR-STRICT: %[[RET:.*]] = cir.load %[[RET_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, !cir.ptr<!rec_VirtMem>
+// CIR-STRICT: cir.return %[[RET]] : !cir.ptr<!rec_VirtMem>
+//
+// LLVM-STRICT-LABEL: define {{.*}}@_Z6use_vmP7VirtMem
+// LLVM-STRICT: %[[ARG_ALLOCA:.*]] = alloca ptr
+// LLVM-STRICT: %[[RET_ALLOCA:.*]] = alloca ptr
+// LLVM-STRICT: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG_ALLOCA]]
+// LLVM-STRICT: %[[LAUNDER:.*]] = call ptr 
@llvm.launder.invariant.group.p0(ptr %[[ARG_LOAD]])
+// LLVM-STRICT: store ptr %[[LAUNDER]], ptr %[[RET_ALLOCA]]
+// LLVM-STRICT: %[[RET:.*]] = load ptr, ptr %[[RET_ALLOCA]]
+// LLVM-STRICT: ret ptr %[[RET]]
+//
+// OGCG-STRICT-LABEL: define {{.*}}@_Z6use_vmP7VirtMem
+// OGCG-STRICT: %[[ARG_ALLOCA:.*]] = alloca ptr
+// OGCG-STRICT: %[[LAUNDER:.*]] = call ptr 
@llvm.launder.invariant.group.p0(ptr %[[ARG_LOAD]])
+// OGCG-STRICT: ret ptr %[[LAUNDER]]

>From d856f0b5bc0c0d46fa6a0fed2b612f28c3865802 Mon Sep 17 00:00:00 2001
From: erichkeane <[email protected]>
Date: Tue, 12 May 2026 13:56:38 -0700
Subject: [PATCH 2/2] Change assembly format

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 +-
 clang/test/CIR/CodeGen/launder.cpp           | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 6415b19058397..1e51637a00a7d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -8200,7 +8200,7 @@ def CIR_LaunderOp : CIR_Op<"launder", 
[SameOperandsAndResultType]> {
   let results = (outs CIR_PointerType:$result);
 
   let assemblyFormat = [{
-    `(` $arg `)` `:` qualified(type($result)) attr-dict
+    $arg `:` qualified(type($result)) attr-dict
   }];
 }
 
diff --git a/clang/test/CIR/CodeGen/launder.cpp 
b/clang/test/CIR/CodeGen/launder.cpp
index b76be5c8e6adb..397459c0a7a24 100644
--- a/clang/test/CIR/CodeGen/launder.cpp
+++ b/clang/test/CIR/CodeGen/launder.cpp
@@ -51,7 +51,7 @@ auto use_derived(Derived *d) {
 // CIR-STRICT: %[[ARG_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>, ["d", init]
 // CIR-STRICT: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>, ["__retval"]
 // CIR-STRICT: %[[LOAD_ARG:.*]] = cir.load align(8) %[[ARG_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_Derived>>, !cir.ptr<!rec_Derived>
-// CIR-STRICT: %[[LAUNDER:.*]] = cir.launder(%[[LOAD_ARG]]) : 
!cir.ptr<!rec_Derived>
+// CIR-STRICT: %[[LAUNDER:.*]] = cir.launder %[[LOAD_ARG]]  : 
!cir.ptr<!rec_Derived>
 // CIR-STRICT: cir.store %[[LAUNDER]], %[[RET_ALLOCA]] : 
!cir.ptr<!rec_Derived>, !cir.ptr<!cir.ptr<!rec_Derived>>
 // CIR-STRICT: %[[RET:.*]] = cir.load %[[RET_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_Derived>>, !cir.ptr<!rec_Derived>
 // CIR-STRICT: cir.return %[[RET]] : !cir.ptr<!rec_Derived>
@@ -99,7 +99,7 @@ auto use_vm(VirtMem *vm) {
 // CIR-STRICT: %[[ARG_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_VirtMem>, 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, ["vm", init]
 // CIR-STRICT: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_VirtMem>, 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, ["__retval"]
 // CIR-STRICT: %[[LOAD_ARG:.*]] = cir.load align(8) %[[ARG_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, !cir.ptr<!rec_VirtMem>
-// CIR-STRICT: %[[LAUNDER:.*]] = cir.launder(%[[LOAD_ARG]]) : 
!cir.ptr<!rec_VirtMem>
+// CIR-STRICT: %[[LAUNDER:.*]] = cir.launder %[[LOAD_ARG]] : 
!cir.ptr<!rec_VirtMem>
 // CIR-STRICT: cir.store %[[LAUNDER]], %[[RET_ALLOCA]] : 
!cir.ptr<!rec_VirtMem>, !cir.ptr<!cir.ptr<!rec_VirtMem>>
 // CIR-STRICT: %[[RET:.*]] = cir.load %[[RET_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_VirtMem>>, !cir.ptr<!rec_VirtMem>
 // CIR-STRICT: cir.return %[[RET]] : !cir.ptr<!rec_VirtMem>

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to