From f6055a8303d3c6271b18df5872d0d44eabb4e080 Mon Sep 17 00:00:00 2001 From: YazZz1k Date: Wed, 21 Feb 2024 12:43:40 +0300 Subject: [PATCH] [CIR][CIRGen] Support for __builtin_prefetch --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 35 +++++++++++++++++++ clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 23 ++++++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 ++++++++-- clang/test/CIR/CodeGen/builtin-prefetch.c | 20 +++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 clang/test/CIR/CodeGen/builtin-prefetch.c diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 55f54a4a7df3..b363b9093b46 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3204,6 +3204,41 @@ def TrapOp : CIR_Op<"trap", [Terminator]> { let assemblyFormat = "attr-dict"; } +//===----------------------------------------------------------------------===// +// PrefetchOp +//===----------------------------------------------------------------------===// + +def PrefetchOp : CIR_Op<"prefetch"> { + let summary = "prefetch operation"; + let description = [{ + The `cir.prefetch` op prefetches data from the memmory address. + + ```mlir + cir.prefetch(%0 : !cir.ptr) locality(1) write + ``` + + This opcode has the three attributes: + 1. The $locality is a temporal locality specifier + ranging from (0) - no locality, to (3) - extremely local keep in cache. + 2. The $isWrite is the specifier determining if the prefetch is prepaired + for a 'read' or 'write'. + If $isWrite doesn't specified it means that prefetch is prepared for 'read'. + }]; + + let arguments = ( + ins VoidPtr:$addr, + ConfinedAttr, + IntMaxValue<3>]>:$locality, + UnitAttr:$isWrite); + + let assemblyFormat = [{ + `(` $addr `:` qualified(type($addr)) `)` + `locality``(` $locality `)` + (`write` $isWrite^) : (`read`)? + attr-dict + }]; +} + //===----------------------------------------------------------------------===// // Operations Lowered Directly to LLVM IR // diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 78a88d11565c..509ff515ce99 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -439,6 +439,29 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(buildScalarExpr(E->getArg(0))); } + case Builtin::BI__builtin_prefetch: { + auto evaluateOperandAsInt = [&](const Expr *Arg) { + Expr::EvalResult Res; + [[maybe_unused]] bool EvalSucceed = + Arg->EvaluateAsInt(Res, CGM.getASTContext()); + assert(EvalSucceed && "expression should be able to evaluate as int"); + return Res.Val.getInt().getZExtValue(); + }; + + bool IsWrite = false; + if (E->getNumArgs() > 1) + IsWrite = evaluateOperandAsInt(E->getArg(1)); + + int Locality = 0; + if (E->getNumArgs() > 2) + Locality = evaluateOperandAsInt(E->getArg(2)); + + mlir::Value Address = buildScalarExpr(E->getArg(0)); + builder.create(getLoc(E->getSourceRange()), Address, + Locality, IsWrite); + return RValue::get(nullptr); + } + // C++ std:: builtins. case Builtin::BImove: case Builtin::BImove_if_noexcept: diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 4623cf253b24..6936391aaf8e 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2575,7 +2575,21 @@ class CIRInlineAsmOpLowering /*is_align_stack*/ mlir::UnitAttr(), mlir::LLVM::AsmDialectAttr::get(getContext(), llDialect), rewriter.getArrayAttr(opAttrs)); + return mlir::success(); + } +}; +class CIRPrefetchLowering + : public mlir::OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(mlir::cir::PrefetchOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp( + op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(), + /*DataCache*/ 1); return mlir::success(); } }; @@ -2731,8 +2745,8 @@ void populateCIRToLLVMConversionPatterns(mlir::RewritePatternSet &patterns, CIRVectorExtractLowering, CIRVectorCmpOpLowering, CIRVectorSplatLowering, CIRVectorTernaryLowering, CIRStackSaveLowering, CIRStackRestoreLowering, CIRUnreachableLowering, CIRTrapLowering, CIRInlineAsmOpLowering, - CIRSetBitfieldLowering, CIRGetBitfieldLowering>(converter, - patterns.getContext()); + CIRSetBitfieldLowering, CIRGetBitfieldLowering, CIRPrefetchLowering>( + converter, patterns.getContext()); } namespace { diff --git a/clang/test/CIR/CodeGen/builtin-prefetch.c b/clang/test/CIR/CodeGen/builtin-prefetch.c new file mode 100644 index 000000000000..e0cfcad6a4da --- /dev/null +++ b/clang/test/CIR/CodeGen/builtin-prefetch.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir-enable -emit-llvm %s -o - | FileCheck %s -check-prefix=LLVM + +void foo(void *a) { + __builtin_prefetch(a, 1, 1); +} + +// CIR: cir.func @foo(%arg0: !cir.ptr loc({{.*}})) +// CIR: [[PTR_ALLOC:%.*]] = cir.alloca !cir.ptr, cir.ptr >, ["a", init] {alignment = 8 : i64} +// CIR: cir.store %arg0, [[PTR_ALLOC]] : !cir.ptr, cir.ptr > +// CIR: [[PTR:%.*]] = cir.load [[PTR_ALLOC]] : cir.ptr >, !cir.ptr +// CIR: cir.prefetch([[PTR]] : !cir.ptr) locality(1) write +// CIR: cir.return + +// LLVM: define void @foo(ptr [[ARG0:%.*]]) +// LLVM: [[PTR_ALLOC:%.*]] = alloca ptr, i64 1 +// LLVM: store ptr [[ARG0]], ptr [[PTR_ALLOC]] +// LLVM: [[PTR:%.*]] = load ptr, ptr [[PTR_ALLOC]] +// LLVM: call void @llvm.prefetch.p0(ptr [[PTR]], i32 1, i32 1, i32 1) +// LLVM: ret void