Skip to content

Commit 760e039

Browse files
committed
[CIR] Upstream handling for __builtin_prefetch
1 parent cd05383 commit 760e039

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4049,6 +4049,39 @@ def CIR_ExpectOp : CIR_Op<"expect", [
40494049
}];
40504050
}
40514051

4052+
//===----------------------------------------------------------------------===//
4053+
// PrefetchOp
4054+
//===----------------------------------------------------------------------===//
4055+
4056+
def CIR_PrefetchOp : CIR_Op<"prefetch"> {
4057+
let summary = "prefetch operation";
4058+
let description = [{
4059+
The `cir.prefetch` op prefetches data from the memmory address.
4060+
4061+
```mlir
4062+
cir.prefetch(%0 : !cir.ptr<!void>) locality(1) write
4063+
```
4064+
4065+
This opcode has the three attributes:
4066+
1. The $locality is a temporal locality specifier
4067+
ranging from (0) - no locality, to (3) - extremely local keep in cache.
4068+
2. The $isWrite is the specifier determining if the prefetch is prepaired
4069+
for a 'read' or 'write'.
4070+
If $isWrite doesn't specified it means that prefetch is prepared for 'read'.
4071+
}];
4072+
4073+
let arguments = (ins CIR_VoidPtrType:$addr,
4074+
ConfinedAttr<I32Attr, [IntMinValue<0>, IntMaxValue<3>]>:$locality,
4075+
UnitAttr:$isWrite);
4076+
4077+
let assemblyFormat = [{
4078+
`(` $addr `:` qualified(type($addr)) `)`
4079+
`locality``(` $locality `)`
4080+
(`write` $isWrite^) : (`read`)?
4081+
attr-dict
4082+
}];
4083+
}
4084+
40524085
//===----------------------------------------------------------------------===//
40534086
// PtrDiffOp
40544087
//===----------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,27 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
454454
assert(!cir::MissingFeatures::coroSizeBuiltinCall());
455455
return getUndefRValue(e->getType());
456456
}
457+
case Builtin::BI__builtin_prefetch: {
458+
auto evaluateOperandAsInt = [&](const Expr *arg) {
459+
Expr::EvalResult res;
460+
[[maybe_unused]] bool evalSucceed =
461+
arg->EvaluateAsInt(res, cgm.getASTContext());
462+
assert(evalSucceed && "expression should be able to evaluate as int");
463+
return res.Val.getInt().getZExtValue();
464+
};
465+
466+
bool isWrite = false;
467+
if (e->getNumArgs() > 1)
468+
isWrite = evaluateOperandAsInt(e->getArg(1));
469+
470+
int locality = 0;
471+
if (e->getNumArgs() > 2)
472+
locality = evaluateOperandAsInt(e->getArg(2));
473+
474+
mlir::Value address = emitScalarExpr(e->getArg(0));
475+
cir::PrefetchOp::create(builder, loc, address, locality, isWrite);
476+
return RValue::get(nullptr);
477+
}
457478
}
458479

459480
// If this is an alias for a lib function (e.g. __builtin_sin), emit

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,15 @@ static uint64_t getTypeSize(mlir::Type type, mlir::Operation &op) {
15071507
return llvm::divideCeil(layout.getTypeSizeInBits(type), 8);
15081508
}
15091509

1510+
mlir::LogicalResult CIRToLLVMPrefetchOpLowering::matchAndRewrite(
1511+
cir::PrefetchOp op, OpAdaptor adaptor,
1512+
mlir::ConversionPatternRewriter &rewriter) const {
1513+
rewriter.replaceOpWithNewOp<mlir::LLVM::Prefetch>(
1514+
op, adaptor.getAddr(), adaptor.getIsWrite(), adaptor.getLocality(),
1515+
/*DataCache*/ 1);
1516+
return mlir::success();
1517+
}
1518+
15101519
mlir::LogicalResult CIRToLLVMPtrDiffOpLowering::matchAndRewrite(
15111520
cir::PtrDiffOp op, OpAdaptor adaptor,
15121521
mlir::ConversionPatternRewriter &rewriter) const {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s -check-prefix=CIR
2+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s -check-prefix=LLVM
3+
4+
void foo(void *a) {
5+
__builtin_prefetch(a, 1, 1);
6+
}
7+
8+
// CIR: cir.func dso_local @foo(%arg0: !cir.ptr<!void> loc({{.*}}))
9+
// CIR: [[PTR_ALLOC:%.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["a", init] {alignment = 8 : i64}
10+
// CIR: cir.store %arg0, [[PTR_ALLOC]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
11+
// CIR: [[PTR:%.*]] = cir.load{{.*}} [[PTR_ALLOC]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
12+
// CIR: cir.prefetch([[PTR]] : !cir.ptr<!void>) locality(1) write
13+
// CIR: cir.return
14+
15+
// LLVM: define dso_local void @foo(ptr [[ARG0:%.*]])
16+
// LLVM: [[PTR_ALLOC:%.*]] = alloca ptr, i64 1
17+
// LLVM: store ptr [[ARG0]], ptr [[PTR_ALLOC]]
18+
// LLVM: [[PTR:%.*]] = load ptr, ptr [[PTR_ALLOC]]
19+
// LLVM: call void @llvm.prefetch.p0(ptr [[PTR]], i32 1, i32 1, i32 1)
20+
// LLVM: ret void

0 commit comments

Comments
 (0)