https://github.com/Fznamznon updated 
https://github.com/llvm/llvm-project/pull/235843

>From f81af30cb0e61e9d7df7b11a78a71b70b78acc68 Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <[email protected]>
Date: Mon, 26 Oct 2026 12:06:09 -0500
Subject: [PATCH 1/2] [CIR] Introduce `cir.vec.fcmp` op and floating comparison
 kinds

Currently CIR uses the same operation and a set of comparison kinds for
both floating and integer comparisons which results in multiple
workarounds. For example: there are currently no unordered comparision
kinds and instead inversion is applied to ordered ones.
This PR only brings a new op and new comparison kinds that include unordered
kinds and true/false and uses it in one of the places (X86 builtins) where
it allows to remove a workaround. The intention is to do the whole
split between floating and integer comparisons at least for vector
variant of cir cmp op and this PR is the first step.

Assisted-by: claude
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h      |  35 +++++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  72 ++++++++++
 clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp    |  65 +++------
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       |  10 ++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 133 +++++++++++++++++-
 clang/test/CIR/CodeGen/builtins-x86.c         |  16 +--
 .../CodeGenBuiltins/builtin-fcmp-sse-strict.c |  70 +++++++++
 .../CIR/CodeGenBuiltins/builtin-fcmp-sse.c    |  40 +++---
 clang/test/CIR/IR/invalid-vec-fcmp.cir        |  13 ++
 9 files changed, 370 insertions(+), 84 deletions(-)
 create mode 100644 clang/test/CIR/CodeGenBuiltins/builtin-fcmp-sse-strict.c
 create mode 100644 clang/test/CIR/IR/invalid-vec-fcmp.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 9560eae0dc1153..a4a401baa4b075 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -999,6 +999,41 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return cir::VecCmpOp::create(*this, loc, resultTy, kind, lhs, rhs, fenv);
   }
 
+  /// Compares \p lhs and \p rhs element-wise.  Each result element is a
+  /// signed integer of the operand element's bit width.  That is not the
+  /// result an FP80 element needs, so an FP80 compare names its result type
+  /// with the overload below.
+  cir::VecFCmpOp createVecFCompare(mlir::Location loc, cir::FCmpOpKind kind,
+                                   mlir::Value lhs, mlir::Value rhs,
+                                   bool signaling = false) {
+    VectorType vecCast = mlir::cast<VectorType>(lhs.getType());
+    mlir::Type elemTy = vecCast.getElementType();
+    assert(!(mlir::isa<cir::FPTypeInterface>(elemTy) &&
+             &mlir::cast<cir::FPTypeInterface>(elemTy).getFloatSemantics() ==
+                 &llvm::APFloat::x87DoubleExtended()) &&
+           "an FP80 vector compare must name its result type");
+    IntType integralTy = getSIntNTy(getCIRIntOrFloatBitWidth(elemTy));
+    auto resTy = cir::VectorType::get(integralTy, vecCast.getSize());
+    return cir::VecFCmpOp::create(*this, loc, resTy, kind, lhs, rhs, signaling,
+                                  getConstrainedFPAttr());
+  }
+
+  /// Compares \p lhs and \p rhs element-wise, producing \p resultTy, which
+  /// must be a vector of integers or bools with as many elements as \p lhs.
+  /// The result element width can then differ from the operand element's
+  /// bit width, as for FP80, whose result elements are 128 bits.
+  cir::VecFCmpOp createVecFCompare(mlir::Location loc, VectorType resultTy,
+                                   cir::FCmpOpKind kind, mlir::Value lhs,
+                                   mlir::Value rhs, bool signaling = false) {
+    assert(mlir::cast<VectorType>(lhs.getType()).getSize() ==
+               resultTy.getSize() &&
+           cir::isIntOrBoolType(resultTy.getElementType()) &&
+           "vector compare result must be an int or bool vector of the "
+           "operand length");
+    return cir::VecFCmpOp::create(*this, loc, resultTy, kind, lhs, rhs,
+                                  signaling, getConstrainedFPAttr());
+  }
+
   mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
     return createCompare(loc, cir::CmpOpKind::ne, operand, operand);
   }
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index a56ed5141322eb..17d00fd856a90f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -6498,6 +6498,78 @@ def CIR_VecCmpOp : CIR_Op<"vec.cmp",
   let hasFolder = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// VecFCmpOp
+//===----------------------------------------------------------------------===//
+
+def CIR_FCmpOpKind : CIR_I32Enum<"FCmpOpKind", "floating compare operation 
kind", [
+  I32EnumCase<"_false", 0, "false">,
+  I32EnumCase<"oeq", 1>,
+  I32EnumCase<"ogt", 2>,
+  I32EnumCase<"oge", 3>,
+  I32EnumCase<"olt", 4>,
+  I32EnumCase<"ole", 5>,
+  I32EnumCase<"one", 6>,
+  I32EnumCase<"ord", 7>,
+  I32EnumCase<"ueq", 8>,
+  I32EnumCase<"ugt", 9>,
+  I32EnumCase<"uge", 10>,
+  I32EnumCase<"ult", 11>,
+  I32EnumCase<"ule", 12>,
+  I32EnumCase<"une", 13>,
+  I32EnumCase<"uno", 14>,
+  I32EnumCase<"_true", 15, "true">
+]>;
+
+def CIR_FCmpOpKindAttr : CIR_EnumAttr<CIR_FCmpOpKind, "fcmp">;
+
+def CIR_VecFCmpOp : CIR_Op<"vec.fcmp",
+    !listconcat([SameTypeOperands], CIR_FenvOpTraits)> {
+  let summary = "Compare two floating point vectors";
+  let description = [{
+    The `cir.vec.fcmp` operation does an element-wise comparison of two vectors
+    of the same floating type. The result is a vector of the same size as the 
operands
+    whose element type is signed integral type. The values in the result are 0 
or -1.
+
+    The optional `fenv` attribute describes constraints on the floating-point
+    handling of the operation.
+
+    `signaling` attribute overrides whether a floating-point
+    comparison raises an invalid exception for quiet NaN operands if fenv
+    attribute is present.
+
+    ```
+    %ogt = cir.vec.fcmp(ogt, %va, %vb) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i> signaling fenv<>
+    ```
+  }];
+
+  let arguments = (ins
+    CIR_FCmpOpKindAttr:$kind,
+    CIR_VectorType:$lhs,
+    CIR_VectorType:$rhs,
+    UnitAttr:$signaling,
+    OptionalAttr<CIR_FenvAttr>:$fenv
+  );
+
+  let results = (outs CIR_VectorType:$result);
+
+  let assemblyFormat = [{
+    `(` enum($kind) `,` $lhs `,` $rhs `)` `:` qualified(type($lhs)) `,`
+    qualified(type($result)) (`signaling` $signaling^)?
+    (`fenv` `` $fenv^)? attr-dict
+  }];
+
+  let builders = [
+    OpBuilder<(ins "mlir::Type":$result, "cir::FCmpOpKind":$kind,
+                   "mlir::Value":$lhs, "mlir::Value":$rhs), [{
+      build($_builder, $_state, result, kind, lhs, rhs, /*signaling=*/false,
+            cir::FenvAttr{});
+    }]>
+  ];
+
+  let hasVerifier = 1;
+}
+
 
