[clang] af0f337 - [CIR] Implement 'bzero' builtin lowering in terms of cir.libc.memcpy (#184835)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 6 06:07:35 PST 2026
Author: Erich Keane
Date: 2026-03-06T06:07:28-08:00
New Revision: af0f3379ae3ab5ab49621c575b5ccbc5f597a449
URL: https://github.com/llvm/llvm-project/commit/af0f3379ae3ab5ab49621c575b5ccbc5f597a449
DIFF: https://github.com/llvm/llvm-project/commit/af0f3379ae3ab5ab49621c575b5ccbc5f597a449.diff
LOG: [CIR] Implement 'bzero' builtin lowering in terms of cir.libc.memcpy (#184835)
This showed up on a benchmark, so getting it out of the way. bzero just
does a memset-0, so this lowers to the cir.libc.memset intrinsic. Tests
added were from the classic codegen with improved check lines.
Added:
Modified:
clang/include/clang/CIR/Dialect/IR/CIROps.td
clang/lib/CIR/CodeGen/CIRGenBuilder.h
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
clang/test/CIR/CodeGen/builtins-x86.c
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 5db68b44c2804..79eef71229192 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -3992,12 +3992,13 @@ def CIR_MemSetOp : CIR_Op<"libc.memset"> {
let arguments = (ins
Arg<CIR_VoidPtrType, "", [MemWrite]>:$dst,
+ OptionalAttr<I64Attr>:$alignment,
CIR_UInt8:$val,
CIR_AnyFundamentalUIntType:$len
);
let assemblyFormat = [{
- $len `bytes` `at` $dst `to` $val attr-dict
+ $len `bytes` `at` $dst (`align` `(` $alignment^ `)`)? `to` $val attr-dict
`:` qualified(type($dst)) `,` type($val) `,` type($len)
}];
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index cbb6a78d5212b..e2f89cc5aa12f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -243,7 +243,14 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
cir::MemSetOp createMemSet(mlir::Location loc, mlir::Value dst,
mlir::Value val, mlir::Value len) {
assert(val.getType() == getUInt8Ty());
- return cir::MemSetOp::create(*this, loc, dst, val, len);
+ return cir::MemSetOp::create(*this, loc, dst, {}, val, len);
+ }
+
+ cir::MemSetOp createMemSet(mlir::Location loc, Address dst, mlir::Value val,
+ mlir::Value len) {
+ mlir::IntegerAttr align = getAlignmentAttr(dst.getAlignment());
+ assert(val.getType() == getUInt8Ty());
+ return cir::MemSetOp::create(*this, loc, dst.getPointer(), align, val, len);
}
// ---------------------------
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 17056c0edbe0b..244979aac917e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -1575,8 +1575,19 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
case Builtin::BI__builtin_alloca_with_align_uninitialized:
case Builtin::BI__builtin_alloca_with_align:
case Builtin::BI__builtin_infer_alloc_token:
+ return errorBuiltinNYI(*this, e, builtinID);
case Builtin::BIbzero:
- case Builtin::BI__builtin_bzero:
+ case Builtin::BI__builtin_bzero: {
+ mlir::Location loc = getLoc(e->getSourceRange());
+ Address destPtr = emitPointerWithAlignment(e->getArg(0));
+ Address destPtrCast = destPtr.withElementType(builder, cgm.voidTy);
+ mlir::Value size = emitScalarExpr(e->getArg(1));
+ mlir::Value zero = builder.getNullValue(builder.getUInt8Ty(), loc);
+ assert(!cir::MissingFeatures::sanitizers());
+ builder.createMemSet(loc, destPtrCast, zero, size);
+ assert(!cir::MissingFeatures::generateDebugInfo());
+ return RValue::getIgnored();
+ }
case Builtin::BIbcopy:
case Builtin::BI__builtin_bcopy:
return errorBuiltinNYI(*this, e, builtinID);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index accb60df3799e..8bcd040382ab3 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -205,9 +205,24 @@ mlir::LogicalResult CIRToLLVMMemCpyOpLowering::matchAndRewrite(
mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
cir::MemSetOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
- rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
+
+ auto memset = rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetOp>(
op, adaptor.getDst(), adaptor.getVal(), adaptor.getLen(),
/*isVolatile=*/false);
+
+ if (op.getAlignmentAttr()) {
+ // Construct a list full of empty attributes.
+ llvm::SmallVector<mlir::Attribute> attrs{memset.getNumOperands(),
+ rewriter.getDictionaryAttr({})};
+ llvm::SmallVector<mlir::NamedAttribute> destAttrs;
+ destAttrs.push_back(
+ {mlir::LLVM::LLVMDialect::getAlignAttrName(), op.getAlignmentAttr()});
+ attrs[memset.odsIndex_dst] = rewriter.getDictionaryAttr(destAttrs);
+
+ auto arrayAttr = rewriter.getArrayAttr(attrs);
+ memset.setArgAttrsAttr(arrayAttr);
+ }
+
return mlir::success();
}
diff --git a/clang/test/CIR/CodeGen/builtins-x86.c b/clang/test/CIR/CodeGen/builtins-x86.c
index e56794b566192..8511286a79723 100644
--- a/clang/test/CIR/CodeGen/builtins-x86.c
+++ b/clang/test/CIR/CodeGen/builtins-x86.c
@@ -67,3 +67,55 @@ v4i test_convertvector(v4f a) {
// OGCG: fptosi <4 x float> %{{.*}} to <4 x i32>
return __builtin_convertvector(a, v4i);
}
+
+void foo();
+void test_conditional_bzero(void) {
+// CIR-LABEL: test_conditional_bzero
+// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!s8i x 20>
+// CIR: %[[SIZE:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["len", init]
+// CIR: %[[ARR_DECAY:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s8i x 20>> -> !cir.ptr<!s8i>
+// CIR: %[[ARR_TO_VOID_PTR:.*]] = cir.cast bitcast %[[ARR_DECAY]] : !cir.ptr<!s8i> -> !cir.ptr<!void>
+// CIR: %[[SIZE_LOAD:.*]] = cir.load {{.*}}%[[SIZE]] : !cir.ptr<!s32i>, !s32i
+// CIR: %[[SIZE_CAST:.*]] = cir.cast integral %[[SIZE_LOAD]] : !s32i -> !u64i
+// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !u8i
+// CIR: cir.libc.memset %[[SIZE_CAST]] bytes at %[[ARR_TO_VOID_PTR]] align(16) to %[[ZERO]] : !cir.ptr<!void>, !u8i, !u64i
+//
+// CIR: %[[ARR_DECAY:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s8i x 20>> -> !cir.ptr<!s8i>
+// CIR: %[[ARR_TO_VOID_PTR:.*]] = cir.cast bitcast %[[ARR_DECAY]] : !cir.ptr<!s8i> -> !cir.ptr<!void>
+// CIR: %[[SIZE_LOAD:.*]] = cir.load {{.*}}%[[SIZE]] : !cir.ptr<!s32i>, !s32i
+// CIR: %[[SIZE_CAST:.*]] = cir.cast integral %[[SIZE_LOAD]] : !s32i -> !u64i
+// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !u8i
+// CIR: cir.libc.memset %[[SIZE_CAST]] bytes at %[[ARR_TO_VOID_PTR]] align(16) to %[[ZERO]] : !cir.ptr<!void>, !u8i, !u64i
+//
+// LLVM-LABEL: @test_conditional_bzero
+// LLVM: %[[ARR:.*]] = alloca [20 x i8]
+// LLVM: %[[ARR_DECAY:.*]] = getelementptr i8, ptr %[[ARR]], i32 0
+// LLVM: %[[SIZE_LOAD:.*]] = load i32, ptr %{{.*}}
+// LLVM: %[[SIZE_CAST:.*]] = sext i32 %[[SIZE_LOAD]] to i64
+// LLVM: call void @llvm.memset.p0.i64(ptr align 16 %[[ARR_DECAY]], i8 0, i64 %[[SIZE_CAST]], i1 false)
+//
+// LLVM: %[[ARR_DECAY:.*]] = getelementptr i8, ptr %[[ARR]], i32 0
+// LLVM: %[[SIZE_LOAD:.*]] = load i32, ptr %{{.*}}
+// LLVM: %[[SIZE_CAST:.*]] = sext i32 %[[SIZE_LOAD]] to i64
+// LLVM: call void @llvm.memset.p0.i64(ptr align 16 %[[ARR_DECAY]], i8 0, i64 %[[SIZE_CAST]], i1 false)
+//
+// OGCG-LABEL: @test_conditional_bzero
+// OGCG: %[[ARR:.*]] = alloca [20 x i8]
+// OGCG: %[[ARR_DECAY:.*]] = getelementptr inbounds [20 x i8], ptr %[[ARR]], i64 0
+// OGCG: %[[SIZE_LOAD:.*]] = load i32, ptr %{{.*}}
+// OGCG: %[[SIZE_CAST:.*]] = sext i32 %[[SIZE_LOAD]] to i64
+// OGCG: call void @llvm.memset.p0.i64(ptr align 16 %[[ARR_DECAY]], i8 0, i64 %[[SIZE_CAST]], i1 false)
+//
+// OGCG: %[[ARR_DECAY:.*]] = getelementptr inbounds [20 x i8], ptr %[[ARR]], i64 0
+// OGCG: %[[SIZE_LOAD:.*]] = load i32, ptr %{{.*}}
+// OGCG: %[[SIZE_CAST:.*]] = sext i32 %[[SIZE_LOAD]] to i64
+// OGCG: call void @llvm.memset.p0.i64(ptr align 16 %[[ARR_DECAY]], i8 0, i64 %[[SIZE_CAST]], i1 false)
+
+ char dst[20];
+ int _sz = 20, len = 20;
+ return (_sz
+ ? ((_sz >= len)
+ ? __builtin_bzero(dst, len)
+ : foo())
+ : __builtin_bzero(dst, len));
+}
More information about the cfe-commits
mailing list