Skip to content

Commit 42c15b9

Browse files
committed
[CIR][CIRGen][Builtin][X86] Lower __rdtscp
1 parent 74f16f7 commit 42c15b9

File tree

3 files changed

+60
-9
lines changed

3 files changed

+60
-9
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,5 +144,30 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned BuiltinID,
144144
getLoc(E->getExprLoc()), builder.getStringAttr("x86.rdtsc"), intTy)
145145
.getResult();
146146
}
147+
case X86::BI__builtin_ia32_rdtscp: {
148+
149+
// For rdtscp, we need to create a proper struct type to hold {i64, i32}
150+
mlir::Type i64Ty = cir::IntType::get(&getMLIRContext(), 64, false);
151+
mlir::Type i32Ty = cir::IntType::get(&getMLIRContext(), 32, false);
152+
153+
mlir::Type ResTy = cir::RecordType::get(&getMLIRContext(), {i64Ty, i32Ty},
154+
mlir::StringAttr(), false, false,
155+
cir::RecordType::Struct);
156+
157+
auto Call = builder
158+
.create<cir::LLVMIntrinsicCallOp>(
159+
getLoc(E->getExprLoc()),
160+
builder.getStringAttr("x86.rdtscp"), ResTy)
161+
.getResult();
162+
163+
// Store processor ID in address param
164+
mlir::Value PID = builder.create<cir::ExtractMemberOp>(
165+
getLoc(E->getExprLoc()), i32Ty, Call, 1);
166+
builder.create<cir::StoreOp>(getLoc(E->getExprLoc()), PID, Ops[0]);
167+
168+
// Return the timestamp at index 0
169+
return builder.create<cir::ExtractMemberOp>(getLoc(E->getExprLoc()), i64Ty,
170+
Call, 0);
171+
}
147172
}
148173
}

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,3 @@ void test_mm_sfence() {
4545
// CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse.sfence" : () -> !void
4646
// LLVM: call void @llvm.x86.sse.sfence()
4747
}
48-
49-
unsigned long long test_rdtsc() {
50-
// CIR-LABEL: @test_rdtsc
51-
// LLVM-LABEL: @test_rdtsc
52-
return __rdtsc();
53-
// CIR: {{%.*}} = cir.llvm.intrinsic "x86.rdtsc" : () -> !u64i
54-
// LLVM: call i64 @llvm.x86.rdtsc
55-
}
56-
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s
2+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s
4+
// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
5+
6+
// This test mimics clang/test/CodeGen/X86/rd-builtins.c, which eventually
7+
// CIR shall be able to support fully.
8+
9+
#include <x86intrin.h>
10+
11+
unsigned long long test_rdtsc() {
12+
// CIR-LABEL: @test_rdtsc
13+
// LLVM-LABEL: @test_rdtsc
14+
return __rdtsc();
15+
// CIR: {{%.*}} = cir.llvm.intrinsic "x86.rdtsc" : () -> !u64i
16+
// LLVM: call i64 @llvm.x86.rdtsc
17+
}
18+
19+
unsigned long long test_rdtscp(unsigned int *a) {
20+
21+
return __rdtscp(a);
22+
23+
// CIR-LABEL: @__rdtscp
24+
// CIR: [[RDTSCP:%.*]] = cir.llvm.intrinsic "x86.rdtscp" : () -> !rec_anon_struct
25+
// CIR: [[TSC_AUX:%.*]] = cir.extract_member [[RDTSCP]][1] : !rec_anon_struct -> !u32i
26+
// CIR: cir.store [[TSC_AUX]], %{{.*}} : !u32i, !cir.ptr<!u32i>
27+
// CIR: {{%.*}} = cir.extract_member [[RDTSCP]][0] : !rec_anon_struct -> !u64i
28+
29+
// LLVM: @test_rdtscp
30+
// LLVM: [[RDTSCP:%.*]] = call { i64, i32 } @llvm.x86.rdtscp
31+
// LLVM: [[TSC_AUX:%.*]] = extractvalue { i64, i32 } [[RDTSCP]], 1
32+
// LLVM: store i32 [[TSC_AUX]], ptr %{{.*}}
33+
// LLVM: [[TSC:%.*]] = extractvalue { i64, i32 } [[RDTSCP]], 0
34+
}
35+

0 commit comments

Comments
 (0)