Skip to content

Commit

Permalink
[CIR][CIRGen] Support for __builtin_prefetch
Browse files Browse the repository at this point in the history
  • Loading branch information
YazZz1k committed Mar 13, 2024
1 parent 278c391 commit f6055a8
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 2 deletions.
35 changes: 35 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<!void>) 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<I32Attr, [IntMinValue<0>,
IntMaxValue<3>]>:$locality,
UnitAttr:$isWrite);

let assemblyFormat = [{
`(` $addr `:` qualified(type($addr)) `)`
`locality``(` $locality `)`
(`write` $isWrite^) : (`read`)?
attr-dict
}];
}

//===----------------------------------------------------------------------===//
// Operations Lowered Directly to LLVM IR
//
Expand Down
23 changes: 23 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<mlir::cir::PrefetchOp>(getLoc(E->getSourceRange()), Address,
Locality, IsWrite);
return RValue::get(nullptr);
}

// C++ std:: builtins.
case Builtin::BImove:
case Builtin::BImove_if_noexcept:
Expand Down
18 changes: 16 additions & 2 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<mlir::cir::PrefetchOp> {
public:
using OpConversionPattern<mlir::cir::PrefetchOp>::OpConversionPattern;

mlir::LogicalResult
matchAndRewrite(mlir::cir::PrefetchOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
/*DataCache*/ 1);
return mlir::success();
}
};
Expand Down Expand Up @@ -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 {
Expand Down
20 changes: 20 additions & 0 deletions clang/test/CIR/CodeGen/builtin-prefetch.c
Original file line number Diff line number Diff line change
@@ -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<!void> loc({{.*}}))
// CIR: [[PTR_ALLOC:%.*]] = cir.alloca !cir.ptr<!void>, cir.ptr <!cir.ptr<!void>>, ["a", init] {alignment = 8 : i64}
// CIR: cir.store %arg0, [[PTR_ALLOC]] : !cir.ptr<!void>, cir.ptr <!cir.ptr<!void>>
// CIR: [[PTR:%.*]] = cir.load [[PTR_ALLOC]] : cir.ptr <!cir.ptr<!void>>, !cir.ptr<!void>
// CIR: cir.prefetch([[PTR]] : !cir.ptr<!void>) 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

0 comments on commit f6055a8

Please sign in to comment.