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)); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
