Skip to content

Commit 49fa2a4

Browse files
authored
[CIR] Support x86 builtin rdtsc (llvm#180714)
This PR implements CodeGen for rdtsc builtins in CIR upstream. Towards llvm#167765
1 parent 4aa5573 commit 49fa2a4

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -860,11 +860,24 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
860860
case X86::BI_m_prefetchw:
861861
return emitPrefetch(*this, builtinID, expr, ops);
862862
case X86::BI__rdtsc:
863+
return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()), "x86.rdtsc",
864+
builder.getUInt64Ty());
863865
case X86::BI__builtin_ia32_rdtscp: {
864-
cgm.errorNYI(expr->getSourceRange(),
865-
std::string("unimplemented X86 builtin call: ") +
866-
getContext().BuiltinInfo.getName(builtinID));
867-
return mlir::Value{};
866+
mlir::Location loc = getLoc(expr->getExprLoc());
867+
mlir::Type i64Ty = builder.getUInt64Ty();
868+
mlir::Type i32Ty = builder.getUInt32Ty();
869+
mlir::Type structTy = builder.getAnonRecordTy({i64Ty, i32Ty});
870+
mlir::Value result =
871+
builder.emitIntrinsicCallOp(loc, "x86.rdtscp", structTy);
872+
873+
// Extract and store processor_id (element 1 of the returned struct)
874+
mlir::Value processorId =
875+
cir::ExtractMemberOp::create(builder, loc, i32Ty, result, 1);
876+
// ops[0] is the address to store the processor ID
877+
builder.createStore(loc, processorId, Address{ops[0], CharUnits::One()});
878+
879+
// Return timestamp (element 0 of the returned struct)
880+
return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0);
868881
}
869882
case X86::BI__builtin_ia32_lzcnt_u16:
870883
case X86::BI__builtin_ia32_lzcnt_u32:

clang/test/CIR/CodeGenBuiltins/X86/rd-builtins.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,39 @@ unsigned long long test_rdpmc(int a) {
2626
// OGCG: ret i64 %{{.*}}
2727
return _rdpmc(a);
2828
}
29+
30+
unsigned long long test_rdtsc(void) {
31+
// CIR-LABEL: @test_rdtsc
32+
// CIR: %{{.*}} = cir.call_llvm_intrinsic "x86.rdtsc" : () -> !u64i
33+
34+
// LLVM-LABEL: @test_rdtsc
35+
// LLVM: call i64 @llvm.x86.rdtsc()
36+
37+
// OGCG-LABEL: @test_rdtsc
38+
// OGCG: call i64 @llvm.x86.rdtsc()
39+
40+
return __rdtsc();
41+
}
42+
43+
unsigned long long test_rdtscp(unsigned int *a) {
44+
// CIR-LABEL: @test_rdtscp
45+
// CIR: %[[RDTSCP:.*]] = cir.call_llvm_intrinsic "x86.rdtscp" : () -> !rec_anon_struct
46+
// CIR: %[[TSC_AUX:.*]] = cir.extract_member %[[RDTSCP]][1] : !rec_anon_struct -> !u32i
47+
// CIR: cir.store {{.*}}%[[TSC_AUX]], {{%.*}} : !u32i
48+
// CIR: %[[TSC:.*]] = cir.extract_member %[[RDTSCP]][0] : !rec_anon_struct -> !u64i
49+
50+
// LLVM-LABEL: @test_rdtscp
51+
// LLVM: %[[RDTSCP:.*]] = call { i64, i32 } @llvm.x86.rdtscp()
52+
// LLVM: %[[TSC_AUX:.*]] = extractvalue { i64, i32 } %[[RDTSCP]], 1
53+
// LLVM: store i32 %[[TSC_AUX]], ptr %{{.*}}
54+
// LLVM: %[[TSC:.*]] = extractvalue { i64, i32 } %[[RDTSCP]], 0
55+
56+
// OGCG-LABEL: @test_rdtscp
57+
// OGCG: %[[RDTSCP:.*]] = call { i64, i32 } @llvm.x86.rdtscp
58+
// OGCG: %[[TSC_AUX:.*]] = extractvalue { i64, i32 } %[[RDTSCP]], 1
59+
// OGCG: store i32 %[[TSC_AUX]], ptr %{{.*}}
60+
// OGCG: %[[TSC:.*]] = extractvalue { i64, i32 } %[[RDTSCP]], 0
61+
62+
return __builtin_ia32_rdtscp(a);
63+
}
64+

0 commit comments

Comments
 (0)