[clang] [CIR] Add alignment attributes to cir.copy (PR #206341)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 28 08:44:41 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Sirui Mu (Lancern)
<details>
<summary>Changes</summary>
This patch contains the following changes:
- It adds two optional attributes to the `cir.copy` operation, namely `src_alignment` and `dst_alignment`. They give the alignment of the source pointer and the destination pointer.
- It updates the LLVM lowering pass and attaches alignment information to the `llvm.memcpy` operation lowered from `cir.copy` operation. If `src_alignment` or `dst_alignment` is missing, the default alignment of the pointee type is used instead.
- Tests are updated accordingly.
There is one revealed mismatch between LLVM and OGCG checks after this update, at `clang/test/CIR/CodeGen/array.cpp:482`. The corresponding `cir.CopyOp` is created at `clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp:2244`, which currently lacks special handling for pointer alignments.
Assisted-by: Codex / gpt-5.5 xhigh
---
Patch is 84.60 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/206341.diff
43 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+3-2)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+9-3)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+10)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+1-2)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+21-1)
- (modified) clang/test/CIR/CodeGen/abstract-cond.c (+10-10)
- (modified) clang/test/CIR/CodeGen/agg-atomic-cast.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/agg-expr-lvalue.c (+2-2)
- (modified) clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp (+4-4)
- (modified) clang/test/CIR/CodeGen/array.cpp (+6-6)
- (modified) clang/test/CIR/CodeGen/atomic-libcall.c (+2-2)
- (modified) clang/test/CIR/CodeGen/binassign.c (+4-4)
- (modified) clang/test/CIR/CodeGen/complex-cast.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/compound_literal.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/consteval-aggregate.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/copy-constructor.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/embed-expr.c (+1-1)
- (modified) clang/test/CIR/CodeGen/global-decomp-decls.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/lambda.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/local-const-aggregate-name-clash.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/loop.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/no-odr-use.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/no-unique-address.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/nrvo.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/paren-init-list.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/paren-list-agg-init.cpp (+18-18)
- (modified) clang/test/CIR/CodeGen/pointer-to-member-func.cpp (+3-3)
- (modified) clang/test/CIR/CodeGen/statement-exprs.c (+3-3)
- (modified) clang/test/CIR/CodeGen/static-local.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/struct-init.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/struct.cpp (+12-12)
- (modified) clang/test/CIR/CodeGen/temp-param-obj-decl.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/three-way-cmp.cpp (+8-8)
- (modified) clang/test/CIR/CodeGen/var-arg-aggregate.c (+2-2)
- (modified) clang/test/CIR/CodeGen/variable-decomposition.cpp (+1-1)
- (modified) clang/test/CIR/CodeGenCXX/new-array-init.cpp (+9-9)
- (modified) clang/test/CIR/CodeGenCXX/sizeof-pack.cpp (+2-2)
- (modified) clang/test/CIR/CodeGenOpenACC/combined-firstprivate-clause.cpp (+6-6)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-firstprivate-clause-templates.cpp (+2-2)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-firstprivate-clause.c (+2-2)
- (modified) clang/test/CIR/CodeGenOpenACC/compute-firstprivate-clause.cpp (+6-6)
- (modified) clang/test/CIR/CodeGenOpenACC/firstprivate-clause-recipes.cpp (+3-3)
- (modified) clang/test/CIR/Lowering/array.cpp (+5-5)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index e1a5561ae11e1..f8a3aca76f102 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -377,8 +377,9 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
cir::CopyOp createCopy(mlir::Value dst, mlir::Value src,
bool isVolatile = false,
bool skipTailPadding = false) {
- return cir::CopyOp::create(*this, dst.getLoc(), dst, src, isVolatile,
- skipTailPadding);
+ return cir::CopyOp::create(*this, dst.getLoc(), dst, src,
+ /*dst_alignment=*/{}, /*src_alignment=*/{},
+ isVolatile, skipTailPadding);
}
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 7d1c48b994b27..67f81e44db0c0 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4616,13 +4616,19 @@ def CIR_CopyOp : CIR_Op<"copy",[
let arguments = (ins
Arg<CIR_PointerType, "", [MemWrite]>:$dst,
Arg<CIR_PointerType, "", [MemRead]>:$src,
+ OptionalAttr<I64Attr>:$dst_alignment,
+ OptionalAttr<I64Attr>:$src_alignment,
UnitAttr:$is_volatile,
UnitAttr:$skip_tail_padding
);
- let assemblyFormat = [{$src `to` $dst (`volatile` $is_volatile^)?
- (`skip_tail_padding` $skip_tail_padding^)?
- attr-dict `:` qualified(type($dst))
+ let assemblyFormat = [{
+ $src (`align` `(` $src_alignment^ `)`)?
+ `to`
+ $dst (`align` `(` $dst_alignment^ `)`)?
+ (`volatile` $is_volatile^)?
+ (`skip_tail_padding` $skip_tail_padding^)?
+ attr-dict `:` qualified(type($dst))
}];
let hasVerifier = 1;
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index cc1ff1e32521f..1de0e5e3bb8cb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -239,6 +239,16 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
// Operation creation helpers
// --------------------------
//
+ using CIRBaseBuilderTy::createCopy;
+ cir::CopyOp createCopy(Address dst, Address src, bool isVolatile = false,
+ bool skipTailPadding = false) {
+ cir::CopyOp op = createCopy(dst.getPointer(), src.getPointer(), isVolatile,
+ skipTailPadding);
+ op.setDstAlignment(dst.getAlignment().getQuantity());
+ op.setSrcAlignment(src.getAlignment().getQuantity());
+ 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);
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 4d54519e4d25f..fcccf6f8c5f68 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -1337,8 +1337,7 @@ void CIRGenFunction::emitAggregateCopy(LValue dest, LValue src, QualType ty,
// NOTE(cir): original codegen would normally convert destPtr and srcPtr to
// i8* since memcpy operates on bytes. We don't need that in CIR because
// cir.copy will operate on any CIR pointer that points to a sized type.
- builder.createCopy(destPtr.getPointer(), srcPtr.getPointer(), isVolatile,
- skipTailPadding);
+ builder.createCopy(destPtr, srcPtr, isVolatile, skipTailPadding);
assert(!cir::MissingFeatures::opTBAA());
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index e0fc9e58ed4b7..69f2c7ebd0fb5 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -216,8 +216,28 @@ mlir::LogicalResult CIRToLLVMCopyOpLowering::matchAndRewrite(
rewriter, op.getLoc(), rewriter.getI64Type(),
op.getCopySizeInBytes(layout));
assert(!cir::MissingFeatures::aggValueSlotVolatile());
+
+ uint64_t dstTypeAlign = dataLayout.getTypeABIAlignment(convertTypeForMemory(
+ *getTypeConverter(), dataLayout, op.getDst().getType().getPointee()));
+ uint64_t srcTypeAlign = dataLayout.getTypeABIAlignment(convertTypeForMemory(
+ *getTypeConverter(), dataLayout, op.getSrc().getType().getPointee()));
+
+ mlir::NamedAttribute dstAlignAttr = rewriter.getNamedAttr(
+ mlir::LLVM::LLVMDialect::getAlignAttrName(),
+ rewriter.getI64IntegerAttr(op.getDstAlignment().value_or(dstTypeAlign)));
+ mlir::NamedAttribute srcAlignAttr = rewriter.getNamedAttr(
+ mlir::LLVM::LLVMDialect::getAlignAttrName(),
+ rewriter.getI64IntegerAttr(op.getSrcAlignment().value_or(srcTypeAlign)));
+ mlir::ArrayAttr argAttrs = rewriter.getArrayAttr({
+ /*dst_attrs=*/rewriter.getDictionaryAttr({dstAlignAttr}),
+ /*src_attrs=*/rewriter.getDictionaryAttr({srcAlignAttr}),
+ });
+
rewriter.replaceOpWithNewOp<mlir::LLVM::MemcpyOp>(
- op, adaptor.getDst(), adaptor.getSrc(), length, op.getIsVolatile());
+ op, adaptor.getDst(), adaptor.getSrc(), length, op.getIsVolatile(),
+ /*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/abstract-cond.c b/clang/test/CIR/CodeGen/abstract-cond.c
index 00008ea876b7b..98fa2ac8dc0f4 100644
--- a/clang/test/CIR/CodeGen/abstract-cond.c
+++ b/clang/test/CIR/CodeGen/abstract-cond.c
@@ -19,9 +19,9 @@ int test_agg_cond(int a0, struct s6 a1, struct s6 a2) {
// CIR: %[[LOAD_A0:.*]] = cir.load{{.*}} %[[A0]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[COND:.*]] = cir.cast int_to_bool %[[LOAD_A0]] : !s32i -> !cir.bool
// CIR: cir.if %[[COND]] {
-// CIR: cir.copy %[[A1]] to %[[TMP]] : !cir.ptr<!rec_s6>
+// CIR: cir.copy %[[A1]] align(4) to %[[TMP]] align(4) : !cir.ptr<!rec_s6>
// CIR: } else {
-// CIR: cir.copy %[[A2]] to %[[TMP]] : !cir.ptr<!rec_s6>
+// CIR: cir.copy %[[A2]] align(4) to %[[TMP]] align(4) : !cir.ptr<!rec_s6>
// CIR: }
// CIR: cir.get_member %[[TMP]][0] {name = "f0"} : !cir.ptr<!rec_s6> -> !cir.ptr<!s32i>
@@ -30,10 +30,10 @@ int test_agg_cond(int a0, struct s6 a1, struct s6 a2) {
// LLVM: %[[COND:.*]] = icmp ne i32 %[[LOAD_A0]], 0
// LLVM: br i1 %[[COND]], label %[[A1_PATH:.*]], label %[[A2_PATH:.*]]
// LLVM: [[A1_PATH]]:
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[TMP:.*]], ptr {{.*}}, i64 4, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[TMP:.*]], ptr align 4 {{.*}}, i64 4, i1 false)
// LLVM: br label %[[EXIT:.*]]
// LLVM: [[A2_PATH]]:
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[TMP]], ptr {{.*}}, i64 4, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[TMP]], ptr align 4 {{.*}}, i64 4, i1 false)
// LLVM: br label %[[EXIT]]
// LLVM: [[EXIT]]:
// LLVM: getelementptr {{.*}}, ptr %[[TMP]], i32 0, i32 0
@@ -70,12 +70,12 @@ int test_stmt_expr(int flag, struct s6 a1, struct s6 a2) {
// CIR: %[[STMT_TMP:.*]] = cir.alloca "tmp" {{.*}} : !cir.ptr<!rec_s6>
// CIR: cir.scope {
// CIR: %[[T:.*]] = cir.alloca "t" {{.*}} init : !cir.ptr<!rec_s6>
-// CIR: cir.copy %[[A1]] to %[[T]] : !cir.ptr<!rec_s6>
+// CIR: cir.copy %[[A1]] align(4) to %[[T]] align(4) : !cir.ptr<!rec_s6>
// CIR: cir.call @foo() : () -> ()
-// CIR: cir.copy %[[T]] to %[[TMP]] : !cir.ptr<!rec_s6>
+// CIR: cir.copy %[[T]] align(4) to %[[TMP]] align(4) : !cir.ptr<!rec_s6>
// CIR: }
// CIR: } else {
-// CIR: cir.copy %[[A2]] to %[[TMP]] : !cir.ptr<!rec_s6>
+// CIR: cir.copy %[[A2]] align(4) to %[[TMP]] align(4) : !cir.ptr<!rec_s6>
// CIR: }
// CIR: cir.get_member %[[TMP]][0] {name = "f0"} : !cir.ptr<!rec_s6> -> !cir.ptr<!s32i>
@@ -86,14 +86,14 @@ int test_stmt_expr(int flag, struct s6 a1, struct s6 a2) {
// LLVM: [[TRUE]]:
// LLVM: br label %[[STMT_BODY:.*]]
// LLVM: [[STMT_BODY]]:
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[T:.*]], ptr {{.*}}, i64 4, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[T:.*]], ptr align 4 {{.*}}, i64 4, i1 false)
// LLVM: call void @foo()
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[TMP:.*]], ptr %[[T]], i64 4, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[TMP:.*]], ptr align 4 %[[T]], i64 4, i1 false)
// LLVM: br label %[[JOIN_FROM_TRUE:.*]]
// LLVM: [[JOIN_FROM_TRUE]]:
// LLVM: br label %[[EXIT:.*]]
// LLVM: [[FALSE]]:
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[TMP]], ptr {{.*}}, i64 4, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[TMP]], ptr align 4 {{.*}}, i64 4, i1 false)
// LLVM: br label %[[EXIT]]
// LLVM: [[EXIT]]:
// LLVM: getelementptr inbounds nuw %struct.s6, ptr %[[TMP]], i32 0, i32 0
diff --git a/clang/test/CIR/CodeGen/agg-atomic-cast.cpp b/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
index 12ed04f14edf2..450ad8752ef8f 100644
--- a/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
+++ b/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
@@ -16,11 +16,11 @@ void non_atomic_to_atomic_cast() {
// CIR: %[[S_ADDR:.*]] = cir.alloca "s" {{.*}} : !cir.ptr<!rec_S>
// CIR: %[[SA_ADDR:.*]] = cir.alloca "as" {{.*}} init : !cir.ptr<!rec_S>
-// CIR: cir.copy %[[S_ADDR]] to %[[SA_ADDR]] : !cir.ptr<!rec_S>
+// CIR: cir.copy %[[S_ADDR]] align(4) to %[[SA_ADDR]] align(16) : !cir.ptr<!rec_S>
// LLVM: %[[S_ADDR:.*]] = alloca %struct.S, i64 1, align 4
// LLVM: %[[SA_ADDR:.*]] = alloca %struct.S, i64 1, align 16
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[SA_ADDR]], ptr %[[S_ADDR]], i64 16, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[SA_ADDR]], ptr align 4 %[[S_ADDR]], i64 16, i1 false)
// OGCG: %[[S_ADDR:.*]] = alloca %struct.S, align 4
// OGCG: %[[SA_ADDR:.*]] = alloca %struct.S, align 16
diff --git a/clang/test/CIR/CodeGen/agg-expr-lvalue.c b/clang/test/CIR/CodeGen/agg-expr-lvalue.c
index 51109d3082ab0..0470f803e4f2b 100644
--- a/clang/test/CIR/CodeGen/agg-expr-lvalue.c
+++ b/clang/test/CIR/CodeGen/agg-expr-lvalue.c
@@ -37,7 +37,7 @@ void test_member_in_array(void) {
// LLVM-LABEL: define{{.*}} @test_member_in_array
// LLVM: %[[LINE:.*]] = alloca %struct.Line
// LLVM: %[[ARR:.*]] = alloca [1 x %struct.Point]
-// LLVM: call void @llvm.memcpy{{.*}}(ptr %[[LINE]], ptr @[[LINE_CONST]]
+// LLVM: call void @llvm.memcpy{{.*}}(ptr align 4 %[[LINE]], ptr align 4 @[[LINE_CONST]]
// LLVM: %[[MEMBER:.*]] = getelementptr{{.*}}%struct.Line{{.*}}%[[LINE]]{{.*}}i32 0, i32 0
// LLVM: call void @llvm.memcpy
@@ -111,7 +111,7 @@ void test_string_array_in_array(void) {
// LLVM-LABEL: define{{.*}} @test_string_array_in_array
// LLVM: %[[MATRIX:.*]] = alloca [2 x [6 x i8]]
-// LLVM: call void @llvm.memcpy{{.*}}(ptr %[[MATRIX]], ptr @[[MATRIX_CONST]]
+// LLVM: call void @llvm.memcpy{{.*}}(ptr align 1 %[[MATRIX]], ptr align 1 @[[MATRIX_CONST]]
// OGCG-LABEL: define{{.*}} @test_string_array_in_array
// OGCG: alloca [2 x [6 x i8]]
diff --git a/clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp b/clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp
index 4b60feba2c0d7..985ee6b1f75ad 100644
--- a/clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp
+++ b/clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp
@@ -35,11 +35,11 @@ struct Outer : virtual VBase {
// With virtual bases, only the C1 (complete) constructor is emitted.
// CIR-LABEL: cir.func {{.*}} @_ZN5OuterC1ERK10HasPaddingc(
-// CIR: cir.copy %{{.+}} to %{{.+}} skip_tail_padding : !cir.ptr<!rec_HasPadding>
+// CIR: cir.copy %{{.+}} align(4) to %{{.+}} align(8) skip_tail_padding : !cir.ptr<!rec_HasPadding>
// LLVM-LABEL: define {{.*}} void @_ZN5OuterC1ERK10HasPaddingc(
// LLVM: %[[GEP:.*]] = getelementptr inbounds nuw %struct.Outer, ptr %{{.+}}, i32 0, i32 1
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[GEP]], ptr %{{.+}}, i64 5, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[GEP]], ptr align 4 %{{.+}}, i64 5, i1 false)
// OGCG-LABEL: define {{.*}} void @_ZN5OuterC1ERK10HasPaddingc(
// OGCG: %[[GEP:.*]] = getelementptr inbounds nuw %struct.Outer, ptr %{{.+}}, i32 0, i32 1
@@ -58,11 +58,11 @@ struct NonOverlapping {
};
// CIR-LABEL: cir.func {{.*}} @_ZN14NonOverlappingC2ERK10HasPaddingc(
-// CIR: cir.copy %{{.+}} to %{{.+}} : !cir.ptr<!rec_HasPadding>
+// CIR: cir.copy %{{.+}} align(4) to %{{.+}} align(4) : !cir.ptr<!rec_HasPadding>
// LLVM-LABEL: define {{.*}} void @_ZN14NonOverlappingC2ERK10HasPaddingc(
// LLVM: %[[GEP:.*]] = getelementptr inbounds nuw %struct.NonOverlapping, ptr %{{.+}}, i32 0, i32 0
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[GEP]], ptr %{{.+}}, i64 8, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[GEP]], ptr align 4 %{{.+}}, i64 8, i1 false)
// OGCG-LABEL: define {{.*}} void @_ZN14NonOverlappingC2ERK10HasPaddingc(
// OGCG: %[[GEP:.*]] = getelementptr inbounds nuw %struct.NonOverlapping, ptr %{{.+}}, i32 0, i32 0
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
index 5d288ad91a576..d3149988b3213 100644
--- a/clang/test/CIR/CodeGen/array.cpp
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -187,7 +187,7 @@ void func2() {
// LLVM: define{{.*}} void @_Z5func2v(){{.*}}
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[ARR]], ptr @[[FUNC2_ARR:.*]], i64 8, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUNC2_ARR:.*]], i64 8, i1 false)
// OGCG: %[[ARR:.*]] = alloca [2 x i32], align 4
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUN2_ARR]], i64 8, i1 false)
@@ -216,7 +216,7 @@ void func3() {
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
// LLVM: %[[IDX:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[ARR]], ptr @[[FUNC3_ARR:.*]], i64 8, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUNC3_ARR:.*]], i64 8, i1 false)
// LLVM: store i32 1, ptr %[[IDX]], align 4
// LLVM: %[[TMP1:.*]] = load i32, ptr %[[IDX]], align 4
// LLVM: %[[IDX_I64:.*]] = sext i32 %[[TMP1]] to i64
@@ -254,7 +254,7 @@ void func4() {
// LLVM: define{{.*}} void @_Z5func4v(){{.*}}
// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[ARR]], ptr @[[FUNC4_ARR:.*]], i64 8, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUNC4_ARR:.*]], i64 8, i1 false)
// LLVM: %[[ARR_1:.*]] = getelementptr [2 x [1 x i32]], ptr %[[ARR]], i32 0, i64 1
// LLVM: %[[ELE_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_1]], i32 0, i64 0
// LLVM: %[[TMP:.*]] = load i32, ptr %[[ELE_PTR]], align 4
@@ -278,7 +278,7 @@ void func5() {
// LLVM: define{{.*}} void @_Z5func5v(){{.*}}
// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[ARR]], ptr @[[FUNC5_ARR:.*]], i64 8, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUNC5_ARR:.*]], i64 8, i1 false)
// OGCG: %[[ARR:.*]] = alloca [2 x [1 x i32]], align 4
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUN5_ARR]], i64 8, i1 false)
@@ -328,7 +328,7 @@ void func7() {
// LLVM: define{{.*}} void @_Z5func7v(){{.*}}
// LLVM: %[[ARR:.*]] = alloca [1 x ptr], i64 1, align 8
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[ARR]], ptr @[[FUNC7_ARR:.*]], i64 8, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[ARR]], ptr align 8 @[[FUNC7_ARR:.*]], i64 8, i1 false)
// OGCG: %[[ARR:.*]] = alloca [1 x ptr], align 8
// OGCG: call void @llvm.memset.p0.i64(ptr align 8 %[[ARR]], i8 0, i64 8, i1 false)
@@ -479,7 +479,7 @@ void array_with_complex_elements() {
// CIR: cir.copy %[[CONST]] to %[[ARR_ADDR]] : !cir.ptr<!cir.array<!cir.complex<!cir.float> x 2>>
// LLVM: %[[ARR_ADDR:.*]] = alloca [2 x { float, float }], i64 1, align 16
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[ARR_ADDR]], ptr @[[COMPLEX_ARR:.*]], i64 16, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR_ADDR]], ptr align 4 @[[COMPLEX_ARR:.*]], i64 16, i1 false)
// OGCG: %[[ARR_ADDR:.*]] = alloca [2 x { float, float }], align 16
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[ARR_ADDR]], ptr align 16 @__const._Z27array_with_complex_elementsv.arr, i64 16, i1 false)
diff --git a/clang/test/CIR/CodeGen/atomic-libcall.c b/clang/test/CIR/CodeGen/atomic-libcall.c
index 53685dd1b543d..f7f0e89767a9d 100644
--- a/clang/test/CIR/CodeGen/atomic-libcall.c
+++ b/clang/test/CIR/CodeGen/atomic-libcall.c
@@ -67,7 +67,7 @@ void c11_load(_Atomic(struct Big) *ptr) {
// CIR-NEXT: %[[ORDER:.+]] = cir.const #cir.int<0> : !s32i
// CIR-NEXT: cir.call @__atomic_load(%[[SIZE]], %[[PTR_VOIDPTR]], %[[TEMP_VOIDPTR]], %[[ORDER]]) : (!u64i {llvm.noundef}, !cir.ptr<!void> {llvm.noundef}, !cir.ptr<!void> {llvm.noundef}, !s32i {llvm.noundef}) -> ()
// CIR-NEXT: %[[TEMP_CAST:.+]] = cir.cast bitcast %[[TEMP_INTPTR]] : !cir.ptr<!cir.int<u, 192>> -> !cir.ptr<!rec_Big>
- // CIR-NEXT: cir.copy %[[TEMP_CAST]] to %[[DEST_SLOT]] : !cir.ptr<!rec_Big>
+ // CIR-NEXT: cir.copy %[[TEMP_CAST]] align(4) to %[[DEST_SLOT]] align(4) : !cir.ptr<!rec_Big>
// LLVM: %[[DEST_SLOT:.+]] = alloca %struct.Big
// LLVM-NEXT: %[[TEMP_SLOT:.+]] = alloca %struct.Big
@@ -123,7 +123,7 @@ void c11_store(_Atomic(struct Big) *dest, struct Big *val) {
__c11_atomic_store(dest, *val, __ATOMIC_RELAXED);
// CIR: %[[DEST_PTR:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!cir.ptr<!rec_Big>>, !cir.ptr<!rec_Big>
// CIR-NEXT: %[[VALUE_PTR:.+]] = cir.load deref align(8) %{{.+}} : !cir.ptr<!cir.ptr<!rec_Big>>, !cir.ptr<!rec_Big>
- // CIR-NEXT: cir.copy %[[VALUE_PTR]] to %[[TEMP_SLOT:.+]] : !cir.ptr<!rec_Big>
+ // CIR-NEXT: cir.copy %[[VALUE_PTR]] align(4) to %[[TEMP_SLOT:.+]] align(4) : !cir.ptr<!rec_Big>
// CIR-NEXT: %[[DEST_INTPTR:.+]] = cir.cast bitcast %[[DEST_PTR]] : !cir.ptr<!rec_Big> -> !cir.ptr<!cir.int<u, 192>>
// CIR-NEXT: %[[VALUE_INTPTR:.+]] = cir.cast bitcast %[[TEMP_SLOT]] : !cir.ptr<!rec_Big> -> !cir.ptr<!cir.int<u, 192>>
// CIR-NEXT: %[[SIZE:.+]] = cir.const #cir.int<24> : !u64i
diff --git a/clang/test/CIR/CodeGen/binassign.c b/clang/test/CIR/CodeGen/binassign.c
index b650211646623..13ef5b7db0555 100644
--- a/clang/test/CIR/CodeGen/binassign.c
+++ b/clang/test/CIR/CodeGen/binassign.c
@@ -81,16 +81,16 @@ void binary_assign_struct() {
// CIR: %[[LS:.*]] = cir.alloca "ls" {{.*}} : !cir.ptr<![[REC_S:.*]]>
// CIR: %[[LSV:.*]] = cir.alloca "lsv" {{.*}} : !cir.ptr<![[REC_SV:.*]]>
// CIR: %[[GS_PTR:.*]] = cir.get_global @gs : !cir.ptr<![[REC_S]]>
-// CIR: cir.copy %[[GS_PTR]] to %[[LS]] : !cir.ptr<![[REC_S]]>
+// CIR: cir.copy %[[GS_PTR]] align(4) to %[[LS]] align(4) : !cir.ptr<![[REC_S]]>
// CIR: %[[GSV_PTR:.*]] = cir.get_global @gsv : !cir.ptr<![[REC_SV]]>
-// CIR: cir.copy %[[GSV_PTR]] to %[[LSV]] volatile : !cir.ptr<![[REC_SV]]>
+// CIR: cir.copy %[[GSV_PTR]] align(4) to %[[LSV]] align(4) volatile : !cir.ptr<![[REC_SV]]>
// CIR: cir.return
// LLVM: define {{.*}}void @binary_assign_struct()
// LLVM: %[[LS_PTR:.*]] = alloca %struct.S
// LLVM: %[[LSV_PTR:.*]] = alloca %struct.SV
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[LS_PTR]], ptr @gs, i64 8, i1 false)
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[LSV_PTR]], ptr @gsv, i64 8, i1 true)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[LS_PTR]], ptr align 4 @gs, i64 8, i1 false)
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[LSV_PTR]], ptr align 4 @gsv, i64 8, i1 true)
// LLVM: ret void
// OGCG: define {{.*}}void @binary_assign_...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/206341
More information about the cfe-commits
mailing list