[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
https://github.com/andykaylor closed https://github.com/llvm/llvm-project/pull/170877 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
https://github.com/andykaylor edited https://github.com/llvm/llvm-project/pull/170877 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
@@ -7,23 +7,35 @@
void test_xsave(void *p, unsigned long long m) {
// CIR-LABEL: test_xsave
- // CIR: cir.const #cir.int<32> : !s64i
- // CIR: cir.shift(right, {{.*}} : !u64i, {{.*}} : !s64i) -> !u64i
- // CIR: cir.cast integral %{{.*}} : !u64i -> !s32i
- // CIR: cir.cast integral %{{.*}} : !u64i -> !s32i
- // CIR: cir.call_llvm_intrinsic "x86.xsave"
+ // CIR: [[P:%.*]] = cir.load {{.*}} : !cir.ptr>,
!cir.ptr
+ // CIR: [[M:%.*]] = cir.load {{.*}} : !cir.ptr, !u64i
+ // CIR: [[CONST:%.*]] = cir.const #cir.int<32> : !s64i
+ // CIR: [[SHIFT:%.*]] = cir.shift(right, [[M]] : !u64i, [[CONST]] : !s64i)
-> !u64i
+ // CIR: [[CAST1:%.*]] = cir.cast integral [[SHIFT]] : !u64i -> !s32i
+ // CIR: [[CAST2:%.*]] = cir.cast integral [[M]] : !u64i -> !s32i
+ // CIR: cir.call_llvm_intrinsic "x86.xsave" [[P]], [[CAST1]], [[CAST2]]
// LLVM-LABEL: test_xsave
- // LLVM: lshr i64 {{.*}}, 32
- // LLVM: trunc i64 {{.*}} to i32
- // LLVM: trunc i64 {{.*}} to i32
- // LLVM: call void @llvm.x86.xsave(ptr {{.*}}, i32 {{.*}}, i32 {{.*}})
+ // LLVM: [[LP:%.*]] = load ptr, ptr
+ // LLVM: [[LM:%.*]] = load i64, ptr
+ // LLVM: [[LSHIFT:%.*]] = lshr i64 [[LM]], 32
+ // LLVM: [[LCAST1:%.*]] = trunc i64 [[LSHIFT]] to i32
+ // LLVM: [[LCAST2:%.*]] = trunc i64 [[LM]] to i32
+ // LLVM: call void @llvm.x86.xsave(ptr [[LP]], i32 [[LCAST1]], i32
[[LCAST2]])
// OGCG-LABEL: test_xsave
- // OGCG: call void @llvm.x86.xsave
+ // OGCG: [[OP:%.*]] = load ptr, ptr
andykaylor wrote:
This is fine, but it isn't necessary to use different identifiers between LLVM
checks and OGCG checks. We often even reuse identifiers between different test
cases with the same output type.
https://github.com/llvm/llvm-project/pull/170877
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
https://github.com/andykaylor approved this pull request. lgtm https://github.com/llvm/llvm-project/pull/170877 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
@@ -0,0 +1,182 @@
+// 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.const #cir.int<32> : !s64i
+ // CIR: cir.shift(right, {{.*}} : !u64i, {{.*}} : !s64i) -> !u64i
+ // CIR: cir.cast integral %{{.*}} : !u64i -> !s32i
+ // CIR: cir.cast integral %{{.*}} : !u64i -> !s32i
+ // CIR: cir.call_llvm_intrinsic "x86.xsave"
medhatiwari wrote:
Updated! Added detailed checks for test_xsave showing the full use-def flow
(load → const → shift → cast → intrinsic call) for CIR, LLVM, and OGCG. Added a
comment explaining that the other tests follow the same pattern.
https://github.com/llvm/llvm-project/pull/170877
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
https://github.com/medhatiwari updated
https://github.com/llvm/llvm-project/pull/170877
>From e590a91f11e4673920ed56c0da874c9c6a6e9974 Mon Sep 17 00:00:00 2001
From: Medha Tiwari
Date: Fri, 5 Dec 2025 21:27:29 +0530
Subject: [PATCH 1/3] [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 0..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,
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
@@ -0,0 +1,182 @@
+// 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.const #cir.int<32> : !s64i
+ // CIR: cir.shift(right, {{.*}} : !u64i, {{.*}} : !s64i) -> !u64i
+ // CIR: cir.cast integral %{{.*}} : !u64i -> !s32i
+ // CIR: cir.cast integral %{{.*}} : !u64i -> !s32i
+ // CIR: cir.call_llvm_intrinsic "x86.xsave"
andykaylor wrote:
```suggestion
// CIR: [[P:.*]] = cir.load
// CIR: [[M:.*]] = cir.load
// CIR: [[CONST:.*]] = cir.const #cir.int<32> : !s64i
// CIR: [[SHIFT:.*]] = cir.shift(right, [[M]] : !u64i, [[CONST]] : !s64i) ->
!u64i
// CIR: [[CAST1:.*]] = cir.cast integral %[[SHIFT]] : !u64i -> !s32i
// CIR: [[CAST2:.*]] = cir.cast integral %[[M]] : !u64i -> !s32i
// CIR: cir.call_llvm_intrinsic "x86.xsave" %[[P]], %[[CAST1]], %[[CAST2]]
```
This is the level of detail I was hoping to see, here and in the LLVM and OGCG
checks for this case. I want to be able to see the entire use-def flow. It's
fine to omit it for the others though, since as you noted they follow the same
pattern, though a comment explaining that would be useful.
https://github.com/llvm/llvm-project/pull/170877
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
https://github.com/medhatiwari updated
https://github.com/llvm/llvm-project/pull/170877
>From e590a91f11e4673920ed56c0da874c9c6a6e9974 Mon Sep 17 00:00:00 2001
From: Medha Tiwari
Date: Fri, 5 Dec 2025 21:27:29 +0530
Subject: [PATCH 1/2] [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 0..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,
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff origin/main HEAD --extensions cpp,c -- clang/test/CIR/CodeGenBuiltins/X86/xsave-builtins.c clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp --diff_from_common_commit `` :warning: The reproduction instructions above might return results for more than one PR in a stack if you are using a stacked PR workflow. You can limit the results by changing `origin/main` to the base branch/commit you want to compare against. :warning: View the diff from clang-format here. ``diff diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index be0bf5832..850aa0ecb 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -589,8 +589,8 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, // Mhi = (uint32_t)(ops[1] >> 32) - extract high 32 bits via right shift cir::ConstantOp shift32 = builder.getSInt64(32, loc); -mlir::Value mhi = -builder.createShift(loc, ops[1], shift32.getResult(), /*isShiftLeft=*/false); +mlir::Value mhi = builder.createShift(loc, ops[1], shift32.getResult(), + /*isShiftLeft=*/false); mhi = builder.createIntCast(mhi, i32Ty); // Mlo = (uint32_t)ops[1] - extract low 32 bits by truncation `` https://github.com/llvm/llvm-project/pull/170877 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
@@ -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"
medhatiwari wrote:
Added detailed CIR and LLVM checks for test_xsave showing the shift, casts, and
intrinsic call with parameters. The pattern is the same for all other xsave
variants, so I kept just the intrinsic name check for the rest to avoid
redundancy.
https://github.com/llvm/llvm-project/pull/170877
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
@@ -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));
medhatiwari wrote:
Done, changed to builder.getSInt64(32, loc). Also fixed the parameter name to
/*isShiftLeft=*/false for clarity.
https://github.com/llvm/llvm-project/pull/170877
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
https://github.com/medhatiwari updated
https://github.com/llvm/llvm-project/pull/170877
>From e590a91f11e4673920ed56c0da874c9c6a6e9974 Mon Sep 17 00:00:00 2001
From: Medha Tiwari
Date: Fri, 5 Dec 2025 21:27:29 +0530
Subject: [PATCH 1/2] [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 0..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,
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
@@ -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));
andykaylor wrote:
```suggestion
cir::ConstantOp shift32 = builder.getSInt64(32, loc);
```
https://github.com/llvm/llvm-project/pull/170877
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
@@ -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"
andykaylor wrote:
Can you add checks that show all the casts, shifts, and parameters?
https://github.com/llvm/llvm-project/pull/170877
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
https://github.com/andykaylor commented: Thanks for the PR! This looks pretty good. I just have one minor suggestion and a request for improving the test. https://github.com/llvm/llvm-project/pull/170877 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
https://github.com/andykaylor edited https://github.com/llvm/llvm-project/pull/170877 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
llvmbot wrote:
@llvm/pr-subscribers-clang
Author: Medha Tiwari (medhatiwari)
Changes
Handle xsave/xrstor family of X86 builtins in ClangIR
Part of #167752
---
Full diff: https://github.com/llvm/llvm-project/pull/170877.diff
2 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp (+72-1)
- (added) clang/test/CIR/CodeGenBuiltins/X86/xsave-builtins.c (+175)
``diff
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 0..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.
[clang] [CIR][X86] Implement xsave/xrstor builtins Fixes part of #167752 (PR #170877)
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
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 0..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 -We