//===----------------------------------------------------------------------===//
 // VecShuffleOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 35d1b67563df62..8734afd42ada7d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -32,39 +32,14 @@
 using namespace clang;
 using namespace clang::CIRGen;
 
-// OG has unordered comparison as a form of optimization in addition to
-// ordered comparison, while CIR doesn't.
-//
-// This means that we can't encode the comparison code of UGT (unordered
-// greater than), at least not at the CIR level.
-//
-// The boolean shouldInvert compensates for this.
-// For example: to get to the comparison code UGT, we pass in
-// emitVectorFCmp (OLE, shouldInvert = true) since OLE is the inverse of UGT.
-
-// There are several ways to support this otherwise:
-// - register extra CmpOpKind for unordered comparison types and build the
-// translation code for
-//    to go from CIR -> LLVM dialect. Notice we get this naturally with
-//    shouldInvert, benefiting from existing infrastructure, albeit having to
-//    generate an extra `not` at CIR).
-// - Just add extra comparison code to a new VecCmpOpKind instead of
-// cluttering CmpOpKind.
-// - Add a boolean in VecCmpOp to indicate if it's doing unordered or ordered
-// comparison
-// - Just emit the intrinsics call instead of calling this helper, see how the
-// LLVM lowering handles this.
 static mlir::Value emitVectorFCmp(CIRGenFunction &cgf, const CallExpr &expr,
                                   llvm::SmallVector<mlir::Value> &ops,
-                                  cir::CmpOpKind pred, bool shouldInvert) {
+                                  cir::FCmpOpKind pred, bool signaling) {
   CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, &expr);
   clang::CIRGen::CIRGenBuilderTy &builder = cgf.getBuilder();
-  mlir::Value cmp = builder.createVecCompare(cgf.getLoc(expr.getExprLoc()),
-                                             pred, ops[0], ops[1]);
-  // TODO(cir): Add dedicated predicates to avoid the need to invert this.
-  mlir::Value bitCast = builder.createBitcast(
-      shouldInvert ? builder.createNot(cmp) : cmp, ops[0].getType());
-  return bitCast;
+  mlir::Value cmp = builder.createVecFCompare(cgf.getLoc(expr.getExprLoc()),
+                                              pred, ops[0], ops[1], signaling);
+  return builder.createBitcast(cmp, ops[0].getType());
 }
 
 static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location 
loc,
@@ -2724,36 +2699,36 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
     return {};
   case X86::BI__builtin_ia32_cmpeqps:
   case X86::BI__builtin_ia32_cmpeqpd:
-    return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::eq,
-                          /*shouldInvert=*/false);
+    return emitVectorFCmp(*this, *expr, ops, cir::FCmpOpKind::oeq,
+                          /*signaling=*/false);
   case X86::BI__builtin_ia32_cmpltps:
   case X86::BI__builtin_ia32_cmpltpd:
-    return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::lt,
-                          /*shouldInvert=*/false);
+    return emitVectorFCmp(*this, *expr, ops, cir::FCmpOpKind::olt,
+                          /*signaling=*/true);
   case X86::BI__builtin_ia32_cmpleps:
   case X86::BI__builtin_ia32_cmplepd:
-    return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::le,
-                          /*shouldInvert=*/false);
+    return emitVectorFCmp(*this, *expr, ops, cir::FCmpOpKind::ole,
+                          /*signaling=*/true);
   case X86::BI__builtin_ia32_cmpunordps:
   case X86::BI__builtin_ia32_cmpunordpd:
-    return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::uno,
-                          /*shouldInvert=*/false);
+    return emitVectorFCmp(*this, *expr, ops, cir::FCmpOpKind::uno,
+                          /*signaling=*/false);
   case X86::BI__builtin_ia32_cmpneqps:
   case X86::BI__builtin_ia32_cmpneqpd:
-    return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::ne,
-                          /*shouldInvert=*/false);
+    return emitVectorFCmp(*this, *expr, ops, cir::FCmpOpKind::une,
+                          /*signaling=*/false);
   case X86::BI__builtin_ia32_cmpnltps:
   case X86::BI__builtin_ia32_cmpnltpd:
-    return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::lt,
-                          /*shouldInvert=*/true);
+    return emitVectorFCmp(*this, *expr, ops, cir::FCmpOpKind::uge,
+                          /*signaling=*/true);
   case X86::BI__builtin_ia32_cmpnleps:
   case X86::BI__builtin_ia32_cmpnlepd:
-    return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::le,
-                          /*shouldInvert=*/true);
+    return emitVectorFCmp(*this, *expr, ops, cir::FCmpOpKind::ugt,
+                          /*signaling=*/true);
   case X86::BI__builtin_ia32_cmpordps:
   case X86::BI__builtin_ia32_cmpordpd:
