https://github.com/YeonguChoe updated https://github.com/llvm/llvm-project/pull/186294
>From 3abbe008bd366681146acd530cfd470bf9339c3d Mon Sep 17 00:00:00 2001 From: YeonguChoe <[email protected]> Date: Thu, 12 Mar 2026 22:10:56 -0400 Subject: [PATCH 1/2] [CIR] Implement cir.cmp3way Operation A three-way comparison operation is an operation that determines ordering of two numbers in a single operation. Implemented it as specified in the CIR documentation. --- .../CIR/Dialect/Builder/CIRBaseBuilder.h | 7 ++ clang/include/clang/CIR/Dialect/IR/CIROps.td | 34 ++++++++ clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 46 ++++++++++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 82 +++++++++++++++++++ .../CIR/CodeGenCXX/three-way-comparison.cpp | 22 +++++ clang/test/CIR/Lowering/cmp3way.cir | 32 ++++++++ 6 files changed, 219 insertions(+), 4 deletions(-) create mode 100644 clang/test/CIR/CodeGenCXX/three-way-comparison.cpp create mode 100644 clang/test/CIR/Lowering/cmp3way.cir diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index e60288c40132f..2a81da408121c 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -669,6 +669,13 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return cir::CmpOp::create(*this, loc, kind, lhs, rhs); } + cir::CmpThreeWayOp createThreeWayComparison(mlir::Location loc, + mlir::Type resultTy, + mlir::Value lhs, mlir::Value rhs, + mlir::Attribute info) { + return cir::CmpThreeWayOp::create(*this, loc, resultTy, lhs, rhs, info); + } + cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs) { VectorType vecCast = mlir::cast<VectorType>(lhs.getType()); diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index a9b98b1f43b3f..24758a0c946f6 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2071,6 +2071,40 @@ def CIR_CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> { let hasCXXABILowering = true; } +//===----------------------------------------------------------------------===// +// CmpThreeWayOp +//===----------------------------------------------------------------------===// + +def CIR_CmpThreeWayStrongInfoAttr + : CIR_Attr<"CmpThreeWayStrongInfo", "cmp3way_strong_info"> { + let parameters = (ins "int64_t":$lt, "int64_t":$eq, "int64_t":$gt); + let assemblyFormat = + [{`<` `strong` `,` `lt` `=` $lt `,` `eq` `=` $eq `,` `gt` `=` $gt `>`}]; +} +def CIR_CmpThreeWayPartialInfoAttr + : CIR_Attr<"CmpThreeWayPartialInfo", "cmp3way_partial_info"> { + let parameters = (ins "int64_t":$lt, "int64_t":$eq, "int64_t":$gt, + "int64_t":$unordered); + let assemblyFormat = + [{`<` `partial` `,` `lt` `=` $lt `,` `eq` `=` $eq `,` `gt` `=` $gt `,` `unordered` `=` $unordered `>` }]; +} +def CIR_CmpThreeWayInfoAttr : AnyAttrOf<[CIR_CmpThreeWayStrongInfoAttr, + CIR_CmpThreeWayPartialInfoAttr]>; + +def CIR_CmpThreeWayOp + : CIR_Op<"cmp3way", [Pure, SameTypeOperands, ConditionallySpeculatable]> { + let summary = "Performs three-way comparison."; + let description = [{ + Three-way comparison takes two operands of the same type and determines ordering. + }]; + let arguments = (ins CIR_AnyType:$lhs, CIR_AnyType:$rhs, + CIR_CmpThreeWayInfoAttr:$info); + let results = (outs CIR_AnySIntType:$result); + let assemblyFormat = [{ + `(` $lhs `:` type($lhs) `,` $rhs `,` qualified($info) `)` `:` type($result) attr-dict + }]; +} + //===----------------------------------------------------------------------===// // BinOpOverflowOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 9f390fec97613..19e844664f53c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -301,9 +301,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitSubstNonTypeTemplateParmExpr"); } - void VisitConstantExpr(ConstantExpr *e) { - cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitConstantExpr"); - } + void VisitConstantExpr(ConstantExpr *e) { return Visit(e->getSubExpr()); } void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); } void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); } void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); } @@ -326,7 +324,47 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { Visit(e->getRHS()); } void VisitBinCmp(const BinaryOperator *e) { - cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitBinCmp"); + const ComparisonCategoryInfo &CompCategoryInfo = + cgf.getContext().CompCategories.getInfoForType(e->getType()); + + QualType ArgTy = e->getLHS()->getType(); + if (ArgTy->isIntegralOrEnumerationType() || ArgTy->isRealFloatingType() || + ArgTy->isNullPtrType() || ArgTy->isPointerType() || + ArgTy->isMemberPointerType()) { + mlir::Value lhs = cgf.emitScalarExpr(e->getLHS()); + mlir::Value rhs = cgf.emitScalarExpr(e->getRHS()); + + mlir::Attribute info; + if (CompCategoryInfo.isStrong()) { + info = cir::CmpThreeWayStrongInfoAttr::get( + cgf.getBuilder().getContext(), + CompCategoryInfo.getLess()->getIntValue().getSExtValue(), + CompCategoryInfo.getEqualOrEquiv()->getIntValue().getSExtValue(), + CompCategoryInfo.getGreater()->getIntValue().getSExtValue()); + } else { + info = cir::CmpThreeWayPartialInfoAttr::get( + cgf.getBuilder().getContext(), + CompCategoryInfo.getLess()->getIntValue().getSExtValue(), + CompCategoryInfo.getEqualOrEquiv()->getIntValue().getSExtValue(), + CompCategoryInfo.getGreater()->getIntValue().getSExtValue(), + CompCategoryInfo.getUnordered()->getIntValue().getSExtValue()); + } + mlir::Type resultTy = cgf.convertType(cgf.getContext().IntTy); + mlir::Value result = cgf.getBuilder().createThreeWayComparison( + cgf.getLoc(e->getSourceRange()), resultTy, lhs, rhs, info); + + ensureDest(cgf.getLoc(e->getSourceRange()), e->getType()); + LValue destLValue = cgf.makeAddrLValue(dest.getAddress(), e->getType()); + + const FieldDecl *field = *CompCategoryInfo.Record->field_begin(); + LValue fieldLValue = cgf.emitLValueForFieldInitialization( + destLValue, field, field->getName()); + cgf.emitStoreThroughLValue(RValue::get(result), fieldLValue, true); + } else { + cgf.cgm.errorNYI(e->getSourceRange(), + "AggExprEmitter: unsupported operand type"); + return; + } } void VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) { cgf.cgm.errorNYI(e->getSourceRange(), diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 9c68248d5dede..53086ecb4b669 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3155,6 +3155,88 @@ mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite( return cmpOp.emitError() << "unsupported type for CmpOp: " << type; } +mlir::LogicalResult CIRToLLVMCmpThreeWayOpLowering::matchAndRewrite( + cir::CmpThreeWayOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Location loc = op.getLoc(); + auto info = op.getInfo(); + mlir::Type resultTy = getTypeConverter()->convertType(op.getType()); + mlir::Value lhs = adaptor.getLhs(); + mlir::Value rhs = adaptor.getRhs(); + mlir::Type operandTy = lhs.getType(); + + mlir::Value ltValue, eqValue, gtValue, unorderedValue; + if (auto strongInfo = mlir::dyn_cast<cir::CmpThreeWayStrongInfoAttr>(info)) { + ltValue = mlir::LLVM::ConstantOp::create( + rewriter, loc, resultTy, + rewriter.getI64IntegerAttr(strongInfo.getLt())); + eqValue = mlir::LLVM::ConstantOp::create( + rewriter, loc, resultTy, + rewriter.getI64IntegerAttr(strongInfo.getEq())); + gtValue = mlir::LLVM::ConstantOp::create( + rewriter, loc, resultTy, + rewriter.getI64IntegerAttr(strongInfo.getGt())); + } else if (auto partialInfo = + mlir::dyn_cast<cir::CmpThreeWayPartialInfoAttr>(info)) { + ltValue = mlir::LLVM::ConstantOp::create( + rewriter, loc, resultTy, + rewriter.getI64IntegerAttr(partialInfo.getLt())); + eqValue = mlir::LLVM::ConstantOp::create( + rewriter, loc, resultTy, + rewriter.getI64IntegerAttr(partialInfo.getEq())); + gtValue = mlir::LLVM::ConstantOp::create( + rewriter, loc, resultTy, + rewriter.getI64IntegerAttr(partialInfo.getGt())); + unorderedValue = mlir::LLVM::ConstantOp::create( + rewriter, loc, resultTy, + rewriter.getI64IntegerAttr(partialInfo.getUnordered())); + } else { + return op.emitError("unsupported comparison info attribute"); + } + + if (mlir::isa<mlir::IntegerType>(operandTy)) { + bool isSigned = true; + if (auto cirIntTy = mlir::dyn_cast<cir::IntType>(op.getLhs().getType())) { + isSigned = cirIntTy.isSigned(); + } + auto ltPred = isSigned ? mlir::LLVM::ICmpPredicate::slt + : mlir::LLVM::ICmpPredicate::ult; + + mlir::Value ltCmp = + mlir::LLVM::ICmpOp::create(rewriter, loc, ltPred, lhs, rhs); + mlir::Value eqCmp = mlir::LLVM::ICmpOp::create( + rewriter, loc, mlir::LLVM::ICmpPredicate::eq, lhs, rhs); + + mlir::Value result = mlir::LLVM::SelectOp::create( + rewriter, loc, ltCmp, ltValue, + mlir::LLVM::SelectOp::create(rewriter, loc, eqCmp, eqValue, gtValue)); + rewriter.replaceOp(op, result); + return mlir::success(); + } else if (mlir::isa<mlir::FloatType>(operandTy)) { + if (!unorderedValue) { + return op.emitError("strong ordering not supported for float operands"); + } + + mlir::Value ltCmp = mlir::LLVM::FCmpOp::create( + rewriter, loc, mlir::LLVM::FCmpPredicate::olt, lhs, rhs); + mlir::Value eqCmp = mlir::LLVM::FCmpOp::create( + rewriter, loc, mlir::LLVM::FCmpPredicate::oeq, lhs, rhs); + mlir::Value orderedResult = mlir::LLVM::SelectOp::create( + rewriter, loc, ltCmp, ltValue, + mlir::LLVM::SelectOp::create(rewriter, loc, eqCmp, eqValue, gtValue)); + + mlir::Value unorderedCmp = mlir::LLVM::FCmpOp::create( + rewriter, loc, mlir::LLVM::FCmpPredicate::uno, lhs, rhs); + + mlir::Value result = mlir::LLVM::SelectOp::create( + rewriter, loc, unorderedCmp, unorderedValue, orderedResult); + rewriter.replaceOp(op, result); + return mlir::success(); + } else { + return op.emitError("unsupported operand type for three-way comparison"); + } +} + mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite( cir::BinOpOverflowOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/test/CIR/CodeGenCXX/three-way-comparison.cpp b/clang/test/CIR/CodeGenCXX/three-way-comparison.cpp new file mode 100644 index 0000000000000..80c408597f0d2 --- /dev/null +++ b/clang/test/CIR/CodeGenCXX/three-way-comparison.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s + +#include "Inputs/std-compare.h" + +int test_int_spaceship(int a, int b) { + auto result = a <=> b; + // CHECK: cir.cmp3way(%{{.*}} : !s32i, %{{.*}}, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i + return (result < 0) ? -1 : (result > 0) ? 1 : 0; +} + +unsigned int test_uint_spaceship(unsigned int a, unsigned int b) { + auto result = a <=> b; + // CHECK: cir.cmp3way(%{{.*}} : !u32i, %{{.*}}, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i + return (result < 0) ? 0 : (result > 0) ? 2 : 1; +} + +float test_float_spaceship(float a, float b) { + auto result = a <=> b; + // CHECK: cir.cmp3way(%{{.*}} : !cir.float, %{{.*}}, #cir.cmp3way_partial_info<partial, lt = -1, eq = 0, gt = 1, unordered = -127>) + return (result < 0) ? -1.0f : (result > 0) ? 1.0f : 0.0f; +} \ No newline at end of file diff --git a/clang/test/CIR/Lowering/cmp3way.cir b/clang/test/CIR/Lowering/cmp3way.cir new file mode 100644 index 0000000000000..fe3740b6fd30d --- /dev/null +++ b/clang/test/CIR/Lowering/cmp3way.cir @@ -0,0 +1,32 @@ +// RUN: cir-opt %s -cir-to-llvm -o %t.mlir +// RUN: FileCheck --input-file=%t.mlir %s + +!s32i = !cir.int<s, 32> +!u32i = !cir.int<u, 32> +module { + cir.func @test_signed() -> !s32i { + %0 = cir.const #cir.int<5> : !s32i + %1 = cir.const #cir.int<3> : !s32i + %2 = cir.cmp3way(%0 : !s32i, %1, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i + // CHECK: llvm.icmp "slt" + cir.return %2 : !s32i + } + + cir.func @test_unsigned() -> !s32i { + %0 = cir.const #cir.int<5> : !u32i + %1 = cir.const #cir.int<3> : !u32i + %2 = cir.cmp3way(%0 : !u32i, %1, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i + // CHECK: llvm.icmp "ult" + cir.return %2 : !s32i + } + + cir.func @test_float() -> !s32i { + %0 = cir.const #cir.fp<1.5> : !cir.float + %1 = cir.const #cir.fp<2.5> : !cir.float + %2 = cir.cmp3way(%0 : !cir.float, %1, #cir.cmp3way_partial_info<partial, lt = -1, eq = 0, gt = 1, unordered = 2>) : !s32i + // CHECK: llvm.fcmp "olt" + // CHECK: llvm.fcmp "oeq" + // CHECK: llvm.fcmp "uno" + cir.return %2 : !s32i + } +} \ No newline at end of file >From d687aaa6847a81efabee2b1d38933065f22fb255 Mon Sep 17 00:00:00 2001 From: YeonguChoe <[email protected]> Date: Fri, 13 Mar 2026 13:19:11 -0400 Subject: [PATCH 2/2] [CIR] Implement cir.cmp3way Operation A three-way comparison operation is an operation that determines ordering of two numbers in a single operation. Implemented it as specified in the CIR documentation. --- .../CIR/CodeGenCXX/three-way-comparison.cpp | 44 ++++++++++-- clang/test/CIR/Lowering/cmp3way.cir | 72 ++++++++++++++++--- 2 files changed, 100 insertions(+), 16 deletions(-) diff --git a/clang/test/CIR/CodeGenCXX/three-way-comparison.cpp b/clang/test/CIR/CodeGenCXX/three-way-comparison.cpp index 80c408597f0d2..d8ae1cdb67182 100644 --- a/clang/test/CIR/CodeGenCXX/three-way-comparison.cpp +++ b/clang/test/CIR/CodeGenCXX/three-way-comparison.cpp @@ -1,22 +1,54 @@ // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -// RUN: FileCheck --input-file=%t.cir %s +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG -#include "Inputs/std-compare.h" +#include "../../CodeGenCXX/Inputs/std-compare.h" int test_int_spaceship(int a, int b) { auto result = a <=> b; - // CHECK: cir.cmp3way(%{{.*}} : !s32i, %{{.*}}, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i return (result < 0) ? -1 : (result > 0) ? 1 : 0; + // CIR: cir.cmp3way(%{{.*}} : !s32i, %{{.*}}, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i + // LLVM: %[[CMP_LT:.*]] = icmp slt i32 %{{.*}}, %{{.*}} + // LLVM: %[[CMP_EQ:.*]] = icmp eq i32 %{{.*}}, %{{.*}} + // LLVM: %[[SEL1:.*]] = select i1 %[[CMP_EQ]], i32 0, i32 1 + // LLVM: %[[SEL2:.*]] = select i1 %[[CMP_LT]], i32 -1, i32 %[[SEL1]] + // OGCG: %[[CMP_LT:.*]] = icmp slt i32 %{{.*}}, %{{.*}} + // OGCG: %[[SEL_LT:.*]] = select i1 %[[CMP_LT]], i8 -1, i8 1 + // OGCG: %[[CMP_EQ:.*]] = icmp eq i32 %{{.*}}, %{{.*}} + // OGCG: %[[SEL_EQ:.*]] = select i1 %[[CMP_EQ]], i8 0, i8 %[[SEL_LT]] } unsigned int test_uint_spaceship(unsigned int a, unsigned int b) { auto result = a <=> b; - // CHECK: cir.cmp3way(%{{.*}} : !u32i, %{{.*}}, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i return (result < 0) ? 0 : (result > 0) ? 2 : 1; + // CIR: cir.cmp3way(%{{.*}} : !u32i, %{{.*}}, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i + // LLVM: %[[CMP_LT:.*]] = icmp ult i32 %{{.*}}, %{{.*}} + // LLVM: %[[CMP_EQ:.*]] = icmp eq i32 %{{.*}}, %{{.*}} + // LLVM: %[[SEL1:.*]] = select i1 %[[CMP_EQ]], i32 0, i32 1 + // LLVM: %[[SEL2:.*]] = select i1 %[[CMP_LT]], i32 -1, i32 %[[SEL1]] + // OGCG: %[[CMP_LT:.*]] = icmp ult i32 %{{.*}}, %{{.*}} + // OGCG: %[[SEL_LT:.*]] = select i1 %[[CMP_LT]], i8 -1, i8 1 + // OGCG: %[[CMP_EQ:.*]] = icmp eq i32 %{{.*}}, %{{.*}} + // OGCG: %[[SEL_EQ:.*]] = select i1 %[[CMP_EQ]], i8 0, i8 %[[SEL_LT]] } float test_float_spaceship(float a, float b) { auto result = a <=> b; - // CHECK: cir.cmp3way(%{{.*}} : !cir.float, %{{.*}}, #cir.cmp3way_partial_info<partial, lt = -1, eq = 0, gt = 1, unordered = -127>) return (result < 0) ? -1.0f : (result > 0) ? 1.0f : 0.0f; -} \ No newline at end of file + // CIR: cir.cmp3way(%{{.*}} : !cir.float, %{{.*}}, #cir.cmp3way_partial_info<partial, lt = -1, eq = 0, gt = 1, unordered = -127>) + // LLVM: %[[CMP_LT:.*]] = fcmp olt float %{{.*}}, %{{.*}} + // LLVM: %[[CMP_EQ:.*]] = fcmp oeq float %{{.*}}, %{{.*}} + // LLVM: %[[SEL1:.*]] = select i1 %[[CMP_EQ]], i32 0, i32 1 + // LLVM: %[[SEL2:.*]] = select i1 %[[CMP_LT]], i32 -1, i32 %[[SEL1]] + // LLVM: %[[CMP_UNO:.*]] = fcmp uno float %{{.*}}, %{{.*}} + // LLVM: %[[SEL3:.*]] = select i1 %[[CMP_UNO]], i32 -127, i32 %[[SEL2]] + // OGCG: %[[CMP_EQ:.*]] = fcmp oeq float %{{.*}}, %{{.*}} + // OGCG: %[[SEL_EQ:.*]] = select i1 %[[CMP_EQ]], i8 0, i8 -127 + // OGCG: %[[CMP_GT:.*]] = fcmp ogt float %{{.*}}, %{{.*}} + // OGCG: %[[SEL_GT:.*]] = select i1 %[[CMP_GT]], i8 1, i8 %[[SEL_EQ]] + // OGCG: %[[CMP_LT:.*]] = fcmp olt float %{{.*}}, %{{.*}} + // OGCG: %[[SEL_LT:.*]] = select i1 %[[CMP_LT]], i8 -1, i8 %[[SEL_GT]] +} diff --git a/clang/test/CIR/Lowering/cmp3way.cir b/clang/test/CIR/Lowering/cmp3way.cir index fe3740b6fd30d..6e82a2ac07593 100644 --- a/clang/test/CIR/Lowering/cmp3way.cir +++ b/clang/test/CIR/Lowering/cmp3way.cir @@ -1,14 +1,24 @@ -// RUN: cir-opt %s -cir-to-llvm -o %t.mlir -// RUN: FileCheck --input-file=%t.mlir %s +// RUN: cir-opt %s -cir-to-llvm -o %t.cir +// RUN: FileCheck %s --input-file=%t.cir !s32i = !cir.int<s, 32> !u32i = !cir.int<u, 32> -module { +module attributes {cir.triple = "x86_64-unknown-linux-gnu"} { cir.func @test_signed() -> !s32i { %0 = cir.const #cir.int<5> : !s32i %1 = cir.const #cir.int<3> : !s32i %2 = cir.cmp3way(%0 : !s32i, %1, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i - // CHECK: llvm.icmp "slt" + // CHECK-LABEL: llvm.func @test_signed() -> i32 + // CHECK: %[[VAL0:.*]] = llvm.mlir.constant(5 : i32) : i32 + // CHECK: %[[VAL1:.*]] = llvm.mlir.constant(3 : i32) : i32 + // CHECK: %[[LT_RESULT:.*]] = llvm.mlir.constant(-1 : i64) : i32 + // CHECK: %[[EQ_RESULT:.*]] = llvm.mlir.constant(0 : i64) : i32 + // CHECK: %[[GT_RESULT:.*]] = llvm.mlir.constant(1 : i64) : i32 + // CHECK: %[[IS_LT:.*]] = llvm.icmp "slt" %[[VAL0]], %[[VAL1]] : i32 + // CHECK: %[[IS_EQ:.*]] = llvm.icmp "eq" %[[VAL0]], %[[VAL1]] : i32 + // CHECK: %[[EQ_OR_GT:.*]] = llvm.select %[[IS_EQ]], %[[EQ_RESULT]], %[[GT_RESULT]] : i1, i32 + // CHECK: %[[FINAL:.*]] = llvm.select %[[IS_LT]], %[[LT_RESULT]], %[[EQ_OR_GT]] : i1, i32 + // CHECK: llvm.return %[[FINAL]] : i32 cir.return %2 : !s32i } @@ -16,17 +26,59 @@ module { %0 = cir.const #cir.int<5> : !u32i %1 = cir.const #cir.int<3> : !u32i %2 = cir.cmp3way(%0 : !u32i, %1, #cir.cmp3way_strong_info<strong, lt = -1, eq = 0, gt = 1>) : !s32i - // CHECK: llvm.icmp "ult" + // CHECK-LABEL: llvm.func @test_unsigned() -> i32 + // CHECK: %[[VAL0:.*]] = llvm.mlir.constant(5 : i32) : i32 + // CHECK: %[[VAL1:.*]] = llvm.mlir.constant(3 : i32) : i32 + // CHECK: %[[LT_RESULT:.*]] = llvm.mlir.constant(-1 : i64) : i32 + // CHECK: %[[EQ_RESULT:.*]] = llvm.mlir.constant(0 : i64) : i32 + // CHECK: %[[GT_RESULT:.*]] = llvm.mlir.constant(1 : i64) : i32 + // CHECK: %[[IS_LT:.*]] = llvm.icmp "ult" %[[VAL0]], %[[VAL1]] : i32 + // CHECK: %[[IS_EQ:.*]] = llvm.icmp "eq" %[[VAL0]], %[[VAL1]] : i32 + // CHECK: %[[EQ_OR_GT:.*]] = llvm.select %[[IS_EQ]], %[[EQ_RESULT]], %[[GT_RESULT]] : i1, i32 + // CHECK: %[[FINAL:.*]] = llvm.select %[[IS_LT]], %[[LT_RESULT]], %[[EQ_OR_GT]] : i1, i32 + // CHECK: llvm.return %[[FINAL]] : i32 cir.return %2 : !s32i } - cir.func @test_float() -> !s32i { + cir.func @test_float_non_nan() -> !s32i { %0 = cir.const #cir.fp<1.5> : !cir.float %1 = cir.const #cir.fp<2.5> : !cir.float %2 = cir.cmp3way(%0 : !cir.float, %1, #cir.cmp3way_partial_info<partial, lt = -1, eq = 0, gt = 1, unordered = 2>) : !s32i - // CHECK: llvm.fcmp "olt" - // CHECK: llvm.fcmp "oeq" - // CHECK: llvm.fcmp "uno" + // CHECK-LABEL: llvm.func @test_float_non_nan() -> i32 + // CHECK: %[[VAL0:.*]] = llvm.mlir.constant(1.500000e+00 : f32) : f32 + // CHECK: %[[VAL1:.*]] = llvm.mlir.constant(2.500000e+00 : f32) : f32 + // CHECK: %[[LT_RESULT:.*]] = llvm.mlir.constant(-1 : i64) : i32 + // CHECK: %[[EQ_RESULT:.*]] = llvm.mlir.constant(0 : i64) : i32 + // CHECK: %[[GT_RESULT:.*]] = llvm.mlir.constant(1 : i64) : i32 + // CHECK: %[[UNO_RESULT:.*]] = llvm.mlir.constant(2 : i64) : i32 + // CHECK: %[[IS_LT:.*]] = llvm.fcmp "olt" %[[VAL0]], %[[VAL1]] : f32 + // CHECK: %[[IS_EQ:.*]] = llvm.fcmp "oeq" %[[VAL0]], %[[VAL1]] : f32 + // CHECK: %[[EQ_OR_GT:.*]] = llvm.select %[[IS_EQ]], %[[EQ_RESULT]], %[[GT_RESULT]] : i1, i32 + // CHECK: %[[LT_EQ_OR_GT:.*]] = llvm.select %[[IS_LT]], %[[LT_RESULT]], %[[EQ_OR_GT]] : i1, i32 + // CHECK: %[[IS_UNO:.*]] = llvm.fcmp "uno" %[[VAL0]], %[[VAL1]] : f32 + // CHECK: %[[FINAL:.*]] = llvm.select %[[IS_UNO]], %[[UNO_RESULT]], %[[LT_EQ_OR_GT]] : i1, i32 + // CHECK: llvm.return %[[FINAL]] : i32 cir.return %2 : !s32i } -} \ No newline at end of file + + cir.func @test_float_nan() -> !s32i { + %0 = cir.const #cir.fp<0x7FC00000> : !cir.float + %1 = cir.const #cir.fp<2.5> : !cir.float + %2 = cir.cmp3way(%0 : !cir.float, %1, #cir.cmp3way_partial_info<partial, lt = -1, eq = 0, gt = 1, unordered = 2>) : !s32i + // CHECK-LABEL: llvm.func @test_float_nan() -> i32 + // CHECK: %[[VAL0:.*]] = llvm.mlir.constant(0x7FC00000 : f32) : f32 + // CHECK: %[[VAL1:.*]] = llvm.mlir.constant(2.500000e+00 : f32) : f32 + // CHECK: %[[LT_RESULT:.*]] = llvm.mlir.constant(-1 : i64) : i32 + // CHECK: %[[EQ_RESULT:.*]] = llvm.mlir.constant(0 : i64) : i32 + // CHECK: %[[GT_RESULT:.*]] = llvm.mlir.constant(1 : i64) : i32 + // CHECK: %[[UNO_RESULT:.*]] = llvm.mlir.constant(2 : i64) : i32 + // CHECK: %[[IS_LT:.*]] = llvm.fcmp "olt" %[[VAL0]], %[[VAL1]] : f32 + // CHECK: %[[IS_EQ:.*]] = llvm.fcmp "oeq" %[[VAL0]], %[[VAL1]] : f32 + // CHECK: %[[EQ_OR_GT:.*]] = llvm.select %[[IS_EQ]], %[[EQ_RESULT]], %[[GT_RESULT]] : i1, i32 + // CHECK: %[[LT_EQ_OR_GT:.*]] = llvm.select %[[IS_LT]], %[[LT_RESULT]], %[[EQ_OR_GT]] : i1, i32 + // CHECK: %[[IS_UNO:.*]] = llvm.fcmp "uno" %[[VAL0]], %[[VAL1]] : f32 + // CHECK: %[[FINAL:.*]] = llvm.select %[[IS_UNO]], %[[UNO_RESULT]], %[[LT_EQ_OR_GT]] : i1, i32 + // CHECK: llvm.return %[[FINAL]] : i32 + cir.return %2 : !s32i + } +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
