Skip to content

Commit 02cf87c

Browse files
Add prefetch builtins
1 parent ea66d26 commit 02cf87c

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4116,7 +4116,7 @@ def CIR_PrefetchOp : CIR_Op<"prefetch"> {
41164116
$locality is a temporal locality specifier ranging from (0) - no locality,
41174117
to (3) - extremely local, keep in cache. If $locality is not present, the
41184118
default value is 3.
4119-
4119+
41204120
$isWrite specifies whether the prefetch is for a 'read' or 'write'. If
41214121
$isWrite is not specified, it means that prefetch is prepared for 'read'.
41224122
}];
@@ -4150,7 +4150,7 @@ def CIR_ObjSizeOp : CIR_Op<"objsize", [Pure]> {
41504150
When the `min` attribute is present, the operation returns the minimum
41514151
guaranteed accessible size. When absent (max mode), it returns the maximum
41524152
possible object size. Corresponds to `llvm.objectsize`'s `min` argument.
4153-
4153+
41544154
The `dynamic` attribute determines if the value should be evaluated at
41554155
runtime. Corresponds to `llvm.objectsize`'s `dynamic` argument.
41564156

clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
using namespace clang;
2121
using namespace clang::CIRGen;
2222

23+
/// Get integer from a mlir::Value that is an int constant or a constant op.
24+
static int64_t getIntValueFromConstOp(mlir::Value val) {
25+
return val.getDefiningOp<cir::ConstantOp>().getIntValue().getSExtValue();
26+
}
27+
2328
template <typename... Operands>
2429
static mlir::Value emitIntrinsicCallOp(CIRGenFunction &cgf, const CallExpr *e,
2530
const std::string &str,
@@ -33,6 +38,28 @@ static mlir::Value emitIntrinsicCallOp(CIRGenFunction &cgf, const CallExpr *e,
3338
.getResult();
3439
}
3540

41+
static mlir::Value emitPrefetch(CIRGenFunction &cgf, unsigned builtinID,
42+
const CallExpr *e,
43+
mlir::Value &addr, int64_t hint) {
44+
CIRGenBuilderTy &builder = cgf.getBuilder();
45+
mlir::Location location = cgf.getLoc(e->getExprLoc());
46+
mlir::Type voidTy = builder.getVoidTy();
47+
mlir::Value address = builder.createPtrBitcast(addr, voidTy);
48+
bool isWrite{};
49+
int locality{};
50+
51+
if (builtinID == X86::BI_mm_prefetch) {
52+
isWrite = (hint >> 2) & 0x1;
53+
locality = hint & 0x3;
54+
} else {
55+
isWrite = (builtinID == X86::BI_m_prefetchw);
56+
locality = 0x3;
57+
}
58+
59+
cir::PrefetchOp::create(builder, location, address, locality, isWrite);
60+
return {};
61+
}
62+
3663
mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
3764
const CallExpr *e) {
3865
if (builtinID == Builtin::BI__builtin_cpu_is) {
@@ -85,6 +112,9 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
85112
case X86::BI_mm_sfence:
86113
return emitIntrinsicCallOp(*this, e, "x86.sse.sfence", voidTy);
87114
case X86::BI_mm_prefetch:
115+
case X86::BI_m_prefetch:
116+
case X86::BI_m_prefetchw:
117+
return emitPrefetch(*this, builtinID, e, ops[0], getIntValueFromConstOp(ops[1]));
88118
case X86::BI__rdtsc:
89119
case X86::BI__builtin_ia32_rdtscp:
90120
case X86::BI__builtin_ia32_lzcnt_u16:
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-cir -o %t.cir -Wall -Werror
3+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
4+
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-llvm -o %t.ll -Wall -Werror
5+
// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s
6+
7+
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fno-signed-char -fclangir -emit-cir -o %t.cir -Wall -Werror
8+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
9+
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-llvm -o %t.ll -Wall -Werror
10+
// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s
11+
12+
// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG
13+
// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG
14+
15+
16+
#include <x86intrin.h>
17+
18+
void test_m_prefetch(void *p) {
19+
// CIR-LABEL: test_m_prefetch
20+
// LLVM-LABEL: test_m_prefetch
21+
// OGCG-LABEL: test_m_prefetch
22+
return _m_prefetch(p);
23+
// CIR: cir.prefetch read locality(0) %{{.*}} : !cir.ptr<!void>
24+
// LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
25+
// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
26+
}
27+
28+
void test_m_prefetch_w(void *p) {
29+
// CIR-LABEL: test_m_prefetch_w
30+
// LLVM-LABEL: test_m_prefetch_w
31+
// OGCG-LABEL: test_m_prefetch_w
32+
return _m_prefetchw(p);
33+
// CIR: cir.prefetch write locality(0) %{{.*}} : !cir.ptr<!void>
34+
// LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
35+
// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
36+
}

clang/test/CIR/CodeGen/X86/sse-builtins.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,21 @@ void test_mm_sfence(void) {
2626
// LLVM: call void @llvm.x86.sse.sfence()
2727
// OGCG: call void @llvm.x86.sse.sfence()
2828
}
29+
30+
void test_mm_prefetch(char const* p) {
31+
// CIR-LABEL: test_mm_prefetch
32+
// LLVM-LABEL: test_mm_prefetch
33+
_mm_prefetch(p, 0);
34+
// CIR: cir.prefetch read locality(0) %{{.*}} : !cir.ptr<!void>
35+
// LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
36+
// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1)
37+
}
38+
39+
void test_mm_prefetch_local(char const* p) {
40+
// CIR-LABEL: test_mm_prefetch_local
41+
// LLVM-LABEL: test_mm_prefetch_local
42+
_mm_prefetch(p, 3);
43+
// CIR: cir.prefetch read locality(3) %{{.*}} : !cir.ptr<!void>
44+
// LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
45+
// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
46+
}

0 commit comments

Comments
 (0)