[CIR] Support x86 builtin rdtsc (#180714)

This PR implements CodeGen for rdtsc builtins in CIR upstream.
Towards #167765
This commit is contained in:
Aditya Trivedi 2026-02-14 05:10:48 +05:30 committed by GitHub
parent 4aa5573b14
commit 49fa2a4d24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 4 deletions

View File

@ -860,11 +860,24 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI_m_prefetchw:
return emitPrefetch(*this, builtinID, expr, ops);
case X86::BI__rdtsc:
return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()), "x86.rdtsc",
builder.getUInt64Ty());
case X86::BI__builtin_ia32_rdtscp: {
cgm.errorNYI(expr->getSourceRange(),
std::string("unimplemented X86 builtin call: ") +
getContext().BuiltinInfo.getName(builtinID));
return mlir::Value{};
mlir::Location loc = getLoc(expr->getExprLoc());
mlir::Type i64Ty = builder.getUInt64Ty();
mlir::Type i32Ty = builder.getUInt32Ty();
mlir::Type structTy = builder.getAnonRecordTy({i64Ty, i32Ty});
mlir::Value result =
builder.emitIntrinsicCallOp(loc, "x86.rdtscp", structTy);
// Extract and store processor_id (element 1 of the returned struct)
mlir::Value processorId =
cir::ExtractMemberOp::create(builder, loc, i32Ty, result, 1);
// ops[0] is the address to store the processor ID
builder.createStore(loc, processorId, Address{ops[0], CharUnits::One()});
// Return timestamp (element 0 of the returned struct)
return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0);
}
case X86::BI__builtin_ia32_lzcnt_u16:
case X86::BI__builtin_ia32_lzcnt_u32:

View File

@ -26,3 +26,39 @@ unsigned long long test_rdpmc(int a) {
// OGCG: ret i64 %{{.*}}
return _rdpmc(a);
}
unsigned long long test_rdtsc(void) {
// CIR-LABEL: @test_rdtsc
// CIR: %{{.*}} = cir.call_llvm_intrinsic "x86.rdtsc" : () -> !u64i
// LLVM-LABEL: @test_rdtsc
// LLVM: call i64 @llvm.x86.rdtsc()
// OGCG-LABEL: @test_rdtsc
// OGCG: call i64 @llvm.x86.rdtsc()
return __rdtsc();
}
unsigned long long test_rdtscp(unsigned int *a) {
// CIR-LABEL: @test_rdtscp
// CIR: %[[RDTSCP:.*]] = cir.call_llvm_intrinsic "x86.rdtscp" : () -> !rec_anon_struct
// CIR: %[[TSC_AUX:.*]] = cir.extract_member %[[RDTSCP]][1] : !rec_anon_struct -> !u32i
// CIR: cir.store {{.*}}%[[TSC_AUX]], {{%.*}} : !u32i
// CIR: %[[TSC:.*]] = cir.extract_member %[[RDTSCP]][0] : !rec_anon_struct -> !u64i
// LLVM-LABEL: @test_rdtscp
// LLVM: %[[RDTSCP:.*]] = call { i64, i32 } @llvm.x86.rdtscp()
// LLVM: %[[TSC_AUX:.*]] = extractvalue { i64, i32 } %[[RDTSCP]], 1
// LLVM: store i32 %[[TSC_AUX]], ptr %{{.*}}
// LLVM: %[[TSC:.*]] = extractvalue { i64, i32 } %[[RDTSCP]], 0
// OGCG-LABEL: @test_rdtscp
// OGCG: %[[RDTSCP:.*]] = call { i64, i32 } @llvm.x86.rdtscp
// OGCG: %[[TSC_AUX:.*]] = extractvalue { i64, i32 } %[[RDTSCP]], 1
// OGCG: store i32 %[[TSC_AUX]], ptr %{{.*}}
// OGCG: %[[TSC:.*]] = extractvalue { i64, i32 } %[[RDTSCP]], 0
return __builtin_ia32_rdtscp(a);
}