-    return emitVectorFCmp(*this, *expr, ops, cir::CmpOpKind::uno,
-                          /*shouldInvert=*/true);
+    return emitVectorFCmp(*this, *expr, ops, cir::FCmpOpKind::ord,
+                          /*signaling=*/false);
   case X86::BI__builtin_ia32_cmpph128_mask:
   case X86::BI__builtin_ia32_cmpph256_mask:
   case X86::BI__builtin_ia32_cmpph512_mask:
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 2d69135f440458..0c39c3b787bcad 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -4446,6 +4446,16 @@ OpFoldResult cir::VecCmpOp::fold(FoldAdaptor adaptor) {
       getType(), mlir::ArrayAttr::get(getContext(), elements));
 }
 
+//===----------------------------------------------------------------------===//
+// VecFCmpOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::VecFCmpOp::verify() {
+  if (!cir::isFPOrVectorOfFPType(getLhs().getType()))
+    return emitOpError() << "requires floating-point vector operands";
+  return success();
+}
+
 
//===----------------------------------------------------------------------===//
 // VecShuffleOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6b6b932346382c..b3ea1d3dbf7b85 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3928,6 +3928,49 @@ convertCmpKindToFCmpPredicate(cir::CmpOpKind kind) {
   llvm_unreachable("Unknown CmpOpKind");
 }
 
