Skip to content

Commit 4d3b799

Browse files
committed
[CIR][CIRGen] Support __builtin_memset_inline
1 parent da601b3 commit 4d3b799

File tree

6 files changed

+103
-10
lines changed

6 files changed

+103
-10
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

+31
Original file line numberDiff line numberDiff line change
@@ -4147,6 +4147,37 @@ def MemSetOp : CIR_Op<"libc.memset"> {
41474147
let hasVerifier = 0;
41484148
}
41494149

4150+
//===----------------------------------------------------------------------===//
4151+
// MemSetInlineOp
4152+
//===----------------------------------------------------------------------===//
4153+
4154+
def MemSetInlineOp : CIR_Op<"memset_inline"> {
4155+
let arguments = (ins Arg<VoidPtr, "", [MemWrite]>:$dst,
4156+
SInt32:$val,
4157+
I64Attr:$len);
4158+
let summary = "Fill a block of memory with constant length without calling"
4159+
"any external function";
4160+
let description = [{
4161+
Given the CIR pointer, `dst`, `cir.memset_inline` will set the first `len`
4162+
bytes of the memory pointed by `dst` to the specified `val`.
4163+
4164+
The `len` argument must be a constant integer argument specifying the number
4165+
of bytes to fill.
4166+
4167+
Examples:
4168+
4169+
```mlir
4170+
// Set 2 bytes from a struct to 0
4171+
cir.memset_inline 2 bytes from %struct set to %zero : !cir.ptr<!void>, !s32i
4172+
```
4173+
}];
4174+
4175+
let assemblyFormat = [{
4176+
$len `bytes` `from` $dst `set` `to` $val attr-dict
4177+
`:` qualified(type($dst)) `,` type($val)
4178+
}];
4179+
let hasVerifier = 0;
4180+
}
41504181
//===----------------------------------------------------------------------===//
41514182
// MemChrOp
41524183
//===----------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/CIRGenBuilder.h

+7
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,13 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
623623
return create<cir::MemSetOp>(loc, dst, val, len);
624624
}
625625

626+
cir::MemSetInlineOp createMemSetInline(mlir::Location loc, mlir::Value dst,
627+
mlir::Value val,
628+
mlir::IntegerAttr len) {
629+
val = createIntCast(val, cir::IntType::get(getContext(), 32, true));
630+
return create<cir::MemSetInlineOp>(loc, dst, val, len);
631+
}
632+
626633
mlir::Value createNeg(mlir::Value value) {
627634

628635
if (auto intTy = mlir::dyn_cast<cir::IntType>(value.getType())) {

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

+14-2
Original file line numberDiff line numberDiff line change
@@ -1554,8 +1554,20 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
15541554
return RValue::get(Dest.getPointer());
15551555
}
15561556

1557-
case Builtin::BI__builtin_memset_inline:
1558-
llvm_unreachable("BI__builtin_memset_inline NYI");
1557+
case Builtin::BI__builtin_memset_inline: {
1558+
Address Dest = emitPointerWithAlignment(E->getArg(0));
1559+
mlir::Value ByteVal = emitScalarExpr(E->getArg(1));
1560+
uint64_t size =
1561+
E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue();
1562+
emitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(),
1563+
E->getArg(0)->getExprLoc(), FD, 0);
1564+
builder.createMemSetInline(
1565+
getLoc(E->getSourceRange()), Dest.getPointer(), ByteVal,
1566+
mlir::IntegerAttr::get(mlir::IntegerType::get(builder.getContext(), 64),
1567+
size));
1568+
// __builtin_memset_inline has no return value
1569+
return RValue::get(nullptr);
1570+
}
15591571
case Builtin::BI__builtin___memset_chk: {
15601572
// fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2.
15611573
llvm::APSInt size;

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

+21-8
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,18 @@ mlir::LogicalResult CIRToLLVMMemSetOpLowering::matchAndRewrite(
777777
return mlir::success();
778778
}
779779

780+
mlir::LogicalResult CIRToLLVMMemSetInlineOpLowering::matchAndRewrite(
781+
cir::MemSetInlineOp op, OpAdaptor adaptor,
782+
mlir::ConversionPatternRewriter &rewriter) const {
783+
auto converted = rewriter.create<mlir::LLVM::TruncOp>(
784+
op.getLoc(), mlir::IntegerType::get(op.getContext(), 8),
785+
adaptor.getVal());
786+
rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetInlineOp>(
787+
op, adaptor.getDst(), converted, adaptor.getLenAttr(),
788+
/*isVolatile=*/false);
789+
return mlir::success();
790+
}
791+
780792
static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter,
781793
mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
782794
bool isUnsigned, uint64_t cirSrcWidth,
@@ -1851,8 +1863,8 @@ mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
18511863
return op.emitError("cir.vaarg lowering is NYI");
18521864
}
18531865

1854-
/// Returns the name used for the linkage attribute. This *must* correspond
1855-
/// to the name of the attribute in ODS.
1866+
/// Returns the name used for the linkage attribute. This *must* correspond
1867+
/// to the name of the attribute in ODS.
18561868
StringRef CIRToLLVMFuncOpLowering::getLinkageAttrNameString() {
18571869
return "linkage";
18581870
}
@@ -1886,8 +1898,8 @@ void CIRToLLVMFuncOpLowering::lowerFuncAttributes(
18861898
}
18871899
}
18881900

