Author: Mariya Podchishchaeva
Date: 2026-09-25T10:01:52+02:00
New Revision: 67f685af1b364056fd59fc42841d7f428d46ee1a

URL: 
https://github.com/llvm/llvm-project/commit/67f685af1b364056fd59fc42841d7f428d46ee1a
DIFF: 
https://github.com/llvm/llvm-project/commit/67f685af1b364056fd59fc42841d7f428d46ee1a.diff

LOG: [CIR] Lower __builtin_memcpy/mempcpy to cir.libc.memcpy (#225845)

These previously were lowered to a call to undefined memcpy function
which caused link failures when compiled for AMDGPU since there it is
never resolved to a library function.
cir.libc.memcpy is later lowered to llvm.memcpy intrinsic call which
matches classic codegen.
This also adds alignment attributes to cir.libc.memcpy op so resulting
LLVM IR also has them just like LLVM IR produced by the classic codegen

Assisted by: claude

Added: 
    clang/test/CIR/CodeGen/builtin-memcpy.c

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
    clang/lib/CIR/CodeGen/CIRGenBuilder.h
    clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
    clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
    clang/test/CIR/CodeGen/assign-operator.cpp
    clang/test/CIR/CodeGen/atomic.c
    clang/test/CIR/CodeGen/libc.c
    clang/test/CIR/CodeGen/union-copy-move-assignment.cpp
    clang/test/CIR/CodeGenBuiltins/builtin-bit-cast.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index c1ba78eea2835..5ebad8b019e2b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -5250,10 +5250,15 @@ def CIR_MemCpyOp : CIR_MemOp<"libc.memcpy"> {
     ```
   }];
 
-  let arguments = !con(commonArgs, (ins CIR_AnyFundamentalUIntType:$len));
+  let arguments = !con(commonArgs, (ins
+    CIR_AnyFundamentalUIntType:$len,
+    OptionalAttr<I64Attr>:$dst_alignment,
+    OptionalAttr<I64Attr>:$src_alignment
+  ));
 
   let assemblyFormat = [{
-    $len `bytes` `from` $src `to` $dst attr-dict
+    $len `bytes` `from` $src (`align` `(` $src_alignment^ `)`)?
+    `to` $dst (`align` `(` $dst_alignment^ `)`)? attr-dict
     `:` type($len) `,` qualified(type($src)) `->` qualified(type($dst))
   }];
 

diff  --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp 
b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index c4c3b455bf11c..e89be4fc60975 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -216,7 +216,7 @@ Address AtomicInfo::convertToAtomicIntPointer(Address addr,
 
     tmp = tmp.withElementType(builder, cgf.cgm.voidTy);
     builder.createMemCpy(
-        loc, tmp.getPointer(), addr.getPointer(),
+        loc, tmp, addr,
         builder.getConstInt(loc, cgf.cgm.uInt64Ty,
                             std::min(atomicSizeInBits, sourceSizeInBits) / 8));
     addr = tmp;

diff  --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 91e3b18a6b315..01d74e1549fa5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -195,9 +195,12 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
     return op;
   }
 
-  cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst,
-                             mlir::Value src, mlir::Value len) {
-    return cir::MemCpyOp::create(*this, loc, dst, src, len);
+  cir::MemCpyOp createMemCpy(mlir::Location loc, Address dst, Address src,
+                             mlir::Value len) {
+    return cir::MemCpyOp::create(
+        *this, loc, dst.getPointer(), src.getPointer(), len,
+        getI64IntegerAttr(dst.getAlignment().getQuantity()),
+        getI64IntegerAttr(src.getAlignment().getQuantity()));
   }
 
   cir::MemMoveOp createMemMove(mlir::Location loc, mlir::Value dst,

diff  --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 2b223c8ae1939..245708691b7d9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -2430,7 +2430,24 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl 
&gd, unsigned builtinID,
   case Builtin::BImemcpy:
   case Builtin::BI__builtin_memcpy:
   case Builtin::BImempcpy:
-  case Builtin::BI__builtin_mempcpy:
+  case Builtin::BI__builtin_mempcpy: {
+    mlir::Location loc = getLoc(e->getSourceRange());
+    Address dest = emitPointerWithAlignment(e->getArg(0));
+    Address src = emitPointerWithAlignment(e->getArg(1));
+    mlir::Value sizeVal = emitScalarExpr(e->getArg(2));
+    Address destCast = dest.withElementType(builder, cgm.voidTy);
+    Address srcCast = src.withElementType(builder, cgm.voidTy);
+    assert(!cir::MissingFeatures::sanitizers());
+    builder.createMemCpy(loc, destCast, srcCast, sizeVal);
+    assert(!cir::MissingFeatures::generateDebugInfo());
+    if (builtinID == Builtin::BImempcpy ||
+        builtinID == Builtin::BI__builtin_mempcpy) {
+      mlir::Value destPtr = destCast.getPointer();
+      mlir::Value end = builder.createPtrStride(loc, destPtr, sizeVal);
+      return RValue::get(end);
+    }
+    return RValue::get(dest.getPointer());
+  }
   case Builtin::BI__builtin_memcpy_inline:
   case Builtin::BI__builtin___memcpy_chk:
   case Builtin::BI__builtin_objc_memmove_collectable:

diff  --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 8ee72b543c56f..e90d075f76500 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -208,8 +208,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
       mlir::Value sizeVal = cgf.getBuilder().getConstInt(
           loc, cgf.sizeTy,
           cgf.getContext().getTypeSizeInChars(e->getType()).getQuantity());
-      cgf.getBuilder().createMemCpy(loc, destAddress.getPointer(),
-                                    sourceAddress.getPointer(), sizeVal);
+      cgf.getBuilder().createMemCpy(loc, destAddress, sourceAddress, sizeVal);
 
       break;
     }

diff  --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index bd529f71b38ed..53bffe0259002 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -324,9 +324,25 @@ mlir::LogicalResult 
CIRToLLVMCopyOpLowering::matchAndRewrite(
 mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
     cir::MemCpyOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::ArrayAttr argAttrs;
+  if (op.getDstAlignment() || op.getSrcAlignment()) {
+    mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
+        mlir::LLVM::LLVMDialect::getAlignAttrName(),
+        rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(1)));
+    mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
+        mlir::LLVM::LLVMDialect::getAlignAttrName(),
+        rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(1)));
+    argAttrs = rewriter.getArrayAttr({
+        /*dst_attrs=*/rewriter.getDictionaryAttr({dstAlignAttr}),
+        /*src_attrs=*/rewriter.getDictionaryAttr({srcAlignAttr}),
+    });
+  }
   rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
       op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLen(),
-      /*isVolatile=*/false);
+      /*isVolatile=*/false,
+      /*access_groups=*/nullptr, /*alias_scopes=*/nullptr,
+      /*noalias_scopes=*/nullptr, /*tbaa=*/nullptr, /*arg_attrs=*/argAttrs,
+      /*res_attrs=*/nullptr);
   return mlir::success();
 }
 

diff  --git a/clang/test/CIR/CodeGen/assign-operator.cpp 
b/clang/test/CIR/CodeGen/assign-operator.cpp
index e01572198d608..5a874746ccb73 100644
--- a/clang/test/CIR/CodeGen/assign-operator.cpp
+++ b/clang/test/CIR/CodeGen/assign-operator.cpp
@@ -85,7 +85,7 @@ void copy_c(C &c1, C &c2) {
 // CIR:   %[[B_MEMBER_2:.*]] = cir.get_member %[[RET_LOAD]][1] {name = "b"}
 // CIR:   %[[B_VOID_PTR_2:.*]] = cir.cast bitcast %[[B_MEMBER_2]] : 
!cir.ptr<!cir.array<!rec_B x 16>> -> !cir.ptr<!void>
 // CIR:   %[[SIZE:.*]] = cir.const #cir.int<64> : !u64i
-// CIR:   %[[COUNT:.*]] = cir.call @memcpy(%[[B_VOID_PTR]], %[[B_VOID_PTR_2]], 
%[[SIZE]])
+// CIR:   cir.libc.memcpy %[[SIZE]] bytes from %[[B_VOID_PTR_2]] align(4) to 
%[[B_VOID_PTR]] align(4)
 // CIR:   cir.store %[[THIS]], %[[RET_ADDR]]
 // CIR:   %[[RET_VAL:.*]] = cir.load{{.*}} %[[RET_ADDR]]
 // CIR:   cir.return %[[RET_VAL]]
@@ -101,7 +101,7 @@ void copy_c(C &c1, C &c2) {
 // LLVM:   %[[B1:.*]] = getelementptr inbounds nuw %struct.C, ptr 
%[[THIS_LOAD]], i32 0, i32 1
 // LLVM:   %[[ARG_LOAD2:.*]] = load ptr, ptr %[[ARG_ADDR]]
 // LLVM:   %[[B2:.*]] = getelementptr inbounds nuw %struct.C, ptr 
%[[ARG_LOAD2]], i32 0, i32 1
-// LLVM:   %{{.*}} = call ptr @memcpy(ptr {{.*}} %[[B1]], ptr {{.*}} %[[B2]], 
i64 {{.*}} 64)
+// LLVM:   call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[B1]], ptr align 4 
%[[B2]], i64 64, i1 false)
 
 // OGCG: define {{.*}} ptr @_ZN1CaSERKS_(ptr {{.*}} %[[THIS:.*]], ptr {{.*}} 
%[[ARG:.*]])
 // OGCG:   %[[THIS_ADDR:.*]] = alloca ptr
@@ -144,7 +144,6 @@ void copy_ref_to_ref(E &e1, E &e2) {
 // CIR:   cir.return
 
 // CIR: cir.func private @_ZN1AaSERKS_(!cir.ptr<!rec_A> {{.*}}, 
!cir.ptr<!rec_A> {{.*}}) -> (!cir.ptr<!rec_A>{{.*}})
-// CIR: cir.func private @memcpy(!cir.ptr<!void> {{.*}}, !cir.ptr<!void> 
{{.*}}, !u64i {{.*}}) -> !cir.ptr<!void>
 
 // LLVM: define{{.*}} void @_Z15copy_ref_to_refR1ES0_(ptr{{.*}} %[[ARG0:.*]], 
ptr{{.*}} %[[ARG1:.*]]){{.*}} {
 // LLVM:   %[[E1_ADDR:.*]] = alloca ptr

diff  --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index f3913ea28072e..28fe01e83ed65 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -3991,7 +3991,7 @@ void store_atomic_
diff erent_size(S a) {
  // CIR: cir.libc.memset %[[MEMSET_SIZE]] bytes at %[[A_VOID_PTR]] {{.*}} to 
%[[CONST_0]] : !cir.ptr<!void>, !u8i, !u64i
  // CIR: %[[ATOMIC_TMP:.*]] = cir.cast bitcast %[[ATOMIC_TMP_ADDR]] : 
!cir.ptr<!rec_anon_struct1> -> !cir.ptr<!void>
  // CIR: %[[MEMCPY_SIZE:.*]] = cir.const #cir.int<3> : !u64i
- // CIR: cir.libc.memcpy %[[MEMCPY_SIZE]] bytes from %[[A_VOID_PTR]] to 
%[[ATOMIC_TMP]] : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+ // CIR: cir.libc.memcpy %[[MEMCPY_SIZE]] bytes from %[[A_VOID_PTR]] align(1) 
to %[[ATOMIC_TMP]] align(4) : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
  // CIR: %[[ATOMIC_TMP_U32:.*]] = cir.cast bitcast %[[ATOMIC_TMP]] : 
!cir.ptr<!void> -> !cir.ptr<!u32i>
  // CIR: %[[DATA:.*]] = cir.load {{.*}} %[[ATOMIC_TMP_U32]] : !cir.ptr<!u32i>, 
!u32i
  // CIR: cir.store {{.*}} syncscope(system) atomic(seq_cst) %[[DATA]], 
%[[B_VOID_PTR]] : !u32i, !cir.ptr<!u32i>
@@ -4006,7 +4006,7 @@ void store_atomic_
diff erent_size(S a) {
  // LLVM: store %struct.S %[[A]], ptr %[[A_ADDR]], align 1
  // LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[A_ATOMIC_TMP_ADDR]], 
ptr align 1 %[[A_ADDR]], i64 3, i1 false)
  // LLVM: call void @llvm.memset.p0.i64(ptr align 1 %[[A_ATOMIC_TMP_ADDR]], i8 
0, i64 4, i1 false)
- // LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[ATOMIC_TMP_ADDR]], ptr 
%[[A_ATOMIC_TMP_ADDR]], i64 3, i1 false)
+ // LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ATOMIC_TMP_ADDR]], 
ptr align 1 %[[A_ATOMIC_TMP_ADDR]], i64 3, i1 false)
  // LLVM: %[[ATOMIC_TMP:.*]] = load i32, ptr %[[ATOMIC_TMP_ADDR]], align 4
  // LLVM: store atomic i32 %[[ATOMIC_TMP]], ptr %[[B_ADDR]] seq_cst, align 4
 

diff  --git a/clang/test/CIR/CodeGen/builtin-memcpy.c 
b/clang/test/CIR/CodeGen/builtin-memcpy.c
new file mode 100644
index 0000000000000..4e3853a8f711a
--- /dev/null
+++ b/clang/test/CIR/CodeGen/builtin-memcpy.c
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -o - 
%s | FileCheck %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -o - 
%s | FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | 
FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fclangir -emit-cir -o - %s | 
FileCheck %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fclangir -emit-llvm -o - %s | 
FileCheck %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -emit-llvm -o - %s | FileCheck %s 
--check-prefix=LLVM
+
+typedef unsigned long size_t;
+
+void test_memcpy(void *dst, const void *src, size_t n) {
+  __builtin_memcpy(dst, src, n);
+}
+
+// CIR-LABEL: cir.func no_inline dso_local @test_memcpy
+// CIR:         %[[DST:.*]] = cir.load align(8) %{{.*}} : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR-NEXT:    %[[SRC:.*]] = cir.load align(8) %{{.*}} : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR-NEXT:    %[[N:.*]] = cir.load align(8) %{{.*}} : !cir.ptr<!u64i>, !u64i
+// CIR-NEXT:    cir.libc.memcpy %[[N]] bytes from %[[SRC]] align(1) to 
%[[DST]] align(1) : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+
+// LLVM-LABEL: define dso_local void @test_memcpy
+// LLVM:         call void @llvm.memcpy.p0.p0.i64(ptr align 1 %{{.*}}, ptr 
align 1 %{{.*}}, i64 %{{.*}}, i1 false)
+
+void *test_memcpy_ret(void *dst, const void *src, size_t n) {
+  return __builtin_memcpy(dst, src, n);
+}
+
+// CIR-LABEL: cir.func no_inline dso_local @test_memcpy_ret
+// CIR:         %[[DST:.*]] = cir.load align(8) %{{.*}} : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR-NEXT:    %[[SRC:.*]] = cir.load align(8) %{{.*}} : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR-NEXT:    %[[N:.*]] = cir.load align(8) %{{.*}} : !cir.ptr<!u64i>, !u64i
+// CIR-NEXT:    cir.libc.memcpy %[[N]] bytes from %[[SRC]] align(1) to 
%[[DST]] align(1) : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+// CIR:         cir.return %{{.*}} : !cir.ptr<!void>
+
+// LLVM-LABEL: define dso_local ptr @test_memcpy_ret
+// LLVM:         call void @llvm.memcpy.p0.p0.i64(ptr align 1 %{{.*}}, ptr 
align 1 %{{.*}}, i64 %{{.*}}, i1 false)
+// LLVM:         ret ptr %{{.*}}
+
+void test_memcpy_int(int *dst, const int *src, size_t n) {
+  __builtin_memcpy(dst, src, n);
+}
+
+// CIR-LABEL: cir.func no_inline dso_local @test_memcpy_int
+// CIR:         %[[DST_I:.*]] = cir.load align(8) %{{.*}} : 
!cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CIR-NEXT:    %[[DST:.*]] = cir.cast bitcast %[[DST_I]] : !cir.ptr<!s32i> -> 
!cir.ptr<!void>
+// CIR-NEXT:    %[[SRC_I:.*]] = cir.load align(8) %{{.*}} : 
!cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CIR-NEXT:    %[[SRC:.*]] = cir.cast bitcast %[[SRC_I]] : !cir.ptr<!s32i> -> 
!cir.ptr<!void>
+// CIR-NEXT:    %[[N:.*]] = cir.load align(8) %{{.*}} : !cir.ptr<!u64i>, !u64i
+// CIR-NEXT:    cir.libc.memcpy %[[N]] bytes from %[[SRC]] align(4) to 
%[[DST]] align(4) : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+
+// LLVM-LABEL: define dso_local void @test_memcpy_int
+// LLVM:         %[[DST:.*]] = load ptr, ptr %{{.*}}, align 8
+// LLVM-NEXT:    %[[SRC:.*]] = load ptr, ptr %{{.*}}, align 8
+// LLVM-NEXT:    %[[N:.*]] = load i64, ptr %{{.*}}, align 8
+// LLVM-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[DST]], ptr 
align 4 %[[SRC]], i64 %[[N]], i1 false)
+
+void *test_mempcpy(void *dst, const void *src, size_t n) {
+  return __builtin_mempcpy(dst, src, n);
+}
+
+// CIR-LABEL: cir.func no_inline dso_local @test_mempcpy
+// CIR:         %[[DST:.*]] = cir.load align(8) %{{.*}} : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR-NEXT:    %[[SRC:.*]] = cir.load align(8) %{{.*}} : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR-NEXT:    %[[N:.*]] = cir.load align(8) %{{.*}} : !cir.ptr<!u64i>, !u64i
+// CIR-NEXT:    cir.libc.memcpy %[[N]] bytes from %[[SRC]] align(1) to 
%[[DST]] align(1) : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+// CIR-NEXT:    %[[END:.*]] = cir.ptr_stride %[[DST]], %[[N]] : 
(!cir.ptr<!void>, !u64i) -> !cir.ptr<!void>
+// CIR:         cir.return %{{.*}} : !cir.ptr<!void>
+
+// LLVM-LABEL: define dso_local ptr @test_mempcpy
+// LLVM:         %[[DST:.*]] = load ptr, ptr %{{.*}}, align 8
+// LLVM-NEXT:    %[[SRC:.*]] = load ptr, ptr %{{.*}}, align 8
+// LLVM-NEXT:    %[[N:.*]] = load i64, ptr %{{.*}}, align 8
+// LLVM-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[DST]], ptr 
align 1 %[[SRC]], i64 %[[N]], i1 false)
+// LLVM-NEXT:    getelementptr{{.*}} i8, ptr %[[DST]], i64 %[[N]]
+// Note: OG emits getelementptr inbounds; CIR omits inbounds (missing feature 
in cir.ptr_stride lowering).

diff  --git a/clang/test/CIR/CodeGen/libc.c b/clang/test/CIR/CodeGen/libc.c
index e20cdc3dfbbf5..1ea383b1559d2 100644
--- a/clang/test/CIR/CodeGen/libc.c
+++ b/clang/test/CIR/CodeGen/libc.c
@@ -20,7 +20,14 @@
 void *memcpy(void *, const void *, unsigned long);
 void testMemcpy(void *dst, const void *src, unsigned long size) {
   memcpy(dst, src, size);
-  // CHECK: cir.call @memcpy
+  // CHECK: cir.libc.memcpy
+}
+
+void *mempcpy(void *, const void *, unsigned long);
+void *testMempcpy(void *dst, const void *src, unsigned long size) {
+  return mempcpy(dst, src, size);
+  // CHECK: cir.libc.memcpy
+  // CHECK: cir.ptr_stride
 }
 
 void *memmove(void *, const void *, unsigned long);

diff  --git a/clang/test/CIR/CodeGen/union-copy-move-assignment.cpp 
b/clang/test/CIR/CodeGen/union-copy-move-assignment.cpp
index aeb3461990e5c..cd68e2cacba8c 100644
--- a/clang/test/CIR/CodeGen/union-copy-move-assignment.cpp
+++ b/clang/test/CIR/CodeGen/union-copy-move-assignment.cpp
@@ -1,9 +1,9 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
 // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -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-unknown-linux-gnu -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
 
 union U {
   int a;
@@ -16,18 +16,11 @@ auto get_copy = static_cast<U &(U::*)(const U 
&)>(&U::operator=);
 auto get_move = static_cast<U &(U::*)(U &&)>(&U::operator=);
 
 // CIR: cir.func{{.*}}@_ZN1UaSERKS_{{.*}}cxx_assign<!rec_U, copy, trivial true>
-// CIR:   cir.call @memcpy(
+// CIR:   cir.libc.memcpy {{.*}} align(4) to {{.*}} align(4)
 // CIR: cir.func{{.*}}@_ZN1UaSEOS_{{.*}}cxx_assign<!rec_U, move, trivial true>
-// CIR:   cir.call @memcpy(
-
-// The CIR backend calls the memcpy libcall where the classic backend emits the
-// llvm.memcpy intrinsic.
+// CIR:   cir.libc.memcpy {{.*}} align(4) to {{.*}} align(4)
 
 // LLVM: define linkonce_odr noundef nonnull align 4 dereferenceable(4) ptr 
@_ZN1UaSERKS_(ptr noundef nonnull align 4 dereferenceable(4) %{{.+}}, ptr 
noundef nonnull align 4 dereferenceable(4) %{{.+}})
-// LLVMCIR:     call ptr @memcpy(ptr noundef %{{.+}}, ptr noundef %{{.+}}, i64 
noundef 4)
-// LLVMCIR-NOT: call ptr @memcpy
-// OGCG:        call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.+}}, ptr 
align 4 %{{.+}}, i64 4, i1 false)
-// OGCG-NOT:    call void @llvm.memcpy
+// LLVM:        call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.+}}, ptr 
align 4 %{{.+}}, i64 4, i1 false)
 // LLVM: define linkonce_odr noundef nonnull align 4 dereferenceable(4) ptr 
@_ZN1UaSEOS_(ptr noundef nonnull align 4 dereferenceable(4) %{{.+}}, ptr 
noundef nonnull align 4 dereferenceable(4) %{{.+}})
-// LLVMCIR:     call ptr @memcpy(ptr noundef %{{.+}}, ptr noundef %{{.+}}, i64 
noundef 4)
-// OGCG:        call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.+}}, ptr 
align 4 %{{.+}}, i64 4, i1 false)
+// LLVM:        call void @llvm.memcpy.p0.p0.i64(ptr align 4 %{{.+}}, ptr 
align 4 %{{.+}}, i64 4, i1 false)

diff  --git a/clang/test/CIR/CodeGenBuiltins/builtin-bit-cast.cpp 
b/clang/test/CIR/CodeGenBuiltins/builtin-bit-cast.cpp
index 24eb7211551bf..26ad0deb9c373 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-bit-cast.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-bit-cast.cpp
@@ -58,7 +58,7 @@ two_floats test_aggregate_record(two_ints& ti) {
 //  CIR-NEXT:   %[[#SRC_VOID_PTR:]] = cir.cast bitcast %[[#SRC_PTR]] : 
!cir.ptr<!rec_two_ints> -> !cir.ptr<!void>
 //  CIR-NEXT:   %[[#DST_VOID_PTR:]] = cir.cast bitcast %{{.+}} : 
!cir.ptr<!rec_two_floats> -> !cir.ptr<!void>
 //  CIR-NEXT:   %[[#SIZE:]] = cir.const #cir.int<8> : !u64i
-//  CIR-NEXT:   cir.libc.memcpy %[[#SIZE]] bytes from %[[#SRC_VOID_PTR]] to 
%[[#DST_VOID_PTR]] : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+//  CIR-NEXT:   cir.libc.memcpy %[[#SIZE]] bytes from %[[#SRC_VOID_PTR]] 
align(4) to %[[#DST_VOID_PTR]] align(4) : !u64i, !cir.ptr<!void> -> 
!cir.ptr<!void>
 
 // LLVM-LABEL: define dso_local{{.*}} %struct.two_floats 
@_Z21test_aggregate_recordR8two_ints
 //       LLVM:   %[[DST_SLOT:.*]] = alloca %struct.two_floats{{.*}}, align 4
@@ -75,7 +75,7 @@ two_floats test_aggregate_array(int (&ary)[2]) {
 //  CIR-NEXT:   %[[#SRC_VOID_PTR:]] = cir.cast bitcast %[[#SRC_PTR]] : 
!cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!void>
 //  CIR-NEXT:   %[[#DST_VOID_PTR:]] = cir.cast bitcast %{{.+}} : 
!cir.ptr<!rec_two_floats> -> !cir.ptr<!void>
 //  CIR-NEXT:   %[[#SIZE:]] = cir.const #cir.int<8> : !u64i
-//  CIR-NEXT:   cir.libc.memcpy %[[#SIZE]] bytes from %[[#SRC_VOID_PTR]] to 
%[[#DST_VOID_PTR]] : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+//  CIR-NEXT:   cir.libc.memcpy %[[#SIZE]] bytes from %[[#SRC_VOID_PTR]] 
align(4) to %[[#DST_VOID_PTR]] align(4) : !u64i, !cir.ptr<!void> -> 
!cir.ptr<!void>
 
 // LLVM-LABEL: define dso_local{{.*}} %struct.two_floats 
@_Z20test_aggregate_arrayRA2_i
 //       LLVM:   %[[DST_SLOT:.*]] = alloca %struct.two_floats{{.*}}, align 4
@@ -91,7 +91,7 @@ two_ints test_scalar_to_aggregate(unsigned long ul) {
 //       CIR:   %[[#SRC_VOID_PTR:]] = cir.cast bitcast %{{.+}} : 
!cir.ptr<!u64i> -> !cir.ptr<!void>
 //  CIR-NEXT:   %[[#DST_VOID_PTR:]] = cir.cast bitcast %{{.+}} : 
!cir.ptr<!rec_two_ints> -> !cir.ptr<!void>
 //  CIR-NEXT:   %[[#SIZE:]] = cir.const #cir.int<8> : !u64i
-//  CIR-NEXT:   cir.libc.memcpy %[[#SIZE]] bytes from %[[#SRC_VOID_PTR]] to 
%[[#DST_VOID_PTR]] : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+//  CIR-NEXT:   cir.libc.memcpy %[[#SIZE]] bytes from %[[#SRC_VOID_PTR]] 
align(8) to %[[#DST_VOID_PTR]] align(4) : !u64i, !cir.ptr<!void> -> 
!cir.ptr<!void>
 
 // LLVM-DIRECT-LABEL: define dso_local i64 @_Z24test_scalar_to_aggregatem
 // LLVM-VIA-CIR-LABEL: define dso_local %struct.two_ints 
@_Z24test_scalar_to_aggregatem
@@ -124,7 +124,7 @@ two_ints test_rvalue_aggregate() {
 //  CIR-NEXT:   %[[#SRC_VOID_PTR:]] = cir.cast bitcast %[[#TMP_SLOT]] : 
!cir.ptr<!u64i> -> !cir.ptr<!void>
 //  CIR-NEXT:   %[[#DST_VOID_PTR:]] = cir.cast bitcast %0 : 
!cir.ptr<!rec_two_ints> -> !cir.ptr<!void>
 //  CIR-NEXT:   %[[#SIZE:]] = cir.const #cir.int<8> : !u64i
-//  CIR-NEXT:   cir.libc.memcpy %[[#SIZE]] bytes from %[[#SRC_VOID_PTR]] to 
%[[#DST_VOID_PTR]] : !u64i, !cir.ptr<!void> -> !cir.ptr<!void>
+//  CIR-NEXT:   cir.libc.memcpy %[[#SIZE]] bytes from %[[#SRC_VOID_PTR]] 
align(8) to %[[#DST_VOID_PTR]] align(4) : !u64i, !cir.ptr<!void> -> 
!cir.ptr<!void>
 
 /// FIXME: The function signature below should be identical for both lowering
 /// paths, but CIR is still missing calling convention lowering. Update this


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

Reply via email to