https://github.com/medhatiwari created https://github.com/llvm/llvm-project/pull/170877
Handle xsave/xrstor family of X86 builtins in ClangIR Part of #167752 >From e590a91f11e4673920ed56c0da874c9c6a6e9974 Mon Sep 17 00:00:00 2001 From: Medha Tiwari <[email protected]> Date: Fri, 5 Dec 2025 21:27:29 +0530 Subject: [PATCH] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 73 +++++++- .../CIR/CodeGenBuiltins/X86/xsave-builtins.c | 175 ++++++++++++++++++ 2 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 clang/test/CIR/CodeGenBuiltins/X86/xsave-builtins.c diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 1c1ef4da20b0d..26630522de1b0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -533,9 +533,80 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, case X86::BI__builtin_ia32_xsaves: case X86::BI__builtin_ia32_xsaves64: case X86::BI__builtin_ia32_xsetbv: - case X86::BI_xsetbv: + case X86::BI_xsetbv: { + mlir::Location loc = getLoc(expr->getExprLoc()); + StringRef intrinsicName; + switch (builtinID) { + default: + llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_xsave: + intrinsicName = "x86.xsave"; + break; + case X86::BI__builtin_ia32_xsave64: + intrinsicName = "x86.xsave64"; + break; + case X86::BI__builtin_ia32_xrstor: + intrinsicName = "x86.xrstor"; + break; + case X86::BI__builtin_ia32_xrstor64: + intrinsicName = "x86.xrstor64"; + break; + case X86::BI__builtin_ia32_xsaveopt: + intrinsicName = "x86.xsaveopt"; + break; + case X86::BI__builtin_ia32_xsaveopt64: + intrinsicName = "x86.xsaveopt64"; + break; + case X86::BI__builtin_ia32_xrstors: + intrinsicName = "x86.xrstors"; + break; + case X86::BI__builtin_ia32_xrstors64: + intrinsicName = "x86.xrstors64"; + break; + case X86::BI__builtin_ia32_xsavec: + intrinsicName = "x86.xsavec"; + break; + case X86::BI__builtin_ia32_xsavec64: + intrinsicName = "x86.xsavec64"; + break; + case X86::BI__builtin_ia32_xsaves: + intrinsicName = "x86.xsaves"; + break; + case X86::BI__builtin_ia32_xsaves64: + intrinsicName = "x86.xsaves64"; + break; + case X86::BI__builtin_ia32_xsetbv: + case X86::BI_xsetbv: + intrinsicName = "x86.xsetbv"; + break; + } + + // The xsave family of instructions take a 64-bit mask that specifies + // which processor state components to save/restore. The hardware expects + // this mask split into two 32-bit registers: EDX (high 32 bits) and + // EAX (low 32 bits). + mlir::Type i32Ty = builder.getSInt32Ty(); + mlir::Type i64Ty = builder.getSInt64Ty(); + + // Mhi = (uint32_t)(ops[1] >> 32) - extract high 32 bits via right shift + cir::ConstantOp shift32 = + builder.getConstant(loc, cir::IntAttr::get(i64Ty, 32)); + mlir::Value mhi = + builder.createShift(loc, ops[1], shift32.getResult(), /*isRight=*/true); + mhi = builder.createIntCast(mhi, i32Ty); + + // Mlo = (uint32_t)ops[1] - extract low 32 bits by truncation + mlir::Value mlo = builder.createIntCast(ops[1], i32Ty); + + return emitIntrinsicCallOp(builder, loc, intrinsicName, voidTy, + mlir::ValueRange{ops[0], mhi, mlo}); + } case X86::BI__builtin_ia32_xgetbv: case X86::BI_xgetbv: + // xgetbv reads the extended control register specified by ops[0] (ECX) + // and returns the 64-bit value + return emitIntrinsicCallOp(builder, getLoc(expr->getExprLoc()), + "x86.xgetbv", builder.getUInt64Ty(), ops[0]); case X86::BI__builtin_ia32_storedqudi128_mask: case X86::BI__builtin_ia32_storedqusi128_mask: case X86::BI__builtin_ia32_storedquhi128_mask: diff --git a/clang/test/CIR/CodeGenBuiltins/X86/xsave-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/xsave-builtins.c new file mode 100644 index 0000000000000..484f6c402979d --- /dev/null +++ b/clang/test/CIR/CodeGenBuiltins/X86/xsave-builtins.c @@ -0,0 +1,175 @@ +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +xsave -target-feature +xsaveopt -target-feature +xsavec -target-feature +xsaves -fclangir -emit-cir -o %t.cir -Wall -Werror +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +xsave -target-feature +xsaveopt -target-feature +xsavec -target-feature +xsaves -fclangir -emit-llvm -o %t.ll -Wall -Werror +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -x c -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +xsave -target-feature +xsaveopt -target-feature +xsavec -target-feature +xsaves -emit-llvm -o - -Wall -Werror | FileCheck %s -check-prefix=OGCG + +void test_xsave(void *p, unsigned long long m) { + // CIR-LABEL: test_xsave + // CIR: cir.call_llvm_intrinsic "x86.xsave" + + // LLVM-LABEL: test_xsave + // LLVM: call void @llvm.x86.xsave + + // OGCG-LABEL: test_xsave + // OGCG: call void @llvm.x86.xsave + __builtin_ia32_xsave(p, m); +} + +void test_xsave64(void *p, unsigned long long m) { + // CIR-LABEL: test_xsave64 + // CIR: cir.call_llvm_intrinsic "x86.xsave64" + + // LLVM-LABEL: test_xsave64 + // LLVM: call void @llvm.x86.xsave64 + + // OGCG-LABEL: test_xsave64 + // OGCG: call void @llvm.x86.xsave64 + __builtin_ia32_xsave64(p, m); +} + +void test_xrstor(void *p, unsigned long long m) { + // CIR-LABEL: test_xrstor + // CIR: cir.call_llvm_intrinsic "x86.xrstor" + + // LLVM-LABEL: test_xrstor + // LLVM: call void @llvm.x86.xrstor + + // OGCG-LABEL: test_xrstor + // OGCG: call void @llvm.x86.xrstor + __builtin_ia32_xrstor(p, m); +} + +void test_xrstor64(void *p, unsigned long long m) { + // CIR-LABEL: test_xrstor64 + // CIR: cir.call_llvm_intrinsic "x86.xrstor64" + + // LLVM-LABEL: test_xrstor64 + // LLVM: call void @llvm.x86.xrstor64 + + // OGCG-LABEL: test_xrstor64 + // OGCG: call void @llvm.x86.xrstor64 + __builtin_ia32_xrstor64(p, m); +} + +void test_xsaveopt(void *p, unsigned long long m) { + // CIR-LABEL: test_xsaveopt + // CIR: cir.call_llvm_intrinsic "x86.xsaveopt" + + // LLVM-LABEL: test_xsaveopt + // LLVM: call void @llvm.x86.xsaveopt + + // OGCG-LABEL: test_xsaveopt + // OGCG: call void @llvm.x86.xsaveopt + __builtin_ia32_xsaveopt(p, m); +} + +void test_xsaveopt64(void *p, unsigned long long m) { + // CIR-LABEL: test_xsaveopt64 + // CIR: cir.call_llvm_intrinsic "x86.xsaveopt64" + + // LLVM-LABEL: test_xsaveopt64 + // LLVM: call void @llvm.x86.xsaveopt64 + + // OGCG-LABEL: test_xsaveopt64 + // OGCG: call void @llvm.x86.xsaveopt64 + __builtin_ia32_xsaveopt64(p, m); +} + +void test_xsavec(void *p, unsigned long long m) { + // CIR-LABEL: test_xsavec + // CIR: cir.call_llvm_intrinsic "x86.xsavec" + + // LLVM-LABEL: test_xsavec + // LLVM: call void @llvm.x86.xsavec + + // OGCG-LABEL: test_xsavec + // OGCG: call void @llvm.x86.xsavec + __builtin_ia32_xsavec(p, m); +} + +void test_xsavec64(void *p, unsigned long long m) { + // CIR-LABEL: test_xsavec64 + // CIR: cir.call_llvm_intrinsic "x86.xsavec64" + + // LLVM-LABEL: test_xsavec64 + // LLVM: call void @llvm.x86.xsavec64 + + // OGCG-LABEL: test_xsavec64 + // OGCG: call void @llvm.x86.xsavec64 + __builtin_ia32_xsavec64(p, m); +} + +void test_xsaves(void *p, unsigned long long m) { + // CIR-LABEL: test_xsaves + // CIR: cir.call_llvm_intrinsic "x86.xsaves" + + // LLVM-LABEL: test_xsaves + // LLVM: call void @llvm.x86.xsaves + + // OGCG-LABEL: test_xsaves + // OGCG: call void @llvm.x86.xsaves + __builtin_ia32_xsaves(p, m); +} + +void test_xsaves64(void *p, unsigned long long m) { + // CIR-LABEL: test_xsaves64 + // CIR: cir.call_llvm_intrinsic "x86.xsaves64" + + // LLVM-LABEL: test_xsaves64 + // LLVM: call void @llvm.x86.xsaves64 + + // OGCG-LABEL: test_xsaves64 + // OGCG: call void @llvm.x86.xsaves64 + __builtin_ia32_xsaves64(p, m); +} + +void test_xrstors(void *p, unsigned long long m) { + // CIR-LABEL: test_xrstors + // CIR: cir.call_llvm_intrinsic "x86.xrstors" + + // LLVM-LABEL: test_xrstors + // LLVM: call void @llvm.x86.xrstors + + // OGCG-LABEL: test_xrstors + // OGCG: call void @llvm.x86.xrstors + __builtin_ia32_xrstors(p, m); +} + +void test_xrstors64(void *p, unsigned long long m) { + // CIR-LABEL: test_xrstors64 + // CIR: cir.call_llvm_intrinsic "x86.xrstors64" + + // LLVM-LABEL: test_xrstors64 + // LLVM: call void @llvm.x86.xrstors64 + + // OGCG-LABEL: test_xrstors64 + // OGCG: call void @llvm.x86.xrstors64 + __builtin_ia32_xrstors64(p, m); +} + +unsigned long long test_xgetbv(unsigned int a) { + // CIR-LABEL: test_xgetbv + // CIR: cir.call_llvm_intrinsic "x86.xgetbv" + + // LLVM-LABEL: test_xgetbv + // LLVM: call i64 @llvm.x86.xgetbv + + // OGCG-LABEL: test_xgetbv + // OGCG: call i64 @llvm.x86.xgetbv + return __builtin_ia32_xgetbv(a); +} + +void test_xsetbv(unsigned int a, unsigned long long m) { + // CIR-LABEL: test_xsetbv + // CIR: cir.call_llvm_intrinsic "x86.xsetbv" + + // LLVM-LABEL: test_xsetbv + // LLVM: call void @llvm.x86.xsetbv + + // OGCG-LABEL: test_xsetbv + // OGCG: call void @llvm.x86.xsetbv + __builtin_ia32_xsetbv(a, m); +} + _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
