Skip to content

Commit

Permalink
[CIR][CIRGen] Support __builtin_memset_inline
Browse files Browse the repository at this point in the history
  • Loading branch information
PikachuHyA committed Nov 13, 2024
1 parent 3ab5716 commit 74c2c64
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 3 deletions.
31 changes: 31 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -4148,6 +4148,37 @@ def MemSetOp : CIR_Op<"libc.memset"> {
let hasVerifier = 0;
}

//===----------------------------------------------------------------------===//
// MemSetInlineOp
//===----------------------------------------------------------------------===//

def MemSetInlineOp : CIR_Op<"memset_inline"> {
let arguments = (ins Arg<VoidPtr, "", [MemWrite]>:$dst,
SInt32:$val,
I64Attr:$len);
let summary = "Fill a block of memory with constant length without calling"
"any external function";
let description = [{
Given the CIR pointer, `dst`, `cir.memset_inline` will set the first `len`
bytes of the memory pointed by `dst` to the specified `val`.

The `len` argument must be a constant integer argument specifying the number
of bytes to fill.

Examples:

```mlir
// Set 2 bytes from a struct to 0
cir.memset_inline 2 bytes from %struct set to %zero : !cir.ptr<!void>, !s32i
```
}];

let assemblyFormat = [{
$len `bytes` `from` $dst `set` `to` $val attr-dict
`:` qualified(type($dst)) `,` type($val)
}];
let hasVerifier = 0;
}
//===----------------------------------------------------------------------===//
// MemChrOp
//===----------------------------------------------------------------------===//
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,13 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return create<cir::MemSetOp>(loc, dst, val, len);
}

cir::MemSetInlineOp createMemSetInline(mlir::Location loc, mlir::Value dst,
mlir::Value val,
mlir::IntegerAttr len) {
val = createIntCast(val, cir::IntType::get(getContext(), 32, true));
return create<cir::MemSetInlineOp>(loc, dst, val, len);
}

mlir::Value createNeg(mlir::Value value) {

if (auto intTy = mlir::dyn_cast<cir::IntType>(value.getType())) {
Expand Down
16 changes: 14 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1522,8 +1522,20 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(Dest.getPointer());
}

case Builtin::BI__builtin_memset_inline:
llvm_unreachable("BI__builtin_memset_inline NYI");
case Builtin::BI__builtin_memset_inline: {
Address Dest = emitPointerWithAlignment(E->getArg(0));
mlir::Value ByteVal = emitScalarExpr(E->getArg(1));
uint64_t size =
E->getArg(2)->EvaluateKnownConstInt(getContext()).getZExtValue();
emitNonNullArgCheck(RValue::get(Dest.getPointer()), E->getArg(0)->getType(),
E->getArg(0)->getExprLoc(), FD, 0);
builder.createMemSetInline(
getLoc(E->getSourceRange()), Dest.getPointer(), ByteVal,
mlir::IntegerAttr::get(mlir::IntegerType::get(builder.getContext(), 64),
size));
// __builtin_memset_inline has no return value
return RValue::get(nullptr);
}
case Builtin::BI__builtin___memset_chk: {
// fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2.
Expr::EvalResult sizeResult, dstSizeResult;
Expand Down
21 changes: 20 additions & 1 deletion clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,24 @@ class CIRMemsetOpLowering : public mlir::OpConversionPattern<cir::MemSetOp> {
}
};

class CIRMemsetInlineOpLowering
: public mlir::OpConversionPattern<cir::MemSetInlineOp> {
public:
using mlir::OpConversionPattern<cir::MemSetInlineOp>::OpConversionPattern;

mlir::LogicalResult
matchAndRewrite(cir::MemSetInlineOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
auto converted = rewriter.create<mlir::LLVM::TruncOp>(
op.getLoc(), mlir::IntegerType::get(op.getContext(), 8),
adaptor.getVal());
rewriter.replaceOpWithNewOp<mlir::LLVM::MemsetInlineOp>(
op, adaptor.getDst(), converted, adaptor.getLenAttr(),
/*isVolatile=*/false);
return mlir::success();
}
};

static mlir::Value getLLVMIntCast(mlir::ConversionPatternRewriter &rewriter,
mlir::Value llvmSrc, mlir::Type llvmDstIntTy,
bool isUnsigned, uint64_t cirSrcWidth,
Expand Down Expand Up @@ -4398,7 +4416,8 @@ void populateCIRToLLVMConversionPatterns(
CIRAssumeLowering, CIRAssumeAlignedLowering, CIRAssumeSepStorageLowering,
CIRBaseClassAddrOpLowering, CIRDerivedClassAddrOpLowering,
CIRVTTAddrPointOpLowering, CIRIsFPClassOpLowering, CIRAbsOpLowering,
CIRMemMoveOpLowering, CIRMemsetOpLowering, CIRSignBitOpLowering
CIRMemMoveOpLowering, CIRMemsetOpLowering, CIRMemsetInlineOpLowering,
CIRSignBitOpLowering
#define GET_BUILTIN_LOWERING_LIST
#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc"
#undef GET_BUILTIN_LOWERING_LIST
Expand Down
20 changes: 20 additions & 0 deletions clang/test/CIR/CodeGen/builtins-memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,23 @@ void test_memcpy_inline_aligned_buffers(unsigned long long *dst, const unsigned
// COM: LLVM: call void @llvm.memcpy.inline.p0.p0.i64(ptr align 8 {{%.*}}, ptr align 8 {{%.*}}, i64 4, i1 false)
__builtin_memcpy_inline(dst, src, 4);
}

void test_memset_inline(void *dst, int val) {

// CIR-LABEL: test_memset_inline
// CIR: cir.memset_inline 0 bytes from {{%.*}} set to {{%.*}} : !cir.ptr<!void>, !s32i

// LLVM-LABEL: test_memset_inline
// LLVM: call void @llvm.memset.inline.p0.i64(ptr {{%.*}}, i8 {{%.*}}, i64 0, i1 false)
__builtin_memset_inline(dst, val, 0);

// CIR: cir.memset_inline 1 bytes from {{%.*}} set to {{%.*}} : !cir.ptr<!void>, !s32i

// LLVM: call void @llvm.memset.inline.p0.i64(ptr {{%.*}}, i8 {{%.*}}, i64 1, i1 false)
__builtin_memset_inline(dst, val, 1);

// CIR: cir.memset_inline 4 bytes from {{%.*}} set to {{%.*}} : !cir.ptr<!void>, !s32i

// LLVM: call void @llvm.memset.inline.p0.i64(ptr {{%.*}}, i8 {{%.*}}, i64 4, i1 false)
__builtin_memset_inline(dst, val, 4);
}

0 comments on commit 74c2c64

Please sign in to comment.