From a25d15f7ab1953934fb89e6aeb25e00c80ca5f35 Mon Sep 17 00:00:00 2001 From: ghehg Date: Wed, 6 Nov 2024 07:45:24 -0800 Subject: [PATCH 1/5] Implement __builtin_memcpy_inline --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 25 +++++++++++ clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 20 ++++++++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 27 ++++++++++-- clang/test/CIR/CodeGen/builtins-memory.c | 41 +++++++++++++++++++ 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index a48a99ba95e0..9fa7e75c6b98 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4040,6 +4040,30 @@ def MemCpyOp : CIR_MemCpyOp<"libc.memcpy"> { }]; } +def MemCpyInlineOp : CIR_MemCpyOp<"memcpy_inline"> { + let summary = "Represent builtin function `__builtin_memcpy_inline`"; + let description = [{ + Given two CIR pointers, `src` and `dst`, `memcpy_inline` will copy `len` + bytes from the memory pointed by `src` to the memory pointed by `dst`. + + Unlike `cir.libc.memcpy`, this Op guarantees that no external functions + are called. + + Examples: + + ```mlir + // Copying 2 bytes from one array to a struct: + %2 = cir.const #cir.int<2> : !u32i + cir.memcpy_inline %2 bytes from %arr to %struct : !cir.ptr -> !cir.ptr + ``` + }]; + + let assemblyFormat = [{ + $len `bytes` `from` $src `to` $dst attr-dict + `:` type($len) `` `,` qualified(type($src)) `->` qualified(type($dst)) + }]; +} + def MemMoveOp : CIR_MemCpyOp<"libc.memmove"> { let summary = "Equivalent to libc's `memmove`"; let description = [{ @@ -4063,6 +4087,7 @@ def MemMoveOp : CIR_MemCpyOp<"libc.memmove"> { `:` qualified(type($dst)) `,` type($len) }]; } + //===----------------------------------------------------------------------===// // MemSetOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 6809c3ad5ce3..499f2aaff2d9 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1408,8 +1408,24 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(Dest.getPointer()); } - case Builtin::BI__builtin_memcpy_inline: - llvm_unreachable("BI__builtin_memcpy_inline NYI"); + case Builtin::BI__builtin_memcpy_inline: { + Address dest = buildPointerWithAlignment(E->getArg(0)); + Address src = buildPointerWithAlignment(E->getArg(1)); + buildNonNullArgCheck(RValue::get(dest.getPointer()), + E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), + FD, 0); + buildNonNullArgCheck(RValue::get(src.getPointer()), E->getArg(1)->getType(), + E->getArg(1)->getExprLoc(), FD, 1); + uint64_t size = + E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); + auto lenOp = + builder.getConstInt(getLoc(E->getSourceRange()), UInt64Ty, size); + builder.create(getLoc(E->getSourceRange()), + dest.getPointer(), + src.getPointer(), lenOp); + // __builtin_memcpy_inline has no return value + return RValue::get(nullptr); + } case Builtin::BI__builtin_char_memchr: case Builtin::BI__builtin_memchr: { diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 2ae12be6efbd..4311b6d2d5bd 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -778,7 +778,28 @@ class CIRMemChrOpLowering : public mlir::OpConversionPattern { } }; -class CIRMemMoveOpLowering : public mlir::OpConversionPattern { +class CIRMemCpyInlineOpLowering + : public mlir::OpConversionPattern { +public: + using mlir::OpConversionPattern< + mlir::cir::MemCpyInlineOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(mlir::cir::MemCpyInlineOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + auto lenOp = mlir::cast(op.getLen().getDefiningOp()); + rewriter.replaceOpWithNewOp( + op, adaptor.getDst(), adaptor.getSrc(), + rewriter.getIntegerAttr( + getTypeConverter()->convertType(lenOp.getType()), + mlir::cast(lenOp.getValue()).getValue()), + /*isVolatile=*/false); + return mlir::success(); + } +}; + +class CIRMemMoveOpLowering + : public mlir::OpConversionPattern { public: using mlir::OpConversionPattern::OpConversionPattern; @@ -4331,8 +4352,8 @@ void populateCIRToLLVMConversionPatterns( CIRVAStartLowering, CIRVAEndLowering, CIRVACopyLowering, CIRVAArgLowering, CIRBrOpLowering, CIRGetMemberOpLowering, CIRGetRuntimeMemberOpLowering, CIRSwitchFlatOpLowering, CIRPtrDiffOpLowering, CIRCopyOpLowering, - CIRMemCpyOpLowering, CIRMemChrOpLowering, CIRFAbsOpLowering, - CIRExpectOpLowering, CIRVTableAddrPointOpLowering, + CIRMemCpyOpLowering, CIRMemChrOpLowering, CIRMemCpyInlineOpLowering, + CIRFAbsOpLowering, CIRExpectOpLowering, CIRVTableAddrPointOpLowering, CIRVectorCreateLowering, CIRVectorCmpOpLowering, CIRVectorSplatLowering, CIRVectorTernaryLowering, CIRVectorShuffleIntsLowering, CIRVectorShuffleVecLowering, CIRStackSaveLowering, CIRUnreachableLowering, diff --git a/clang/test/CIR/CodeGen/builtins-memory.c b/clang/test/CIR/CodeGen/builtins-memory.c index 439b82e98d33..4bcb1e64db51 100644 --- a/clang/test/CIR/CodeGen/builtins-memory.c +++ b/clang/test/CIR/CodeGen/builtins-memory.c @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir // RUN: FileCheck %s --check-prefix=CIR --input-file=%t.cir +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - \ +// RUN: | opt -S -passes=instcombine,mem2reg,simplifycfg -o %t.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s typedef __SIZE_TYPE__ size_t; void test_memcpy_chk(void *dest, const void *src, size_t n) { @@ -107,3 +110,41 @@ void test_memset_chk(void *dest, int ch, size_t n) { // CIR: cir.call @__memset_chk(%[[#DEST_LOAD]], %[[#CH_LOAD]], %[[#N_LOAD1]], %[[#N_LOAD2]]) __builtin___memset_chk(dest, ch, n, n); } + +// TODO: The test should test intrinsic argument alignment, however, +// currently we lack support for argument attributes. +// Thus, added COM lines as a marker to remind us to change the test +// when the support of argument attributes is in. +void test_memcpy_inline(void *dst, const void *src, size_t n) { + + // CIR-LABEL: test_memcpy_inline + // CIR: [[SIZE0:%.*]] = cir.const #cir.int<0> : !u64i + // CIR: cir.memcpy_inline [[SIZE0]] bytes from {{%.*}} to {{%.*}} : !u64i, !cir.ptr -> !cir.ptr + + // LLVM-LABEL: test_memcpy_inline + // LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr {{%.*}}, ptr {{%.*}}, i64 0, i1 false) + // COM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 0, i1 false) + __builtin_memcpy_inline(dst, src, 0); + + // CIR: [[SIZE1:%.*]] = cir.const #cir.int<1> : !u64i + // CIR: cir.memcpy_inline [[SIZE1]] bytes from {{%.*}} to {{%.*}} : !u64i, !cir.ptr -> !cir.ptr + + // LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr {{%.*}}, ptr {{%.*}}, i64 1, i1 false) + // COM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 1, i1 false) + __builtin_memcpy_inline(dst, src, 1); + + // CIR: [[SIZE4:%.*]] = cir.const #cir.int<4> : !u64i + // CIR: cir.memcpy_inline [[SIZE4]] bytes from {{%.*}} to {{%.*}} : !u64i, !cir.ptr -> !cir.ptr + + // LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr {{%.*}}, ptr {{%.*}}, i64 4, i1 false) + // COM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 4, i1 false) + __builtin_memcpy_inline(dst, src, 4); +} + +void test_memcpy_inline_aligned_buffers(unsigned long long *dst, const unsigned long long *src) { + + // LLVM-LABEL: test_memcpy_inline_aligned_buffers + // LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr {{%.*}}, ptr {{%.*}}, i64 4, i1 false) + // COM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 {{%.*}}, ptr align 8 {{%.*}}, i64 4, i1 false) + __builtin_memcpy_inline(dst, src, 4); +} From 0baf9233c125a6edd883ace75c782de81355c03e Mon Sep 17 00:00:00 2001 From: ghehg Date: Sat, 9 Nov 2024 09:10:25 -0800 Subject: [PATCH 2/5] Address review comments, make MemCpyInline more like LLVM Dialect counterpart --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 36 +++++++++++-------- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 9 +++-- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 +--- clang/test/CIR/CodeGen/builtins-memory.c | 21 +++++------ 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 9fa7e75c6b98..e7370e18d80e 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4040,51 +4040,57 @@ def MemCpyOp : CIR_MemCpyOp<"libc.memcpy"> { }]; } -def MemCpyInlineOp : CIR_MemCpyOp<"memcpy_inline"> { - let summary = "Represent builtin function `__builtin_memcpy_inline`"; +def MemMoveOp : CIR_MemCpyOp<"libc.memmove"> { + let summary = "Equivalent to libc's `memmove`"; let description = [{ - Given two CIR pointers, `src` and `dst`, `memcpy_inline` will copy `len` + Given two CIR pointers, `src` and `dst`, `cir.libc.memmove` will copy `len` bytes from the memory pointed by `src` to the memory pointed by `dst`. - Unlike `cir.libc.memcpy`, this Op guarantees that no external functions - are called. + similiar to `cir.libc.memcpy` but accounts for overlapping memory. Examples: ```mlir // Copying 2 bytes from one array to a struct: %2 = cir.const #cir.int<2> : !u32i - cir.memcpy_inline %2 bytes from %arr to %struct : !cir.ptr -> !cir.ptr + cir.libc.memmove %2 bytes from %arr to %struct : !cir.ptr, !u64i ``` }]; + let assemblyFormat = [{ $len `bytes` `from` $src `to` $dst attr-dict - `:` type($len) `` `,` qualified(type($src)) `->` qualified(type($dst)) + `:` qualified(type($dst)) `,` type($len) }]; } -def MemMoveOp : CIR_MemCpyOp<"libc.memmove"> { - let summary = "Equivalent to libc's `memmove`"; +//===----------------------------------------------------------------------===// +// MemCpyInlineOp +//===----------------------------------------------------------------------===// +def MemCpyInlineOp : CIR_Op<"memcpy_inline"> { + let arguments = (ins Arg:$dst, + Arg:$src, + I64Attr:$len); + let summary = "Memory copy with constant length without calling" + "any external function"; let description = [{ - Given two CIR pointers, `src` and `dst`, `cir.libc.memmove` will copy `len` + Given two CIR pointers, `src` and `dst`, `memcpy_inline` will copy `len` bytes from the memory pointed by `src` to the memory pointed by `dst`. - similiar to `cir.libc.memcpy` but accounts for overlapping memory. + Unlike `cir.libc.memcpy`, this Op guarantees that no external functions + are called, and length of copied bytes is a constant. Examples: ```mlir // Copying 2 bytes from one array to a struct: - %2 = cir.const #cir.int<2> : !u32i - cir.libc.memmove %2 bytes from %arr to %struct : !cir.ptr, !u64i + cir.memcpy_inline 2 bytes from %arr to %struct : !cir.ptr -> !cir.ptr ``` }]; - let assemblyFormat = [{ $len `bytes` `from` $src `to` $dst attr-dict - `:` qualified(type($dst)) `,` type($len) + `:` qualified(type($src)) `->` qualified(type($dst)) }]; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 499f2aaff2d9..364bc172a883 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1418,11 +1418,10 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, E->getArg(1)->getExprLoc(), FD, 1); uint64_t size = E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); - auto lenOp = - builder.getConstInt(getLoc(E->getSourceRange()), UInt64Ty, size); - builder.create(getLoc(E->getSourceRange()), - dest.getPointer(), - src.getPointer(), lenOp); + builder.create( + getLoc(E->getSourceRange()), dest.getPointer(), src.getPointer(), + mlir::IntegerAttr::get(mlir::IntegerType::get(builder.getContext(), 64), + size)); // __builtin_memcpy_inline has no return value return RValue::get(nullptr); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 4311b6d2d5bd..6e556a7589f8 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -787,12 +787,8 @@ class CIRMemCpyInlineOpLowering mlir::LogicalResult matchAndRewrite(mlir::cir::MemCpyInlineOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - auto lenOp = mlir::cast(op.getLen().getDefiningOp()); rewriter.replaceOpWithNewOp( - op, adaptor.getDst(), adaptor.getSrc(), - rewriter.getIntegerAttr( - getTypeConverter()->convertType(lenOp.getType()), - mlir::cast(lenOp.getValue()).getValue()), + op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLenAttr(), /*isVolatile=*/false); return mlir::success(); } diff --git a/clang/test/CIR/CodeGen/builtins-memory.c b/clang/test/CIR/CodeGen/builtins-memory.c index 4bcb1e64db51..940e09a8ed6d 100644 --- a/clang/test/CIR/CodeGen/builtins-memory.c +++ b/clang/test/CIR/CodeGen/builtins-memory.c @@ -111,33 +111,30 @@ void test_memset_chk(void *dest, int ch, size_t n) { __builtin___memset_chk(dest, ch, n, n); } -// TODO: The test should test intrinsic argument alignment, however, +// FIXME: The test should test intrinsic argument alignment, however, // currently we lack support for argument attributes. -// Thus, added COM lines as a marker to remind us to change the test +// Thus, added `COM: LLVM:` lines so we can easily flip the test // when the support of argument attributes is in. void test_memcpy_inline(void *dst, const void *src, size_t n) { // CIR-LABEL: test_memcpy_inline - // CIR: [[SIZE0:%.*]] = cir.const #cir.int<0> : !u64i - // CIR: cir.memcpy_inline [[SIZE0]] bytes from {{%.*}} to {{%.*}} : !u64i, !cir.ptr -> !cir.ptr + // CIR: cir.memcpy_inline 0 bytes from {{%.*}} to {{%.*}} : !cir.ptr -> !cir.ptr // LLVM-LABEL: test_memcpy_inline // LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr {{%.*}}, ptr {{%.*}}, i64 0, i1 false) - // COM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 0, i1 false) + // COM: LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 0, i1 false) __builtin_memcpy_inline(dst, src, 0); - // CIR: [[SIZE1:%.*]] = cir.const #cir.int<1> : !u64i - // CIR: cir.memcpy_inline [[SIZE1]] bytes from {{%.*}} to {{%.*}} : !u64i, !cir.ptr -> !cir.ptr + // CIR: cir.memcpy_inline 1 bytes from {{%.*}} to {{%.*}} : !cir.ptr -> !cir.ptr // LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr {{%.*}}, ptr {{%.*}}, i64 1, i1 false) - // COM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 1, i1 false) + // COM: LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 1, i1 false) __builtin_memcpy_inline(dst, src, 1); - // CIR: [[SIZE4:%.*]] = cir.const #cir.int<4> : !u64i - // CIR: cir.memcpy_inline [[SIZE4]] bytes from {{%.*}} to {{%.*}} : !u64i, !cir.ptr -> !cir.ptr + // CIR: cir.memcpy_inline 4 bytes from {{%.*}} to {{%.*}} : !cir.ptr -> !cir.ptr // LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr {{%.*}}, ptr {{%.*}}, i64 4, i1 false) - // COM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 4, i1 false) + // COM: LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 {{%.*}}, ptr align 1 {{%.*}}, i64 4, i1 false) __builtin_memcpy_inline(dst, src, 4); } @@ -145,6 +142,6 @@ void test_memcpy_inline_aligned_buffers(unsigned long long *dst, const unsigned // LLVM-LABEL: test_memcpy_inline_aligned_buffers // LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr {{%.*}}, ptr {{%.*}}, i64 4, i1 false) - // COM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 {{%.*}}, ptr align 8 {{%.*}}, i64 4, i1 false) + // COM: LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 {{%.*}}, ptr align 8 {{%.*}}, i64 4, i1 false) __builtin_memcpy_inline(dst, src, 4); } From 52789e28755e0fe50739d4c85690904f679ad3da Mon Sep 17 00:00:00 2001 From: ghehg Date: Sat, 9 Nov 2024 09:21:55 -0800 Subject: [PATCH 3/5] rebase --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 10 +++++----- clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 364bc172a883..47b630010884 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1409,16 +1409,16 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } case Builtin::BI__builtin_memcpy_inline: { - Address dest = buildPointerWithAlignment(E->getArg(0)); - Address src = buildPointerWithAlignment(E->getArg(1)); - buildNonNullArgCheck(RValue::get(dest.getPointer()), + Address dest = emitPointerWithAlignment(E->getArg(0)); + Address src = emitPointerWithAlignment(E->getArg(1)); + emitNonNullArgCheck(RValue::get(dest.getPointer()), E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), FD, 0); - buildNonNullArgCheck(RValue::get(src.getPointer()), E->getArg(1)->getType(), + emitNonNullArgCheck(RValue::get(src.getPointer()), E->getArg(1)->getType(), E->getArg(1)->getExprLoc(), FD, 1); uint64_t size = E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); - builder.create( + builder.create( getLoc(E->getSourceRange()), dest.getPointer(), src.getPointer(), mlir::IntegerAttr::get(mlir::IntegerType::get(builder.getContext(), 64), size)); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 6e556a7589f8..459a71b45bd3 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -779,13 +779,13 @@ class CIRMemChrOpLowering : public mlir::OpConversionPattern { }; class CIRMemCpyInlineOpLowering - : public mlir::OpConversionPattern { + : public mlir::OpConversionPattern { public: using mlir::OpConversionPattern< - mlir::cir::MemCpyInlineOp>::OpConversionPattern; + cir::MemCpyInlineOp>::OpConversionPattern; mlir::LogicalResult - matchAndRewrite(mlir::cir::MemCpyInlineOp op, OpAdaptor adaptor, + matchAndRewrite(cir::MemCpyInlineOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { rewriter.replaceOpWithNewOp( op, adaptor.getDst(), adaptor.getSrc(), adaptor.getLenAttr(), @@ -795,7 +795,7 @@ class CIRMemCpyInlineOpLowering }; class CIRMemMoveOpLowering - : public mlir::OpConversionPattern { + : public mlir::OpConversionPattern { public: using mlir::OpConversionPattern::OpConversionPattern; From fd6028207e44ea808ea92c32b53554d1231586c5 Mon Sep 17 00:00:00 2001 From: ghehg Date: Sat, 9 Nov 2024 09:22:15 -0800 Subject: [PATCH 4/5] rebase --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 7 ++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 48 +++++++++---------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 47b630010884..b15549547ea1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1411,11 +1411,10 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_memcpy_inline: { Address dest = emitPointerWithAlignment(E->getArg(0)); Address src = emitPointerWithAlignment(E->getArg(1)); - emitNonNullArgCheck(RValue::get(dest.getPointer()), - E->getArg(0)->getType(), E->getArg(0)->getExprLoc(), - FD, 0); + emitNonNullArgCheck(RValue::get(dest.getPointer()), E->getArg(0)->getType(), + E->getArg(0)->getExprLoc(), FD, 0); emitNonNullArgCheck(RValue::get(src.getPointer()), E->getArg(1)->getType(), - E->getArg(1)->getExprLoc(), FD, 1); + E->getArg(1)->getExprLoc(), FD, 1); uint64_t size = E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue(); builder.create( diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 459a71b45bd3..d0fa5fe9afa1 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -781,8 +781,7 @@ class CIRMemChrOpLowering : public mlir::OpConversionPattern { class CIRMemCpyInlineOpLowering : public mlir::OpConversionPattern { public: - using mlir::OpConversionPattern< - cir::MemCpyInlineOp>::OpConversionPattern; + using mlir::OpConversionPattern::OpConversionPattern; mlir::LogicalResult matchAndRewrite(cir::MemCpyInlineOp op, OpAdaptor adaptor, @@ -794,8 +793,7 @@ class CIRMemCpyInlineOpLowering } }; -class CIRMemMoveOpLowering - : public mlir::OpConversionPattern { +class CIRMemMoveOpLowering : public mlir::OpConversionPattern { public: using mlir::OpConversionPattern::OpConversionPattern; @@ -4393,27 +4391,27 @@ std::unique_ptr prepareLowerModule(mlir::ModuleOp module) { void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout, cir::LowerModule *lowerModule) { - converter.addConversion([&, - lowerModule](cir::PointerType type) -> mlir::Type { - // Drop pointee type since LLVM dialect only allows opaque pointers. - - auto addrSpace = - mlir::cast_if_present(type.getAddrSpace()); - // Null addrspace attribute indicates the default addrspace. - if (!addrSpace) - return mlir::LLVM::LLVMPointerType::get(type.getContext()); - - assert(lowerModule && "CIR AS map is not available"); - // Pass through target addrspace and map CIR addrspace to LLVM addrspace by - // querying the target info. - unsigned targetAS = - addrSpace.isTarget() - ? addrSpace.getTargetValue() - : lowerModule->getTargetLoweringInfo() - .getTargetAddrSpaceFromCIRAddrSpace(addrSpace); - - return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS); - }); + converter.addConversion( + [&, lowerModule](cir::PointerType type) -> mlir::Type { + // Drop pointee type since LLVM dialect only allows opaque pointers. + + auto addrSpace = + mlir::cast_if_present(type.getAddrSpace()); + // Null addrspace attribute indicates the default addrspace. + if (!addrSpace) + return mlir::LLVM::LLVMPointerType::get(type.getContext()); + + assert(lowerModule && "CIR AS map is not available"); + // Pass through target addrspace and map CIR addrspace to LLVM addrspace + // by querying the target info. + unsigned targetAS = + addrSpace.isTarget() + ? addrSpace.getTargetValue() + : lowerModule->getTargetLoweringInfo() + .getTargetAddrSpaceFromCIRAddrSpace(addrSpace); + + return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS); + }); converter.addConversion([&](cir::DataMemberType type) -> mlir::Type { return mlir::IntegerType::get(type.getContext(), dataLayout.getTypeSizeInBits(type)); From 8600ca344c6f276b29c8931c8202484b53ef3aa1 Mon Sep 17 00:00:00 2001 From: ghehg Date: Sat, 9 Nov 2024 17:40:08 -0800 Subject: [PATCH 5/5] MemCpyInlineOp inherits from CIR_MemOp --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 40 ++++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index e7370e18d80e..8db92f967214 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4003,19 +4003,14 @@ def CopyOp : CIR_Op<"copy", // MemCpyOp && MemMoveOp //===----------------------------------------------------------------------===// -class CIR_MemCpyOp: CIR_Op]> { - let arguments = (ins Arg:$dst, - Arg:$src, - PrimitiveUInt:$len); +class CIR_MemOp + : CIR_Op]> { + dag commonArgs = (ins Arg:$dst, + Arg:$src); let hasVerifier = 0; - - let extraClassDeclaration = [{ - /// Returns the byte length type. - cir::IntType getLenTy() { return getLen().getType(); } - }]; } -def MemCpyOp : CIR_MemCpyOp<"libc.memcpy"> { +def MemCpyOp : CIR_MemOp<"libc.memcpy"> { let summary = "Equivalent to libc's `memcpy`"; let description = [{ Given two CIR pointers, `src` and `dst`, `cir.libc.memcpy` will copy `len` @@ -4034,13 +4029,20 @@ def MemCpyOp : CIR_MemCpyOp<"libc.memcpy"> { ``` }]; + let arguments = !con(commonArgs, (ins PrimitiveUInt:$len)); + let assemblyFormat = [{ $len `bytes` `from` $src `to` $dst attr-dict `:` type($len) `` `,` qualified(type($src)) `->` qualified(type($dst)) }]; + + let extraClassDeclaration = [{ + /// Returns the byte length type. + cir::IntType getLenTy() { return getLen().getType(); } + }]; } -def MemMoveOp : CIR_MemCpyOp<"libc.memmove"> { +def MemMoveOp : CIR_MemOp<"libc.memmove"> { let summary = "Equivalent to libc's `memmove`"; let description = [{ Given two CIR pointers, `src` and `dst`, `cir.libc.memmove` will copy `len` @@ -4057,21 +4059,25 @@ def MemMoveOp : CIR_MemCpyOp<"libc.memmove"> { ``` }]; + let arguments = !con(commonArgs, (ins PrimitiveUInt:$len)); let assemblyFormat = [{ $len `bytes` `from` $src `to` $dst attr-dict `:` qualified(type($dst)) `,` type($len) }]; + + let extraClassDeclaration = [{ + /// Returns the byte length type. + cir::IntType getLenTy() { return getLen().getType(); } + }]; } //===----------------------------------------------------------------------===// // MemCpyInlineOp //===----------------------------------------------------------------------===// -def MemCpyInlineOp : CIR_Op<"memcpy_inline"> { - let arguments = (ins Arg:$dst, - Arg:$src, - I64Attr:$len); - let summary = "Memory copy with constant length without calling" + +def MemCpyInlineOp : CIR_MemOp<"memcpy_inline"> { + let summary = "Memory copy with constant length without calling" "any external function"; let description = [{ Given two CIR pointers, `src` and `dst`, `memcpy_inline` will copy `len` @@ -4088,6 +4094,8 @@ def MemCpyInlineOp : CIR_Op<"memcpy_inline"> { ``` }]; + let arguments = !con(commonArgs, (ins I64Attr:$len)); + let assemblyFormat = [{ $len `bytes` `from` $src `to` $dst attr-dict `:` qualified(type($src)) `->` qualified(type($dst))