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
