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

Reply via email to