[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
https://github.com/borysperski updated https://github.com/llvm/llvm-project/pull/215787 >From df49b7b85f79003a47f126a3cd30ca67b723b73f Mon Sep 17 00:00:00 2001 From: Borys Perski <[email protected]> Date: Wed, 12 Aug 2026 14:12:55 +0200 Subject: [PATCH 1/3] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp| 91 +++ .../CIR/CodeGenBuiltins/X86/avx-builtins.c| 120 + .../CIR/CodeGenBuiltins/X86/sse41-builtins.c | 253 ++ 3 files changed, 464 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 9228367fdd44f..e1ce2e99e67b6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -86,6 +86,26 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, return maskVec; } +static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder, + mlir::Location loc, mlir::Value x, + unsigned roundingControl) { + constexpr unsigned roundingMask = 0b11; + unsigned roundingMode = roundingControl & roundingMask; + + switch (roundingMode) { + default: +llvm_unreachable("Invalid rounding mode"); + case 0b00: +return cir::RoundEvenOp::create(builder, loc, x); + case 0b01: +return cir::FloorOp::create(builder, loc, x); + case 0b10: +return cir::CeilOp::create(builder, loc, x); + case 0b11: +return cir::TruncOp::create(builder, loc, x); + } +} + static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder, mlir::Location loc, ArrayRef ops) { @@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { // Return timestamp (element 0 of the returned struct) return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0); } + case X86::BI__builtin_ia32_roundps: + case X86::BI__builtin_ia32_roundpd: + case X86::BI__builtin_ia32_roundps256: + case X86::BI__builtin_ia32_roundpd256: { +unsigned m = +ops[1].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundps: +intrinsicName = "x86.sse41.round.ps"; +break; + case X86::BI__builtin_ia32_roundpd: +intrinsicName = "x86.sse41.round.pd"; +break; + case X86::BI__builtin_ia32_roundps256: +intrinsicName = "x86.avx.round.ps.256"; +break; + case X86::BI__builtin_ia32_roundpd256: +intrinsicName = "x86.avx.round.pd.256"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +return emitX86RoundImmediate(builder, loc, ops[0], m); + } + case X86::BI__builtin_ia32_roundss: + case X86::BI__builtin_ia32_roundsd: { +unsigned m = +ops[2].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundss: +intrinsicName = "x86.sse41.round.ss"; +break; + case X86::BI__builtin_ia32_roundsd: +intrinsicName = "x86.sse41.round.sd"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0); +mlir::Value roundedAt0 = emitX86RoundImmediate(builder, loc, valAt0, m); + +return builder.createInsertElement(loc, ops[0], roundedAt0, 0); + } case X86::BI__builtin_ia32_lzcnt_u16: case X86::BI__builtin_ia32_lzcnt_u32: case X86::BI__builtin_ia32_lzcnt_u64: { diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c index 174fcbc7b0080..773702af5ea25 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c @@ -30,6 +30,54 @@ #include +__m256d test_mm256_ceil_pd(__m256d x) { + // CIR-LABEL:
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
@@ -86,6 +86,26 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder,
mlir::Location loc,
return maskVec;
}
+static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder,
+ mlir::Location loc, mlir::Value x,
+ unsigned roundingControl) {
+ constexpr unsigned roundingMask = 0b11;
borysperski wrote:
Thanks, done.
https://github.com/llvm/llvm-project/pull/215787
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
@@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
const CallExpr *expr) {
// Return timestamp (element 0 of the returned struct)
return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0);
}
+ case X86::BI__builtin_ia32_roundps:
+ case X86::BI__builtin_ia32_roundpd:
+ case X86::BI__builtin_ia32_roundps256:
+ case X86::BI__builtin_ia32_roundpd256: {
+unsigned m =
+ops[1].getDefiningOp().getIntValue().getZExtValue();
+constexpr unsigned mxcsrMask = 0b100;
+constexpr unsigned fRoundNoExcMask = 0b1000;
+unsigned useMXCSR = mxcsrMask & m;
+unsigned fRoundNoExc = fRoundNoExcMask & m;
+
+mlir::Location loc = getLoc(expr->getExprLoc());
+
+if (useMXCSR || !fRoundNoExc) {
+ StringRef intrinsicName;
+ switch (builtinID) {
+ default:
+llvm_unreachable("Unexpected builtin");
+ case X86::BI__builtin_ia32_roundps:
+intrinsicName = "x86.sse41.round.ps";
+break;
+ case X86::BI__builtin_ia32_roundpd:
+intrinsicName = "x86.sse41.round.pd";
+break;
+ case X86::BI__builtin_ia32_roundps256:
+intrinsicName = "x86.avx.round.ps.256";
+break;
+ case X86::BI__builtin_ia32_roundpd256:
+intrinsicName = "x86.avx.round.pd.256";
+break;
+ }
+
+ mlir::Type resTy = ops[0].getType();
+ return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops);
+}
+
+return emitX86RoundImmediate(builder, loc, ops[0], m);
+ }
+ case X86::BI__builtin_ia32_roundss:
+ case X86::BI__builtin_ia32_roundsd: {
borysperski wrote:
Thanks, done.
https://github.com/llvm/llvm-project/pull/215787
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
https://github.com/borysperski updated https://github.com/llvm/llvm-project/pull/215787 >From df49b7b85f79003a47f126a3cd30ca67b723b73f Mon Sep 17 00:00:00 2001 From: Borys Perski <[email protected]> Date: Wed, 12 Aug 2026 14:12:55 +0200 Subject: [PATCH 1/2] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp| 91 +++ .../CIR/CodeGenBuiltins/X86/avx-builtins.c| 120 + .../CIR/CodeGenBuiltins/X86/sse41-builtins.c | 253 ++ 3 files changed, 464 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 9228367fdd44f..e1ce2e99e67b6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -86,6 +86,26 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, return maskVec; } +static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder, + mlir::Location loc, mlir::Value x, + unsigned roundingControl) { + constexpr unsigned roundingMask = 0b11; + unsigned roundingMode = roundingControl & roundingMask; + + switch (roundingMode) { + default: +llvm_unreachable("Invalid rounding mode"); + case 0b00: +return cir::RoundEvenOp::create(builder, loc, x); + case 0b01: +return cir::FloorOp::create(builder, loc, x); + case 0b10: +return cir::CeilOp::create(builder, loc, x); + case 0b11: +return cir::TruncOp::create(builder, loc, x); + } +} + static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder, mlir::Location loc, ArrayRef ops) { @@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { // Return timestamp (element 0 of the returned struct) return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0); } + case X86::BI__builtin_ia32_roundps: + case X86::BI__builtin_ia32_roundpd: + case X86::BI__builtin_ia32_roundps256: + case X86::BI__builtin_ia32_roundpd256: { +unsigned m = +ops[1].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundps: +intrinsicName = "x86.sse41.round.ps"; +break; + case X86::BI__builtin_ia32_roundpd: +intrinsicName = "x86.sse41.round.pd"; +break; + case X86::BI__builtin_ia32_roundps256: +intrinsicName = "x86.avx.round.ps.256"; +break; + case X86::BI__builtin_ia32_roundpd256: +intrinsicName = "x86.avx.round.pd.256"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +return emitX86RoundImmediate(builder, loc, ops[0], m); + } + case X86::BI__builtin_ia32_roundss: + case X86::BI__builtin_ia32_roundsd: { +unsigned m = +ops[2].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundss: +intrinsicName = "x86.sse41.round.ss"; +break; + case X86::BI__builtin_ia32_roundsd: +intrinsicName = "x86.sse41.round.sd"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0); +mlir::Value roundedAt0 = emitX86RoundImmediate(builder, loc, valAt0, m); + +return builder.createInsertElement(loc, ops[0], roundedAt0, 0); + } case X86::BI__builtin_ia32_lzcnt_u16: case X86::BI__builtin_ia32_lzcnt_u32: case X86::BI__builtin_ia32_lzcnt_u64: { diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c index 174fcbc7b0080..773702af5ea25 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c @@ -30,6 +30,54 @@ #include +__m256d test_mm256_ceil_pd(__m256d x) { + // CIR-LABEL:
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
https://github.com/borysperski updated https://github.com/llvm/llvm-project/pull/215787 >From df49b7b85f79003a47f126a3cd30ca67b723b73f Mon Sep 17 00:00:00 2001 From: Borys Perski <[email protected]> Date: Wed, 12 Aug 2026 14:12:55 +0200 Subject: [PATCH] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp| 91 +++ .../CIR/CodeGenBuiltins/X86/avx-builtins.c| 120 + .../CIR/CodeGenBuiltins/X86/sse41-builtins.c | 253 ++ 3 files changed, 464 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 9228367fdd44f..e1ce2e99e67b6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -86,6 +86,26 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, return maskVec; } +static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder, + mlir::Location loc, mlir::Value x, + unsigned roundingControl) { + constexpr unsigned roundingMask = 0b11; + unsigned roundingMode = roundingControl & roundingMask; + + switch (roundingMode) { + default: +llvm_unreachable("Invalid rounding mode"); + case 0b00: +return cir::RoundEvenOp::create(builder, loc, x); + case 0b01: +return cir::FloorOp::create(builder, loc, x); + case 0b10: +return cir::CeilOp::create(builder, loc, x); + case 0b11: +return cir::TruncOp::create(builder, loc, x); + } +} + static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder, mlir::Location loc, ArrayRef ops) { @@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { // Return timestamp (element 0 of the returned struct) return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0); } + case X86::BI__builtin_ia32_roundps: + case X86::BI__builtin_ia32_roundpd: + case X86::BI__builtin_ia32_roundps256: + case X86::BI__builtin_ia32_roundpd256: { +unsigned m = +ops[1].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundps: +intrinsicName = "x86.sse41.round.ps"; +break; + case X86::BI__builtin_ia32_roundpd: +intrinsicName = "x86.sse41.round.pd"; +break; + case X86::BI__builtin_ia32_roundps256: +intrinsicName = "x86.avx.round.ps.256"; +break; + case X86::BI__builtin_ia32_roundpd256: +intrinsicName = "x86.avx.round.pd.256"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +return emitX86RoundImmediate(builder, loc, ops[0], m); + } + case X86::BI__builtin_ia32_roundss: + case X86::BI__builtin_ia32_roundsd: { +unsigned m = +ops[2].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundss: +intrinsicName = "x86.sse41.round.ss"; +break; + case X86::BI__builtin_ia32_roundsd: +intrinsicName = "x86.sse41.round.sd"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0); +mlir::Value roundedAt0 = emitX86RoundImmediate(builder, loc, valAt0, m); + +return builder.createInsertElement(loc, ops[0], roundedAt0, 0); + } case X86::BI__builtin_ia32_lzcnt_u16: case X86::BI__builtin_ia32_lzcnt_u32: case X86::BI__builtin_ia32_lzcnt_u64: { diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c index 174fcbc7b0080..773702af5ea25 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c @@ -30,6 +30,54 @@ #include +__m256d test_mm256_ceil_pd(__m256d x) { + // CIR-LABEL: test_mm256_ceil_pd
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
@@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
const CallExpr *expr) {
// Return timestamp (element 0 of the returned struct)
return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0);
}
+ case X86::BI__builtin_ia32_roundps:
+ case X86::BI__builtin_ia32_roundpd:
+ case X86::BI__builtin_ia32_roundps256:
+ case X86::BI__builtin_ia32_roundpd256: {
+unsigned m =
+ops[1].getDefiningOp().getIntValue().getZExtValue();
+constexpr unsigned mxcsrMask = 0b100;
+constexpr unsigned fRoundNoExcMask = 0b1000;
+unsigned useMXCSR = mxcsrMask & m;
+unsigned fRoundNoExc = fRoundNoExcMask & m;
+
+mlir::Location loc = getLoc(expr->getExprLoc());
+
+if (useMXCSR || !fRoundNoExc) {
borysperski wrote:
@andykaylor thanks for the detailed analysis, and thanks @phoebewang for the
additional context. Could you let me know which approach I should take? Happy
to do the work - just want to make sure I'm heading in the right direction.
https://github.com/llvm/llvm-project/pull/215787
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
@@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
const CallExpr *expr) {
// Return timestamp (element 0 of the returned struct)
return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0);
}
+ case X86::BI__builtin_ia32_roundps:
+ case X86::BI__builtin_ia32_roundpd:
+ case X86::BI__builtin_ia32_roundps256:
+ case X86::BI__builtin_ia32_roundpd256: {
+unsigned m =
+ops[1].getDefiningOp().getIntValue().getZExtValue();
+constexpr unsigned mxcsrMask = 0b100;
+constexpr unsigned fRoundNoExcMask = 0b1000;
+unsigned useMXCSR = mxcsrMask & m;
+unsigned fRoundNoExc = fRoundNoExcMask & m;
+
+mlir::Location loc = getLoc(expr->getExprLoc());
+
+if (useMXCSR || !fRoundNoExc) {
phoebewang wrote:
> If `_MM_FROUND_CUR_DIRECTION` is set (`useMXCSR` here), we should be using
> the constrained intrinsics to prevent code motion relative to calls that
> change the rounding mode. Calling `llvm.experimental.constrained.round` (or
> `cir::RoundOp` for this PR) will achieve that while doing the rounding using
> the current rounding mode.
We checked it
[here](https://github.com/llvm/llvm-project/pull/171227/changes#diff-001b3c346c16a48c23aec37a4962d1ed5c10262df50599c45d71e8d64e60e955R87)
before selecting to LLVM intrinsics. For `_MM_FROUND_CUR_DIRECTION`, we still
use X86 intrinsics. Currently, target intrinsics are not well modeled in
StrictFP. So, it's not a new issue.
> If `_MM_FROUND_NO_EXC` is set, we need to suppress exceptions. Calling a
> constrained intrinsic with `fpexcept.ignore` doesn't do that (or at least the
> semantics of the intrinsic don't guarantee it). That's just supposed to be a
> hint to the optimizer that it can ignore the possibility that the operation
> will raise an exception. It appears that the backend is setting the no
> exception bit based on the metadata argument, but the intrinsic isn't defined
> to require that.
`_MM_FROUND_NO_EXC` is coupled with RoundingControl. It's mainly used as do not
care, rather than do not except, though they are the same thing when using
target intrinsic. The best way to do would lower `fpexcept.ignore` into the
AVX512 RC instructions, but only 512-bit supports it. So, we won't force it.
> If `_MM_FROUND_NO_EXC` is not set but we are in strict FP mode, we should be
> using the constrained intrinsics to prevent code motion relative to calls
> that read the exception state.
Note, the FRoundNoExc only masks the precision exception bit.
In a word, it's an existing problem than constrained intrinsics cannot fully
represent the complex target intrinsic attributes. We have little to do within
the current constrained intrinsics design.
https://github.com/llvm/llvm-project/pull/215787
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
https://github.com/borysperski created https://github.com/llvm/llvm-project/pull/215787 Issue #167765 >From df49b7b85f79003a47f126a3cd30ca67b723b73f Mon Sep 17 00:00:00 2001 From: Borys Perski <[email protected]> Date: Wed, 12 Aug 2026 14:12:55 +0200 Subject: [PATCH] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp| 91 +++ .../CIR/CodeGenBuiltins/X86/avx-builtins.c| 120 + .../CIR/CodeGenBuiltins/X86/sse41-builtins.c | 253 ++ 3 files changed, 464 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 9228367fdd44f..e1ce2e99e67b6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -86,6 +86,26 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, return maskVec; } +static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder, + mlir::Location loc, mlir::Value x, + unsigned roundingControl) { + constexpr unsigned roundingMask = 0b11; + unsigned roundingMode = roundingControl & roundingMask; + + switch (roundingMode) { + default: +llvm_unreachable("Invalid rounding mode"); + case 0b00: +return cir::RoundEvenOp::create(builder, loc, x); + case 0b01: +return cir::FloorOp::create(builder, loc, x); + case 0b10: +return cir::CeilOp::create(builder, loc, x); + case 0b11: +return cir::TruncOp::create(builder, loc, x); + } +} + static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder, mlir::Location loc, ArrayRef ops) { @@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { // Return timestamp (element 0 of the returned struct) return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0); } + case X86::BI__builtin_ia32_roundps: + case X86::BI__builtin_ia32_roundpd: + case X86::BI__builtin_ia32_roundps256: + case X86::BI__builtin_ia32_roundpd256: { +unsigned m = +ops[1].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundps: +intrinsicName = "x86.sse41.round.ps"; +break; + case X86::BI__builtin_ia32_roundpd: +intrinsicName = "x86.sse41.round.pd"; +break; + case X86::BI__builtin_ia32_roundps256: +intrinsicName = "x86.avx.round.ps.256"; +break; + case X86::BI__builtin_ia32_roundpd256: +intrinsicName = "x86.avx.round.pd.256"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +return emitX86RoundImmediate(builder, loc, ops[0], m); + } + case X86::BI__builtin_ia32_roundss: + case X86::BI__builtin_ia32_roundsd: { +unsigned m = +ops[2].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundss: +intrinsicName = "x86.sse41.round.ss"; +break; + case X86::BI__builtin_ia32_roundsd: +intrinsicName = "x86.sse41.round.sd"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0); +mlir::Value roundedAt0 = emitX86RoundImmediate(builder, loc, valAt0, m); + +return builder.createInsertElement(loc, ops[0], roundedAt0, 0); + } case X86::BI__builtin_ia32_lzcnt_u16: case X86::BI__builtin_ia32_lzcnt_u32: case X86::BI__builtin_ia32_lzcnt_u64: { diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c index 174fcbc7b0080..773702af5ea25 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c @@ -30,6 +30,54 @@ #include +__m256d test_mm256_ceil_pd(__m256d x) { + // CIR-LABEL:
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
llvmorg-github-actions[bot] wrote:
@llvm/pr-subscribers-clangir
Author: Borys Perski (borysperski)
Changes
Issue #167765
---
Patch is 21.21 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/215787.diff
3 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp (+91)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c (+120)
- (modified) clang/test/CIR/CodeGenBuiltins/X86/sse41-builtins.c (+253)
``diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 9228367fdd44f..e1ce2e99e67b6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -86,6 +86,26 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder,
mlir::Location loc,
return maskVec;
}
+static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder,
+ mlir::Location loc, mlir::Value x,
+ unsigned roundingControl) {
+ constexpr unsigned roundingMask = 0b11;
+ unsigned roundingMode = roundingControl & roundingMask;
+
+ switch (roundingMode) {
+ default:
+llvm_unreachable("Invalid rounding mode");
+ case 0b00:
+return cir::RoundEvenOp::create(builder, loc, x);
+ case 0b01:
+return cir::FloorOp::create(builder, loc, x);
+ case 0b10:
+return cir::CeilOp::create(builder, loc, x);
+ case 0b11:
+return cir::TruncOp::create(builder, loc, x);
+ }
+}
+
static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder,
mlir::Location loc,
ArrayRef ops) {
@@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
const CallExpr *expr) {
// Return timestamp (element 0 of the returned struct)
return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0);
}
+ case X86::BI__builtin_ia32_roundps:
+ case X86::BI__builtin_ia32_roundpd:
+ case X86::BI__builtin_ia32_roundps256:
+ case X86::BI__builtin_ia32_roundpd256: {
+unsigned m =
+ops[1].getDefiningOp().getIntValue().getZExtValue();
+constexpr unsigned mxcsrMask = 0b100;
+constexpr unsigned fRoundNoExcMask = 0b1000;
+unsigned useMXCSR = mxcsrMask & m;
+unsigned fRoundNoExc = fRoundNoExcMask & m;
+
+mlir::Location loc = getLoc(expr->getExprLoc());
+
+if (useMXCSR || !fRoundNoExc) {
+ StringRef intrinsicName;
+ switch (builtinID) {
+ default:
+llvm_unreachable("Unexpected builtin");
+ case X86::BI__builtin_ia32_roundps:
+intrinsicName = "x86.sse41.round.ps";
+break;
+ case X86::BI__builtin_ia32_roundpd:
+intrinsicName = "x86.sse41.round.pd";
+break;
+ case X86::BI__builtin_ia32_roundps256:
+intrinsicName = "x86.avx.round.ps.256";
+break;
+ case X86::BI__builtin_ia32_roundpd256:
+intrinsicName = "x86.avx.round.pd.256";
+break;
+ }
+
+ mlir::Type resTy = ops[0].getType();
+ return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops);
+}
+
+return emitX86RoundImmediate(builder, loc, ops[0], m);
+ }
+ case X86::BI__builtin_ia32_roundss:
+ case X86::BI__builtin_ia32_roundsd: {
+unsigned m =
+ops[2].getDefiningOp().getIntValue().getZExtValue();
+constexpr unsigned mxcsrMask = 0b100;
+constexpr unsigned fRoundNoExcMask = 0b1000;
+unsigned useMXCSR = mxcsrMask & m;
+unsigned fRoundNoExc = fRoundNoExcMask & m;
+
+mlir::Location loc = getLoc(expr->getExprLoc());
+
+if (useMXCSR || !fRoundNoExc) {
+ StringRef intrinsicName;
+ switch (builtinID) {
+ default:
+llvm_unreachable("Unexpected builtin");
+ case X86::BI__builtin_ia32_roundss:
+intrinsicName = "x86.sse41.round.ss";
+break;
+ case X86::BI__builtin_ia32_roundsd:
+intrinsicName = "x86.sse41.round.sd";
+break;
+ }
+
+ mlir::Type resTy = ops[0].getType();
+ return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops);
+}
+
+mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0);
+mlir::Value roundedAt0 = emitX86RoundImmediate(builder, loc, valAt0, m);
+
+return builder.createInsertElement(loc, ops[0], roundedAt0, 0);
+ }
case X86::BI__builtin_ia32_lzcnt_u16:
case X86::BI__builtin_ia32_lzcnt_u32:
case X86::BI__builtin_ia32_lzcnt_u64: {
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
index 174fcbc7b0080..773702af5ea25 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
@@ -30,6 +30,54 @@
#include
+__m256d test_mm256_ceil_pd(__m256d x) {
+ // CIR-LABEL: test_mm256_ceil_pd
+ // CIR: cir.call_llvm_intrinsic "x86.avx.round.pd.256" %{{.*}}, %{{.*}} :
(!cir.vector<4 x
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
https://github.com/borysperski updated https://github.com/llvm/llvm-project/pull/215787 >From df49b7b85f79003a47f126a3cd30ca67b723b73f Mon Sep 17 00:00:00 2001 From: Borys Perski <[email protected]> Date: Wed, 12 Aug 2026 14:12:55 +0200 Subject: [PATCH] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins --- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp| 91 +++ .../CIR/CodeGenBuiltins/X86/avx-builtins.c| 120 + .../CIR/CodeGenBuiltins/X86/sse41-builtins.c | 253 ++ 3 files changed, 464 insertions(+) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 9228367fdd44f..e1ce2e99e67b6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -86,6 +86,26 @@ static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, return maskVec; } +static mlir::Value emitX86RoundImmediate(CIRGenBuilderTy &builder, + mlir::Location loc, mlir::Value x, + unsigned roundingControl) { + constexpr unsigned roundingMask = 0b11; + unsigned roundingMode = roundingControl & roundingMask; + + switch (roundingMode) { + default: +llvm_unreachable("Invalid rounding mode"); + case 0b00: +return cir::RoundEvenOp::create(builder, loc, x); + case 0b01: +return cir::FloorOp::create(builder, loc, x); + case 0b10: +return cir::CeilOp::create(builder, loc, x); + case 0b11: +return cir::TruncOp::create(builder, loc, x); + } +} + static mlir::Value emitX86CompressStore(CIRGenBuilderTy &builder, mlir::Location loc, ArrayRef ops) { @@ -1145,6 +1165,77 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { // Return timestamp (element 0 of the returned struct) return cir::ExtractMemberOp::create(builder, loc, i64Ty, result, 0); } + case X86::BI__builtin_ia32_roundps: + case X86::BI__builtin_ia32_roundpd: + case X86::BI__builtin_ia32_roundps256: + case X86::BI__builtin_ia32_roundpd256: { +unsigned m = +ops[1].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundps: +intrinsicName = "x86.sse41.round.ps"; +break; + case X86::BI__builtin_ia32_roundpd: +intrinsicName = "x86.sse41.round.pd"; +break; + case X86::BI__builtin_ia32_roundps256: +intrinsicName = "x86.avx.round.ps.256"; +break; + case X86::BI__builtin_ia32_roundpd256: +intrinsicName = "x86.avx.round.pd.256"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +return emitX86RoundImmediate(builder, loc, ops[0], m); + } + case X86::BI__builtin_ia32_roundss: + case X86::BI__builtin_ia32_roundsd: { +unsigned m = +ops[2].getDefiningOp().getIntValue().getZExtValue(); +constexpr unsigned mxcsrMask = 0b100; +constexpr unsigned fRoundNoExcMask = 0b1000; +unsigned useMXCSR = mxcsrMask & m; +unsigned fRoundNoExc = fRoundNoExcMask & m; + +mlir::Location loc = getLoc(expr->getExprLoc()); + +if (useMXCSR || !fRoundNoExc) { + StringRef intrinsicName; + switch (builtinID) { + default: +llvm_unreachable("Unexpected builtin"); + case X86::BI__builtin_ia32_roundss: +intrinsicName = "x86.sse41.round.ss"; +break; + case X86::BI__builtin_ia32_roundsd: +intrinsicName = "x86.sse41.round.sd"; +break; + } + + mlir::Type resTy = ops[0].getType(); + return builder.emitIntrinsicCallOp(loc, intrinsicName, resTy, ops); +} + +mlir::Value valAt0 = builder.createExtractElement(loc, ops[1], 0); +mlir::Value roundedAt0 = emitX86RoundImmediate(builder, loc, valAt0, m); + +return builder.createInsertElement(loc, ops[0], roundedAt0, 0); + } case X86::BI__builtin_ia32_lzcnt_u16: case X86::BI__builtin_ia32_lzcnt_u32: case X86::BI__builtin_ia32_lzcnt_u64: { diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c index 174fcbc7b0080..773702af5ea25 100644 --- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c +++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c @@ -30,6 +30,54 @@ #include +__m256d test_mm256_ceil_pd(__m256d x) { + // CIR-LABEL: test_mm256_ceil_pd
[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)
github-actions[bot] wrote: Hello @borysperski :wave: Thank you for submitting a Pull Request (PR) to the LLVM Project. Since this is your first PR, here are a few useful links covering our main contribution policies and review practices. * All contributions to LLVM must follow our [LLVM AI Tool Use Policy](https://llvm.org/docs/AIToolPolicy.html). In particular, if you used AI while working on this PR, remember to add a note to the PR description. * The [LLVM Code-Review Policy and Practices](https://llvm.org/docs/CodeReview.html) document contains practical information about the PR process, including how patches are reviewed and accepted, and who can review a PR. * Our [LLVM Developer Policy](https://llvm.org/docs/DeveloperPolicy.html) describes our expectations for code quality, commit summaries and contains notes on our CI system. Please reply to this message to confirm that you have read these policies, especially the LLVM AI Tool Use Policy, and that any AI tool usage has been noted in the PR description. --- ### Frequently asked questions **How do I add reviewers?** This PR will be automatically labeled, and the relevant teams will be notified. For some parts of the project, reviewers may also be added automatically. You can also add reviewers manually using the **Reviewers** section on this page. If you cannot use that section, it is probably because you do not have write permissions for the repository. In that case, you can request a review by tagging reviewers in a comment using `@` followed by their GitHub username. **What if there are no comments?** If you have not received any comments on your PR after a week, you can request a review by pinging the PR with a comment such as “Ping”. The common courtesy ping rate is once a week. Please remember that you are asking for volunteer time from other developers. **Are any special GitHub settings required to contribute to LLVM?** We only require contributors to have a public email address associated with their GitHub commits, see this [section](https://llvm.org/docs/DeveloperPolicy.html#email-addresses) of LLVM Developer Policy for details. --- If you have questions, feel free to leave a comment on this PR, or ask on [LLVM Discord](https://discord.com/invite/xS7Z362) or [LLVM Discourse](https://discourse.llvm.org/). Thank you, The LLVM Community https://github.com/llvm/llvm-project/pull/215787 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