1889-
/// When do module translation, we can only translate LLVM-compatible types.
1890-
/// Here we lower possible OpenCLKernelMetadataAttr to use the converted type.
1901+
/// When do module translation, we can only translate LLVM-compatible types.
1902+
/// Here we lower possible OpenCLKernelMetadataAttr to use the converted type.
18911903
void CIRToLLVMFuncOpLowering::lowerFuncOpenCLKernelMetadata(
18921904
mlir::NamedAttribute &extraAttrsEntry) const {
18931905
const auto attrKey = cir::OpenCLKernelMetadataAttr::getMnemonic();
@@ -2100,8 +2112,8 @@ mlir::LogicalResult CIRToLLVMSwitchFlatOpLowering::matchAndRewrite(
21002112
return mlir::success();
21012113
}
21022114

2103-
/// Replace CIR global with a region initialized LLVM global and update
2104-
/// insertion point to the end of the initializer block.
2115+
/// Replace CIR global with a region initialized LLVM global and update
2116+
/// insertion point to the end of the initializer block.
21052117
void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp(
21062118
cir::GlobalOp op, mlir::ConversionPatternRewriter &rewriter) const {
21072119
const auto llvmType = getTypeConverter()->convertType(op.getSymType());
@@ -3890,8 +3902,9 @@ void populateCIRToLLVMConversionPatterns(
38903902
CIRToLLVMBaseClassAddrOpLowering, CIRToLLVMDerivedClassAddrOpLowering,
38913903
CIRToLLVMVTTAddrPointOpLowering, CIRToLLVMIsFPClassOpLowering,
38923904
CIRToLLVMAbsOpLowering, CIRToLLVMMemMoveOpLowering,
3893-
CIRToLLVMMemSetOpLowering, CIRToLLVMMemCpyInlineOpLowering,
3894-
CIRToLLVMSignBitOpLowering, CIRToLLVMPtrMaskOpLowering
3905+
CIRToLLVMMemSetOpLowering, CIRToLLVMMemSetInlineOpLowering,
3906+
CIRToLLVMMemCpyInlineOpLowering, CIRToLLVMSignBitOpLowering,
3907+
CIRToLLVMPtrMaskOpLowering
38953908
#define GET_BUILTIN_LOWERING_LIST
38963909
#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc"
38973910
#undef GET_BUILTIN_LOWERING_LIST

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

+10
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ class CIRToLLVMMemSetOpLowering
125125
mlir::ConversionPatternRewriter &) const override;
126126
};
127127

128+
class CIRToLLVMMemSetInlineOpLowering
129+
: public mlir::OpConversionPattern<cir::MemSetInlineOp> {
130+
public:
131+
using mlir::OpConversionPattern<cir::MemSetInlineOp>::OpConversionPattern;
132+
133+
mlir::LogicalResult
134+
matchAndRewrite(cir::MemSetInlineOp op, OpAdaptor adaptor,
135+
mlir::ConversionPatternRewriter &rewriter) const override;
136+
};
137+
128138
class CIRToLLVMPtrStrideOpLowering
129139
: public mlir::OpConversionPattern<cir::PtrStrideOp> {
130140
public:

clang/test/CIR/CodeGen/builtins-memory.c

+20
Original file line numberDiff line numberDiff line change
@@ -210,3 +210,23 @@ void test_memcpy_inline_aligned_buffers(unsigned long long *dst, const unsigned
210210
// COM: LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 {{%.*}}, ptr align 8 {{%.*}}, i64 4, i1 false)
211211
__builtin_memcpy_inline(dst, src, 4);
212212
}
213+
214+
void test_memset_inline(void *dst, int val) {
215+
216+
// CIR-LABEL: test_memset_inline
217+
// CIR: cir.memset_inline 0 bytes from {{%.*}} set to {{%.*}} : !cir.ptr<!void>, !s32i
218+
219+
// LLVM-LABEL: test_memset_inline
220+
// LLVM: call void @llvm.memset.inline.p0.i64(ptr {{%.*}}, i8 {{%.*}}, i64 0, i1 false)
221+
__builtin_memset_inline(dst, val, 0);
222+
223+
// CIR: cir.memset_inline 1 bytes from {{%.*}} set to {{%.*}} : !cir.ptr<!void>, !s32i
224+
225+
// LLVM: call void @llvm.memset.inline.p0.i64(ptr {{%.*}}, i8 {{%.*}}, i64 1, i1 false)
226+
__builtin_memset_inline(dst, val, 1);
227+
228+
// CIR: cir.memset_inline 4 bytes from {{%.*}} set to {{%.*}} : !cir.ptr<!void>, !s32i
229+
230+
// LLVM: call void @llvm.memset.inline.p0.i64(ptr {{%.*}}, i8 {{%.*}}, i64 4, i1 false)
231+
__builtin_memset_inline(dst, val, 4);
232+
}

0 commit comments

Comments
 (0)