https://github.com/adams381 updated https://github.com/llvm/llvm-project/pull/175234
>From 2866f4c2ba59fcc470e9e7273ade35eb5ab03212 Mon Sep 17 00:00:00 2001 From: Adam Smith <[email protected]> Date: Fri, 9 Jan 2026 11:54:53 -0800 Subject: [PATCH] [CIR] Add MemChrOp for __builtin_char_memchr and __builtin_memchr Add support for the memchr builtin functions: - Define CIR_MemChrOp (cir.libc.memchr) in CIROps.td - Add builtin handling in CIRGenBuiltin.cpp - Add LLVM lowering in LowerToLLVM.cpp - Add CodeGen and IR tests --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 31 +++++++++++++++++++ clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 12 ++++++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 20 ++++++++++++ clang/test/CIR/CodeGen/builtin-memchr.c | 23 ++++++++++++++ clang/test/CIR/IR/libc-memchr.cir | 12 +++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 clang/test/CIR/CodeGen/builtin-memchr.c create mode 100644 clang/test/CIR/IR/libc-memchr.cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index e2b582c5c55df..4c9c656eb254b 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5906,4 +5906,35 @@ def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> { }]; } +//===----------------------------------------------------------------------===// +// MemChrOp +//===----------------------------------------------------------------------===// + +def CIR_MemChrOp : CIR_Op<"libc.memchr"> { + let summary = "libc's `memchr`"; + let description = [{ + Search for `pattern` in data range from `src` to `src` + `len`. + `len` provides a bound to the search in `src`. `result` is a pointer to + found `pattern` or a null pointer. + + Examples: + + ```mlir + %p = cir.libc.memchr(%src, %pattern, %len) + ``` + }]; + + let arguments = (ins + Arg<CIR_VoidPtrType, "", [MemRead]>:$src, + CIR_SInt32:$pattern, + CIR_UInt64:$len + ); + + let results = (outs CIR_VoidPtrType:$result); + + let assemblyFormat = [{ + `(` $src `,` $pattern `,` $len `)` attr-dict + }]; +} + #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 85406e9f6488a..a9929723d831e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1165,12 +1165,22 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, case Builtin::BIbcopy: case Builtin::BI__builtin_bcopy: return errorBuiltinNYI(*this, e, builtinID); + case Builtin::BI__builtin_char_memchr: + case Builtin::BI__builtin_memchr: { + Address srcPtr = emitPointerWithAlignment(e->getArg(0)); + mlir::Value src = + builder.createBitcast(srcPtr.getPointer(), builder.getVoidPtrTy()); + mlir::Value pattern = emitScalarExpr(e->getArg(1)); + mlir::Value len = emitScalarExpr(e->getArg(2)); + mlir::Value res = cir::MemChrOp::create(builder, getLoc(e->getExprLoc()), + src, pattern, len); + return RValue::get(res); + } case Builtin::BImemcpy: case Builtin::BI__builtin_memcpy: case Builtin::BImempcpy: case Builtin::BI__builtin_mempcpy: case Builtin::BI__builtin_memcpy_inline: - case Builtin::BI__builtin_char_memchr: case Builtin::BI__builtin___memcpy_chk: case Builtin::BI__builtin_objc_memmove_collectable: case Builtin::BI__builtin___memmove_chk: diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index d0fa8bae545be..ab254dc997cb4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -4284,6 +4284,26 @@ mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite( return mlir::failure(); } +mlir::LogicalResult CIRToLLVMMemChrOpLowering::matchAndRewrite( + cir::MemChrOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); + mlir::Type srcTy = getTypeConverter()->convertType(op.getSrc().getType()); + mlir::Type patternTy = + getTypeConverter()->convertType(op.getPattern().getType()); + mlir::Type lenTy = getTypeConverter()->convertType(op.getLen().getType()); + auto fnTy = + mlir::LLVM::LLVMFunctionType::get(llvmPtrTy, {srcTy, patternTy, lenTy}, + /*isVarArg=*/false); + llvm::StringRef fnName = "memchr"; + createLLVMFuncOpIfNotExist(rewriter, op, fnName, fnTy); + rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>( + op, mlir::TypeRange{llvmPtrTy}, fnName, + mlir::ValueRange{adaptor.getSrc(), adaptor.getPattern(), + adaptor.getLen()}); + return mlir::success(); +} + std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } diff --git a/clang/test/CIR/CodeGen/builtin-memchr.c b/clang/test/CIR/CodeGen/builtin-memchr.c new file mode 100644 index 0000000000000..e544422992a05 --- /dev/null +++ b/clang/test/CIR/CodeGen/builtin-memchr.c @@ -0,0 +1,23 @@ +// 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-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-prefix=OGCG --input-file=%t.ll %s + +void *test_memchr(const char arg[32]) { + return __builtin_char_memchr(arg, 123, 32); +} + +// CIR-LABEL: @test_memchr +// CIR: %[[PATTERN:.*]] = cir.const #cir.int<123> : !s32i +// CIR: %[[LEN:.*]] = cir.const #cir.int<32> : !u64i +// CIR: {{%.*}} = cir.libc.memchr({{%.*}}, %[[PATTERN]], %[[LEN]]) + +// LLVM-LABEL: @test_memchr +// LLVM: call ptr @memchr(ptr %{{.*}}, i32 123, i64 32) +// LLVM: ret ptr + +// OGCG-LABEL: @test_memchr +// OGCG: call ptr @memchr(ptr noundef %{{.*}}, i32 noundef 123, i64 noundef 32) +// OGCG: ret ptr diff --git a/clang/test/CIR/IR/libc-memchr.cir b/clang/test/CIR/IR/libc-memchr.cir new file mode 100644 index 0000000000000..bbddb15b187a5 --- /dev/null +++ b/clang/test/CIR/IR/libc-memchr.cir @@ -0,0 +1,12 @@ +// RUN: cir-opt %s --verify-roundtrip | FileCheck %s + +!voidptr = !cir.ptr<!cir.void> +!s32i = !cir.int<s, 32> +!u64i = !cir.int<u, 64> +module { + cir.func @f(%src : !voidptr, %pattern : !s32i, %len : !u64i) -> !voidptr { + // CHECK: cir.libc.memchr + %ptr = cir.libc.memchr(%src, %pattern, %len) + cir.return %ptr : !voidptr + } +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
