[clang] [CIR][X86] Add support for roundpd, roundps, roundsd, roundss builtins (PR #215787)

2026-09-20 Thread Borys Perski via cfe-commits

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)

2026-09-19 Thread Borys Perski via cfe-commits


@@ -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)

2026-09-19 Thread Borys Perski via cfe-commits


@@ -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)

2026-09-19 Thread Borys Perski via cfe-commits

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)

2026-09-18 Thread Borys Perski via cfe-commits

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)

2026-08-18 Thread Borys Perski via cfe-commits


@@ -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)

2026-08-14 Thread Phoebe Wang via cfe-commits


@@ -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)

2026-08-12 Thread Borys Perski via cfe-commits

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)

2026-08-12 Thread via cfe-commits

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)

2026-08-12 Thread Borys Perski via cfe-commits

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)

2026-08-12 Thread via cfe-commits

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