+/// Convert from a CIR fp comparison kind to an LLVM IR floating-point
+/// comparison kind.
+static mlir::LLVM::FCmpPredicate
+convertCmpKindToFCmpPredicate(cir::FCmpOpKind kind) {
+  using CIR = cir::FCmpOpKind;
+  using LLVMFCmp = mlir::LLVM::FCmpPredicate;
+  switch (kind) {
+  case CIR::_false:
+    return LLVMFCmp::_false;
+  case CIR::oeq:
+    return LLVMFCmp::oeq;
+  case CIR::ogt:
+    return LLVMFCmp::ogt;
+  case CIR::oge:
+    return LLVMFCmp::oge;
+  case CIR::olt:
+    return LLVMFCmp::olt;
+  case CIR::ole:
+    return LLVMFCmp::ole;
+  case CIR::one:
+    return LLVMFCmp::one;
+  case CIR::ord:
+    return LLVMFCmp::ord;
+  case CIR::ueq:
+    return LLVMFCmp::ueq;
+  case CIR::ugt:
+    return LLVMFCmp::ugt;
+  case CIR::uge:
+    return LLVMFCmp::uge;
+  case CIR::ult:
+    return LLVMFCmp::ult;
+  case CIR::ule:
+    return LLVMFCmp::ule;
+  case CIR::une:
+    return LLVMFCmp::une;
+  case CIR::uno:
+    return LLVMFCmp::uno;
+  case CIR::_true:
+    return LLVMFCmp::_true;
+  }
+  llvm_unreachable("Unknown FCmpOpKind");
+}
+
 static llvm::StringRef
 convertCmpKindToConstrainedFCmpPredicate(cir::CmpOpKind kind) {
   using CIR = cir::CmpOpKind;
@@ -3969,10 +4012,51 @@ static bool isSignalingConstrainedFCmp(cir::CmpOpKind 
kind) {
   llvm_unreachable("Unknown CmpOpKind");
 }
 
+static llvm::StringRef
+convertCmpKindToConstrainedFCmpPredicate(cir::FCmpOpKind kind) {
+  using CIR = cir::FCmpOpKind;
+  switch (kind) {
+  case CIR::_false:
+    return "false";
+  case CIR::oeq:
+    return "oeq";
+  case CIR::ogt:
+    return "ogt";
+  case CIR::oge:
+    return "oge";
+  case CIR::olt:
+    return "olt";
+  case CIR::ole:
+    return "ole";
+  case CIR::one:
+    return "one";
+  case CIR::ord:
+    return "ord";
+  case CIR::ueq:
+    return "ueq";
+  case CIR::ugt:
+    return "ugt";
+  case CIR::uge:
+    return "uge";
+  case CIR::ult:
+    return "ult";
+  case CIR::ule:
+    return "ule";
+  case CIR::une:
+    return "une";
+  case CIR::uno:
+    return "uno";
+  case CIR::_true:
+    return "true";
+  }
+  llvm_unreachable("Unknown FCmpOpKind");
+}
+
+template <typename OpKindTy>
 static mlir::LLVM::CallIntrinsicOp
 createConstrainedFCmpCall(mlir::ConversionPatternRewriter &rewriter,
                           mlir::Location loc, mlir::Value lhs, mlir::Value rhs,
-                          cir::CmpOpKind kind, cir::FenvAttr fenv,
+                          OpKindTy kind, bool isSignaling, cir::FenvAttr fenv,
                           mlir::Type llvmResTy) {
   llvm::SmallVector<mlir::Value, 4> callOperands = {
       lhs, rhs,
@@ -3980,7 +4064,7 @@ createConstrainedFCmpCall(mlir::ConversionPatternRewriter 
&rewriter,
                               convertCmpKindToConstrainedFCmpPredicate(kind)),
       createFenvMetadataValue(rewriter, loc,
                               getConstrainedExceptMetadata(fenv))};
-  llvm::StringRef intrinsicName = isSignalingConstrainedFCmp(kind)
+  llvm::StringRef intrinsicName = isSignaling
                                       ? "llvm.experimental.constrained.fcmps"
                                       : "llvm.experimental.constrained.fcmp";
   return createCallLLVMIntrinsicOp(rewriter, loc, intrinsicName, llvmResTy,
@@ -4019,7 +4103,8 @@ mlir::LogicalResult 
CIRToLLVMCmpOpLowering::matchAndRewrite(
     if (cir::FenvAttr fenv = cmpOp.getFenvAttr()) {
       mlir::LLVM::CallIntrinsicOp call = createConstrainedFCmpCall(
           rewriter, cmpOp.getLoc(), adaptor.getLhs(), adaptor.getRhs(),
-          cmpOp.getKind(), fenv, llvmResTy);
+          cmpOp.getKind(), isSignalingConstrainedFCmp(cmpOp.getKind()), fenv,
+          llvmResTy);
       rewriter.replaceOp(cmpOp, call.getResult(0));
       return mlir::success();
     }
@@ -5522,9 +5607,10 @@ mlir::LogicalResult 
CIRToLLVMVecCmpOpLowering::matchAndRewrite(
       llvm::ElementCount size = op.getLhs().getType().getSize();
       auto i1VecTy = mlir::VectorType::get(
           size.getKnownMinValue(), rewriter.getI1Type(), {size.isScalable()});
-      bitResult = createConstrainedFCmpCall(rewriter, op.getLoc(),
-                                            adaptor.getLhs(), adaptor.getRhs(),
-                                            op.getKind(), fenv, i1VecTy)
+      bitResult = createConstrainedFCmpCall(
+                      rewriter, op.getLoc(), adaptor.getLhs(), 
adaptor.getRhs(),
+                      op.getKind(), isSignalingConstrainedFCmp(op.getKind()),
+                      fenv, i1VecTy)
                       .getResult(0);
     } else {
       bitResult = mlir::LLVM::FCmpOp::create(
@@ -5548,6 +5634,41 @@ mlir::LogicalResult 
CIRToLLVMVecCmpOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMVecFCmpOpLowering::matchAndRewrite(
+    cir::VecFCmpOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Type elementType = op.getLhs().getType().getElementType();
+  if (!mlir::isa<cir::FPTypeInterface>(elementType))
+    return op.emitError() << "unsupported type for VecFCmpOp: " << elementType;
+
+  mlir::Value bitResult;
+  if (cir::FenvAttr fenv = op.getFenvAttr()) {
+    llvm::ElementCount size = op.getLhs().getType().getSize();
+    auto i1VecTy = mlir::VectorType::get(
+        size.getKnownMinValue(), rewriter.getI1Type(), {size.isScalable()});
+    bitResult = createConstrainedFCmpCall(
+                    rewriter, op.getLoc(), adaptor.getLhs(), adaptor.getRhs(),
+                    op.getKind(), op.getSignaling(), fenv, i1VecTy)
+                    .getResult(0);
+  } else {
+    bitResult = mlir::LLVM::FCmpOp::create(
+        rewriter, op.getLoc(), convertCmpKindToFCmpPredicate(op.getKind()),
+        adaptor.getLhs(), adaptor.getRhs());
+  }
+
+  // LLVM IR vector comparison returns a vector of i1. This one-bit vector
+  // must be sign-extended to the correct result type, unless a vector of i1 is
+  // the type we need.
+  mlir::Type vecElemTy = op.getType().getElementType();
+  if (isa<cir::IntType>(vecElemTy) &&
+      cast<cir::IntType>(vecElemTy).getWidth() > 1)
+    rewriter.replaceOpWithNewOp<mlir::LLVM::SExtOp>(
+        op, typeConverter->convertType(op.getType()), bitResult);
+  else
+    rewriter.replaceOp(op, bitResult);
+  return mlir::success();
+}
+
 mlir::LogicalResult CIRToLLVMVecSplatOpLowering::matchAndRewrite(
     cir::VecSplatOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGen/builtins-x86.c 
b/clang/test/CIR/CodeGen/builtins-x86.c
index 4f72a3000fc442..3f7505d23d1076 100644
--- a/clang/test/CIR/CodeGen/builtins-x86.c
+++ b/clang/test/CIR/CodeGen/builtins-x86.c
@@ -61,7 +61,7 @@ typedef __bf16   v8bf __attribute__((vector_size(16)));
 
 v4f test_cmpeqps(v4f a, v4f b) {
   // CIR-LABEL: @test_cmpeqps
-  // CIR: cir.vec.cmp(eq, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
+  // CIR: cir.vec.fcmp(oeq, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
   // CIR: cir.cast bitcast %{{.*}} : !cir.vector<4 x !s32i> -> !cir.vector<4 x 
!cir.float>
 
   // LLVM-LABEL: @test_cmpeqps
@@ -74,7 +74,7 @@ v4f test_cmpeqps(v4f a, v4f b) {
 
 v4f test_cmpltps(v4f a, v4f b) {
   // CIR-LABEL: @test_cmpltps
-  // CIR: cir.vec.cmp(lt, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
+  // CIR: cir.vec.fcmp(olt, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
   // CIR: cir.cast bitcast %{{.*}} : !cir.vector<4 x !s32i> -> !cir.vector<4 x 
!cir.float>
 
   // LLVM-LABEL: @test_cmpltps
@@ -87,7 +87,7 @@ v4f test_cmpltps(v4f a, v4f b) {
 
 v4f test_cmpleps(v4f a, v4f b) {
   // CIR-LABEL: @test_cmpleps
-  // CIR: cir.vec.cmp(le, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
+  // CIR: cir.vec.fcmp(ole, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
   // CIR: cir.cast bitcast %{{.*}} : !cir.vector<4 x !s32i> -> !cir.vector<4 x 
!cir.float>
 
   // LLVM-LABEL: @test_cmpleps
@@ -100,7 +100,7 @@ v4f test_cmpleps(v4f a, v4f b) {
 
 v4f test_cmpunordps(v4f a, v4f b) {
   // CIR-LABEL: @test_cmpunordps
-  // CIR: cir.vec.cmp(uno, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
+  // CIR: cir.vec.fcmp(uno, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
   // CIR: cir.cast bitcast %{{.*}} : !cir.vector<4 x !s32i> -> !cir.vector<4 x 
!cir.float>
 
   // LLVM-LABEL: @test_cmpunordps
@@ -113,12 +113,10 @@ v4f test_cmpunordps(v4f a, v4f b) {
 
 v4f test_cmpordps(v4f a, v4f b) {
   // CIR-LABEL: @test_cmpordps
-  // CIR: cir.vec.cmp(uno, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
-  // CIR: cir.not %{{.*}} : !cir.vector<4 x !s32i>
+  // CIR: cir.vec.fcmp(ord, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
 
   // LLVM-LABEL: @test_cmpordps
-  // LLVM: fcmp uno <4 x float>
-  // LLVM: xor <4 x i32> %{{.*}}, splat (i32 -1)
+  // LLVM: fcmp ord <4 x float>
 
   // OGCG-LABEL: @test_cmpordps
   // OGCG: fcmp ord <4 x float>
@@ -127,7 +125,7 @@ v4f test_cmpordps(v4f a, v4f b) {
 
 v4f test_cmpneqps(v4f a, v4f b) {
   // CIR-LABEL: @test_cmpneqps
-  // CIR: cir.vec.cmp(ne, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
+  // CIR: cir.vec.fcmp(une, %{{.*}}, %{{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i>
   // CIR: cir.cast bitcast %{{.*}} : !cir.vector<4 x !s32i> -> !cir.vector<4 x 
!cir.float>
 
   // LLVM-LABEL: @test_cmpneqps
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-fcmp-sse-strict.c 
b/clang/test/CIR/CodeGenBuiltins/builtin-fcmp-sse-strict.c
new file mode 100644
index 00000000000000..043a6b97bc3a02
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-fcmp-sse-strict.c
@@ -0,0 +1,70 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu 
-ffp-exception-behavior=strict -fclangir -emit-cir %s -o - | FileCheck %s 
--check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu 
-ffp-exception-behavior=strict -fclangir -emit-llvm %s -o - | FileCheck %s 
--check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu 
-ffp-exception-behavior=strict -emit-llvm %s -o - | FileCheck %s 
--check-prefix=LLVM
+
+typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));
+typedef double __m128d __attribute__((__vector_size__(16), __aligned__(16)));
+
+// CIR-LABEL: @test_cmpeqps
+// LLVM-LABEL: @test_cmpeqps
+__m128 test_cmpeqps(__m128 A, __m128 B) {
+  // CIR: cir.vec.fcmp(oeq, {{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i> fenv<{{.*}}strict_except = true>
+  // LLVM: call <4 x i1> @llvm.experimental.constrained.fcmp.v4f32(<4 x float> 
{{.*}}, <4 x float> {{.*}}, metadata !"oeq", metadata !"fpexcept.strict")
+  return __builtin_ia32_cmpeqps(A, B);
+}
+
+// CIR-LABEL: @test_cmpltps
+// LLVM-LABEL: @test_cmpltps
+__m128 test_cmpltps(__m128 A, __m128 B) {
+  // CIR: cir.vec.fcmp(olt, {{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i> signaling fenv<{{.*}}strict_except = true>
+  // LLVM: call <4 x i1> @llvm.experimental.constrained.fcmps.v4f32(<4 x 
float> {{.*}}, <4 x float> {{.*}}, metadata !"olt", metadata !"fpexcept.strict")
+  return __builtin_ia32_cmpltps(A, B);
+}
+
+// CIR-LABEL: @test_cmpleps
+// LLVM-LABEL: @test_cmpleps
+__m128 test_cmpleps(__m128 A, __m128 B) {
+  // CIR: cir.vec.fcmp(ole, {{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i> signaling fenv<{{.*}}strict_except = true>
+  // LLVM: call <4 x i1> @llvm.experimental.constrained.fcmps.v4f32(<4 x 
float> {{.*}}, <4 x float> {{.*}}, metadata !"ole", metadata !"fpexcept.strict")
+  return __builtin_ia32_cmpleps(A, B);
+}
+
+// CIR-LABEL: @test_cmpunordps
+// LLVM-LABEL: @test_cmpunordps
+__m128 test_cmpunordps(__m128 A, __m128 B) {
+  // CIR: cir.vec.fcmp(uno, {{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i> fenv<{{.*}}strict_except = true>
+  // LLVM: call <4 x i1> @llvm.experimental.constrained.fcmp.v4f32(<4 x float> 
{{.*}}, <4 x float> {{.*}}, metadata !"uno", metadata !"fpexcept.strict")
+  return __builtin_ia32_cmpunordps(A, B);
+}
+
+// CIR-LABEL: @test_cmpneqps
+// LLVM-LABEL: @test_cmpneqps
+__m128 test_cmpneqps(__m128 A, __m128 B) {
+  // CIR: cir.vec.fcmp(une, {{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i> fenv<{{.*}}strict_except = true>
+  // LLVM: call <4 x i1> @llvm.experimental.constrained.fcmp.v4f32(<4 x float> 
{{.*}}, <4 x float> {{.*}}, metadata !"une", metadata !"fpexcept.strict")
+  return __builtin_ia32_cmpneqps(A, B);
+}
+
+// CIR-LABEL: @test_cmpnltps
+// LLVM-LABEL: @test_cmpnltps
+__m128 test_cmpnltps(__m128 A, __m128 B) {
+  // CIR: cir.vec.fcmp(uge, {{.*}}) : !cir.vector<4 x !cir.float>, 
!cir.vector<4 x !s32i> signaling fenv<{{.*}}strict_except = true>
+  // LLVM: call <4 x i1> @llvm.experimental.constrained.fcmps.v4f32(<4 x 
float> {{.*}}, <4 x float> {{.*}}, metadata !"uge", metadata !"fpexcept.strict")
+  return __builtin_ia32_cmpnltps(A, B);
+}
+
+// CIR-LABEL: @test_cmpnlepd
+// LLVM-LABEL: @test_cmpnlepd
+__m128d test_cmpnlepd(__m128d A, __m128d B) {
+  // CIR: cir.vec.fcmp(ugt, {{.*}}) : !cir.vector<2 x !cir.double>, 
!cir.vector<2 x !s64i> signaling fenv<{{.*}}strict_except = true>
+  // LLVM: call <2 x i1> @llvm.experimental.constrained.fcmps.v2f64(<2 x 
double> {{.*}}, <2 x double> {{.*}}, metadata !"ugt", metadata 
!"fpexcept.strict")
+  return __builtin_ia32_cmpnlepd(A, B);
+}
+
+// CIR-LABEL: @test_cmpordpd
+// LLVM-LABEL: @test_cmpordpd
+__m128d test_cmpordpd(__m128d A, __m128d B) {
+  // CIR: cir.vec.fcmp(ord, {{.*}}) : !cir.vector<2 x !cir.double>, 
!cir.vector<2 x !s64i> fenv<{{.*}}strict_except = true>
+  // LLVM: call <2 x i1> @llvm.experimental.constrained.fcmp.v2f64(<2 x 
double> {{.*}}, <2 x double> {{.*}}, metadata !"ord", metadata 
!"fpexcept.strict")
+  return __builtin_ia32_cmpordpd(A, B);
+}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-fcmp-sse.c 
b/clang/test/CIR/CodeGenBuiltins/builtin-fcmp-sse.c
index 204c0d8d3d84c7..4dd08a3420c97c 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-fcmp-sse.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-fcmp-sse.c
@@ -18,9 +18,8 @@ __m128 test_cmpnleps(__m128 A, __m128 B) {
   // CIR:           cir.store %[[ARG1]], %[[ALLOCA_1]] : !cir.vector<4 x 
!cir.float>, !cir.ptr<!cir.vector<4 x !cir.float>>
   // CIR:           %[[LOAD_0:.*]] = cir.load align(16) %[[ALLOCA_0]] : 
!cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
   // CIR:           %[[LOAD_1:.*]] = cir.load align(16) %[[ALLOCA_1]] : 
!cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
-  // CIR:           %[[VEC_0:.*]] = cir.vec.cmp(le, %[[LOAD_0]], %[[LOAD_1]]) 
: !cir.vector<4 x !cir.float>, !cir.vector<4 x !s32i>
-  // CIR:           %[[UNARY_0:.*]] = cir.not %[[VEC_0]] : !cir.vector<4 x 
!s32i>
-  // CIR:           %[[CAST_0:.*]] = cir.cast bitcast %[[UNARY_0]] : 
!cir.vector<4 x !s32i> -> !cir.vector<4 x !cir.float>
+  // CIR:           %[[VEC_0:.*]] = cir.vec.fcmp(ugt, %[[LOAD_0]], 
%[[LOAD_1]]) : !cir.vector<4 x !cir.float>, !cir.vector<4 x !s32i>
+  // CIR:           %[[CAST_0:.*]] = cir.cast bitcast %[[VEC_0]] : 
!cir.vector<4 x !s32i> -> !cir.vector<4 x !cir.float>
   // CIR:           cir.store %[[CAST_0]], %[[ALLOCA_2]] : !cir.vector<4 x 
!cir.float>, !cir.ptr<!cir.vector<4 x !cir.float>>
   // CIR:           %[[LOAD_2:.*]] = cir.load %[[ALLOCA_2]] : 
!cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float>
   // CIR:           cir.return %[[LOAD_2]] : !cir.vector<4 x !cir.float>
@@ -35,10 +34,9 @@ __m128 test_cmpnleps(__m128 A, __m128 B) {
   // LLVM-NEXT:    store <4 x float> [[TMP1]], ptr [[TMP4]], align 16
   // LLVM-NEXT:    [[TMP6:%.*]] = load <4 x float>, ptr [[TMP3]], align 16
   // LLVM-NEXT:    [[TMP7:%.*]] = load <4 x float>, ptr [[TMP4]], align 16
-  // LLVM-NEXT:    [[TMP8:%.*]] = fcmp ole <4 x float> [[TMP6]], [[TMP7]]
+  // LLVM-NEXT:    [[TMP8:%.*]] = fcmp ugt <4 x float> [[TMP6]], [[TMP7]]
   // LLVM-NEXT:    [[TMP9:%.*]] = sext <4 x i1> [[TMP8]] to <4 x i32>
-  // LLVM-NEXT:    [[TMP10:%.*]] = xor <4 x i32> [[TMP9]], splat (i32 -1)
-  // LLVM-NEXT:    [[TMP11:%.*]] = bitcast <4 x i32> [[TMP10]] to <4 x float>
+  // LLVM-NEXT:    [[TMP11:%.*]] = bitcast <4 x i32> [[TMP9]] to <4 x float>
   // LLVM-NEXT:    store <4 x float> [[TMP11]], ptr [[TMP5]], align 16
   // LLVM-NEXT:    [[TMP12:%.*]] = load <4 x float>, ptr [[TMP5]], align 16
   // LLVM-NEXT:    ret <4 x float> [[TMP12]]
@@ -69,9 +67,8 @@ __m128d test_cmpnlepd(__m128d A, __m128d B) {
   // CIR:           cir.store %[[ARG1]], %[[ALLOCA_1]] : !cir.vector<2 x 
!cir.double>, !cir.ptr<!cir.vector<2 x !cir.double>> 
   // CIR:           %[[LOAD_0:.*]] = cir.load align(16) %[[ALLOCA_0]] : 
!cir.ptr<!cir.vector<2 x !cir.double>>, !cir.vector<2 x !cir.double> 
   // CIR:           %[[LOAD_1:.*]] = cir.load align(16) %[[ALLOCA_1]] : 
!cir.ptr<!cir.vector<2 x !cir.double>>, !cir.vector<2 x !cir.double> 
-  // CIR:           %[[VEC_0:.*]] = cir.vec.cmp(le, %[[LOAD_0]], %[[LOAD_1]]) 
: !cir.vector<2 x !cir.double>, !cir.vector<2 x !s64i> 
-  // CIR:           %[[UNARY_0:.*]] = cir.not %[[VEC_0]] : !cir.vector<2 x 
!s64i> 
-  // CIR:           %[[CAST_0:.*]] = cir.cast bitcast %[[UNARY_0]] : 
!cir.vector<2 x !s64i> -> !cir.vector<2 x !cir.double> 
+  // CIR:           %[[VEC_0:.*]] = cir.vec.fcmp(ugt, %[[LOAD_0]], 
%[[LOAD_1]]) : !cir.vector<2 x !cir.double>, !cir.vector<2 x !s64i>
+  // CIR:           %[[CAST_0:.*]] = cir.cast bitcast %[[VEC_0]] : 
!cir.vector<2 x !s64i> -> !cir.vector<2 x !cir.double>
   // CIR:           cir.store %[[CAST_0]], %[[ALLOCA_2]] : !cir.vector<2 x 
!cir.double>, !cir.ptr<!cir.vector<2 x !cir.double>> 
   // CIR:           %[[LOAD_2:.*]] = cir.load %[[ALLOCA_2]] : 
!cir.ptr<!cir.vector<2 x !cir.double>>, !cir.vector<2 x !cir.double> 
   // CIR:           cir.return %[[LOAD_2]] : !cir.vector<2 x !cir.double> 
@@ -86,10 +83,9 @@ __m128d test_cmpnlepd(__m128d A, __m128d B) {
   // LLVM-NEXT:    store <2 x double> [[TMP1]], ptr [[TMP4]], align 16
   // LLVM-NEXT:    [[TMP6:%.*]] = load <2 x double>, ptr [[TMP3]], align 16
   // LLVM-NEXT:    [[TMP7:%.*]] = load <2 x double>, ptr [[TMP4]], align 16
-  // LLVM-NEXT:    [[TMP8:%.*]] = fcmp ole <2 x double> [[TMP6]], [[TMP7]]
+  // LLVM-NEXT:    [[TMP8:%.*]] = fcmp ugt <2 x double> [[TMP6]], [[TMP7]]
   // LLVM-NEXT:    [[TMP9:%.*]] = sext <2 x i1> [[TMP8]] to <2 x i64>
-  // LLVM-NEXT:    [[TMP10:%.*]] = xor <2 x i64> [[TMP9]], splat (i64 -1)
-  // LLVM-NEXT:    [[TMP11:%.*]] = bitcast <2 x i64> [[TMP10]] to <2 x double>
+  // LLVM-NEXT:    [[TMP11:%.*]] = bitcast <2 x i64> [[TMP9]] to <2 x double>
   // LLVM-NEXT:    store <2 x double> [[TMP11]], ptr [[TMP5]], align 16
   // LLVM-NEXT:    [[TMP12:%.*]] = load <2 x double>, ptr [[TMP5]], align 16
   // LLVM-NEXT:    ret <2 x double> [[TMP12]]
@@ -120,9 +116,8 @@ __m128 test_cmpnltps(__m128 A, __m128 B) {
   // CIR:           cir.store %[[ARG1]], %[[ALLOCA_1]] : !cir.vector<4 x 
!cir.float>, !cir.ptr<!cir.vector<4 x !cir.float>> 
   // CIR:           %[[LOAD_0:.*]] = cir.load align(16) %[[ALLOCA_0]] : 
!cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float> 
   // CIR:           %[[LOAD_1:.*]] = cir.load align(16) %[[ALLOCA_1]] : 
!cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float> 
-  // CIR:           %[[VEC_0:.*]] = cir.vec.cmp(lt, %[[LOAD_0]], %[[LOAD_1]]) 
: !cir.vector<4 x !cir.float>, !cir.vector<4 x !s32i> 
-  // CIR:           %[[UNARY_0:.*]] = cir.not %[[VEC_0]] : !cir.vector<4 x 
!s32i> 
-  // CIR:           %[[CAST_0:.*]] = cir.cast bitcast %[[UNARY_0]] : 
!cir.vector<4 x !s32i> -> !cir.vector<4 x !cir.float> 
+  // CIR:           %[[VEC_0:.*]] = cir.vec.fcmp(uge, %[[LOAD_0]], 
%[[LOAD_1]]) : !cir.vector<4 x !cir.float>, !cir.vector<4 x !s32i>
+  // CIR:           %[[CAST_0:.*]] = cir.cast bitcast %[[VEC_0]] : 
!cir.vector<4 x !s32i> -> !cir.vector<4 x !cir.float>
   // CIR:           cir.store %[[CAST_0]], %[[ALLOCA_2]] : !cir.vector<4 x 
!cir.float>, !cir.ptr<!cir.vector<4 x !cir.float>> 
   // CIR:           %[[LOAD_2:.*]] = cir.load %[[ALLOCA_2]] : 
!cir.ptr<!cir.vector<4 x !cir.float>>, !cir.vector<4 x !cir.float> 
   // CIR:           cir.return %[[LOAD_2]] : !cir.vector<4 x !cir.float> 
@@ -137,10 +132,9 @@ __m128 test_cmpnltps(__m128 A, __m128 B) {
   // LLVM-NEXT:    store <4 x float> [[TMP1]], ptr [[TMP4]], align 16
   // LLVM-NEXT:    [[TMP6:%.*]] = load <4 x float>, ptr [[TMP3]], align 16
   // LLVM-NEXT:    [[TMP7:%.*]] = load <4 x float>, ptr [[TMP4]], align 16
-  // LLVM-NEXT:    [[TMP8:%.*]] = fcmp olt <4 x float> [[TMP6]], [[TMP7]]
+  // LLVM-NEXT:    [[TMP8:%.*]] = fcmp uge <4 x float> [[TMP6]], [[TMP7]]
   // LLVM-NEXT:    [[TMP9:%.*]] = sext <4 x i1> [[TMP8]] to <4 x i32>
-  // LLVM-NEXT:    [[TMP10:%.*]] = xor <4 x i32> [[TMP9]], splat (i32 -1)
-  // LLVM-NEXT:    [[TMP11:%.*]] = bitcast <4 x i32> [[TMP10]] to <4 x float>
+  // LLVM-NEXT:    [[TMP11:%.*]] = bitcast <4 x i32> [[TMP9]] to <4 x float>
   // LLVM-NEXT:    store <4 x float> [[TMP11]], ptr [[TMP5]], align 16
   // LLVM-NEXT:    [[TMP12:%.*]] = load <4 x float>, ptr [[TMP5]], align 16
   // LLVM-NEXT:    ret <4 x float> [[TMP12]]
@@ -171,9 +165,8 @@ __m128d test_cmpnltpd(__m128d A, __m128d B) {
   // CIR:           cir.store %[[ARG1]], %[[ALLOCA_1]] : !cir.vector<2 x 
!cir.double>, !cir.ptr<!cir.vector<2 x !cir.double>> 
   // CIR:           %[[LOAD_0:.*]] = cir.load align(16) %[[ALLOCA_0]] : 
!cir.ptr<!cir.vector<2 x !cir.double>>, !cir.vector<2 x !cir.double> 
   // CIR:           %[[LOAD_1:.*]] = cir.load align(16) %[[ALLOCA_1]] : 
!cir.ptr<!cir.vector<2 x !cir.double>>, !cir.vector<2 x !cir.double> 
-  // CIR:           %[[VEC_0:.*]] = cir.vec.cmp(lt, %[[LOAD_0]], %[[LOAD_1]]) 
: !cir.vector<2 x !cir.double>, !cir.vector<2 x !s64i> 
-  // CIR:           %[[UNARY_0:.*]] = cir.not %[[VEC_0]] : !cir.vector<2 x 
!s64i> 
-  // CIR:           %[[CAST_0:.*]] = cir.cast bitcast %[[UNARY_0]] : 
!cir.vector<2 x !s64i> -> !cir.vector<2 x !cir.double> 
+  // CIR:           %[[VEC_0:.*]] = cir.vec.fcmp(uge, %[[LOAD_0]], 
%[[LOAD_1]]) : !cir.vector<2 x !cir.double>, !cir.vector<2 x !s64i>
+  // CIR:           %[[CAST_0:.*]] = cir.cast bitcast %[[VEC_0]] : 
!cir.vector<2 x !s64i> -> !cir.vector<2 x !cir.double>
   // CIR:           cir.store %[[CAST_0]], %[[ALLOCA_2]] : !cir.vector<2 x 
!cir.double>, !cir.ptr<!cir.vector<2 x !cir.double>> 
   // CIR:           %[[LOAD_2:.*]] = cir.load %[[ALLOCA_2]] : 
!cir.ptr<!cir.vector<2 x !cir.double>>, !cir.vector<2 x !cir.double> 
   // CIR:           cir.return %[[LOAD_2]] : !cir.vector<2 x !cir.double> 
@@ -188,10 +181,9 @@ __m128d test_cmpnltpd(__m128d A, __m128d B) {
   // LLVM-NEXT:    store <2 x double> [[TMP1]], ptr [[TMP4]], align 16
   // LLVM-NEXT:    [[TMP6:%.*]] = load <2 x double>, ptr [[TMP3]], align 16
   // LLVM-NEXT:    [[TMP7:%.*]] = load <2 x double>, ptr [[TMP4]], align 16
-  // LLVM-NEXT:    [[TMP8:%.*]] = fcmp olt <2 x double> [[TMP6]], [[TMP7]]
+  // LLVM-NEXT:    [[TMP8:%.*]] = fcmp uge <2 x double> [[TMP6]], [[TMP7]]
   // LLVM-NEXT:    [[TMP9:%.*]] = sext <2 x i1> [[TMP8]] to <2 x i64>
-  // LLVM-NEXT:    [[TMP10:%.*]] = xor <2 x i64> [[TMP9]], splat (i64 -1)
-  // LLVM-NEXT:    [[TMP11:%.*]] = bitcast <2 x i64> [[TMP10]] to <2 x double>
+  // LLVM-NEXT:    [[TMP11:%.*]] = bitcast <2 x i64> [[TMP9]] to <2 x double>
   // LLVM-NEXT:    store <2 x double> [[TMP11]], ptr [[TMP5]], align 16
   // LLVM-NEXT:    [[TMP12:%.*]] = load <2 x double>, ptr [[TMP5]], align 16
   // LLVM-NEXT:    ret <2 x double> [[TMP12]]
diff --git a/clang/test/CIR/IR/invalid-vec-fcmp.cir 
b/clang/test/CIR/IR/invalid-vec-fcmp.cir
new file mode 100644
index 00000000000000..8b9d9a3373c721
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-vec-fcmp.cir
@@ -0,0 +1,13 @@
+// RUN: cir-opt %s -verify-diagnostics
+
+!s32i = !cir.int<s, 32>
+
+module {
+  cir.func @vec_fcmp_on_int(%a: !cir.vector<4 x !s32i>,
+                            %b: !cir.vector<4 x !s32i>) {
+    // expected-error@+1 {{requires floating-point vector operands}}
+    %0 = cir.vec.fcmp(oeq, %a, %b) : !cir.vector<4 x !s32i>,
+                                    !cir.vector<4 x !s32i>
+    cir.return
+  }
+}

>From 476c19cbf1324780ec881085a1d2a6ca8f9141d5 Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <[email protected]>
Date: Tue, 3 Nov 2026 09:54:26 -0600
Subject: [PATCH 2/2] Split the variables

---
 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 7bb69dcad73a9e..0b8e7b860f87ee 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -5648,10 +5648,10 @@ mlir::LogicalResult 
CIRToLLVMVecFCmpOpLowering::matchAndRewrite(
     llvm::ElementCount size = op.getLhs().getType().getSize();
     auto i1VecTy = mlir::VectorType::get(
         size.getKnownMinValue(), rewriter.getI1Type(), {size.isScalable()});
-    bitResult = createConstrainedFCmpCall(
-                    rewriter, op.getLoc(), adaptor.getLhs(), adaptor.getRhs(),
-                    op.getKind(), op.getSignaling(), fenv, i1VecTy)
-                    .getResult(0);
+    mlir::LLVM::CallIntrinsicOp CFCmpCall = createConstrainedFCmpCall(
+        rewriter, op.getLoc(), adaptor.getLhs(), adaptor.getRhs(), 
op.getKind(),
+        op.getSignaling(), fenv, i1VecTy);
+    bitResult = CFCmpCall.getResult(0);
   } else {
     bitResult = mlir::LLVM::FCmpOp::create(
         rewriter, op.getLoc(), convertCmpKindToFCmpPredicate(op.getKind()),

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to