From 858bd2925095cbe15d594cb42cd5e9d1e7f1f235 Mon Sep 17 00:00:00 2001 From: PikachuHy Date: Tue, 5 Nov 2024 10:55:34 +0800 Subject: [PATCH] [CIR][CIRGen] support builtin signbit --- .../CIR/Dialect/Builder/CIRBaseBuilder.h | 5 +++ clang/include/clang/CIR/Dialect/IR/CIROps.td | 13 ++++++++ clang/include/clang/CIR/MissingFeatures.h | 1 + clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 15 +++++++-- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 27 +++++++++++++++- clang/test/CIR/CodeGen/builtin-signbit.c | 32 +++++++++++++++++++ 6 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 clang/test/CIR/CodeGen/builtin-signbit.c diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 49f1256db284..2f33905109f5 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -417,6 +417,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return create(loc, dst, src, len); } + mlir::cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) { + auto resTy = mlir::cir::IntType::get(getContext(), 32, true); + return create(loc, resTy, val); + } + mlir::Value createSub(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false, bool hasNSW = false) { auto op = create(lhs.getLoc(), lhs.getType(), diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 63bf3b6b9438..57d622180388 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -5078,4 +5078,17 @@ def AtomicCmpXchg : CIR_Op<"atomic.cmp_xchg", let hasVerifier = 0; } +def SignBitOp : CIR_Op<"signbit", [Pure]> { + let summary = "Checks the sign of a floating-point number"; + let description = [{ + It returns a non-zero value (true) if the number is negative + and zero (false) if the number is positive or zero. + }]; + let arguments = (ins CIR_AnyFloat:$input); + let results = (outs SInt32:$res); + let assemblyFormat = [{ + $input attr-dict `:` type($input) `->` qualified(type($res)) + }]; +} + #endif // LLVM_CLANG_CIR_DIALECT_IR_CIROPS diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 9b1eb419f3e0..bd3a5c643918 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -228,6 +228,7 @@ struct MissingFeatures { static bool xray() { return false; } static bool buildConstrainedFPCall() { return false; } static bool emitEmptyRecordCheck() { return false; } + static bool isPPC_FP128Ty() { return false; } // Inline assembly static bool asmGoto() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 0cac50ecf9ef..d5a805f9a234 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -217,6 +217,13 @@ static mlir::Value buildFromInt(CIRGenFunction &CGF, mlir::Value v, QualType t, return v; } +static mlir::Value buildSignBit(mlir::Location loc, CIRGenFunction &CGF, + mlir::Value val) { + assert(!::cir::MissingFeatures::isPPC_FP128Ty()); + auto ret = CGF.getBuilder().createSignBit(loc, val); + return ret->getResult(0); +} + static Address checkAtomicAlignment(CIRGenFunction &CGF, const CallExpr *E) { ASTContext &ctx = CGF.getContext(); Address ptr = CGF.buildPointerWithAlignment(E->getArg(0)); @@ -1698,8 +1705,12 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_signbit: case Builtin::BI__builtin_signbitf: - case Builtin::BI__builtin_signbitl: - llvm_unreachable("BI__builtin_signbit like NYI"); + case Builtin::BI__builtin_signbitl: { + auto loc = getLoc(E->getBeginLoc()); + return RValue::get(builder.createZExtOrBitCast( + loc, buildSignBit(loc, *this, buildScalarExpr(E->getArg(0))), + ConvertType(E->getType()))); + } case Builtin::BI__warn_memset_zero_len: llvm_unreachable("BI__warn_memset_zero_len NYI"); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 0102629e7c39..58f1e9a28faf 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -4246,6 +4246,31 @@ class CIRAbsOpLowering : public mlir::OpConversionPattern { return mlir::success(); } }; +class CIRSignBitOpLowering + : public mlir::OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(mlir::cir::SignBitOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + assert(!::cir::MissingFeatures::isPPC_FP128Ty()); + + mlir::DataLayout layout(op->getParentOfType()); + int width = layout.getTypeSizeInBits(op.getInput().getType()); + auto intTy = mlir::IntegerType::get(rewriter.getContext(), width); + auto bitcast = rewriter.create(op->getLoc(), intTy, + adaptor.getInput()); + auto zero = rewriter.create(op->getLoc(), intTy, 0); + auto cmpResult = rewriter.create( + op.getLoc(), mlir::LLVM::ICmpPredicate::slt, bitcast.getResult(), zero); + auto converted = rewriter.create( + op.getLoc(), mlir::IntegerType::get(rewriter.getContext(), 32), + cmpResult); + rewriter.replaceOp(op, converted); + return mlir::success(); + } +}; void populateCIRToLLVMConversionPatterns( mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter, @@ -4285,7 +4310,7 @@ void populateCIRToLLVMConversionPatterns( CIRFreeExceptionOpLowering, CIRThrowOpLowering, CIRIntrinsicCallLowering, CIRBaseClassAddrOpLowering, CIRDerivedClassAddrOpLowering, CIRVTTAddrPointOpLowering, CIRIsFPClassOpLowering, CIRAbsOpLowering, - CIRMemMoveOpLowering, CIRMemsetOpLowering + CIRMemMoveOpLowering, CIRMemsetOpLowering, CIRSignBitOpLowering #define GET_BUILTIN_LOWERING_LIST #include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc" #undef GET_BUILTIN_LOWERING_LIST diff --git a/clang/test/CIR/CodeGen/builtin-signbit.c b/clang/test/CIR/CodeGen/builtin-signbit.c new file mode 100644 index 000000000000..dabb2221ba86 --- /dev/null +++ b/clang/test/CIR/CodeGen/builtin-signbit.c @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s -check-prefix=LLVM + +void test_signbit_float(float val) { + // CIR: test_signbit_float + // LLVM: test_signbit_float + __builtin_signbit(val); + // CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i + // LLVM: [[TMP1:%.*]] = bitcast float %{{.+}} to i32 + // LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0 + // LLVM: %{{.+}} = zext i1 [[TMP2]] to i32 +} + +void test_signbit_double(double val) { + // CIR: test_signbit_double + // LLVM: test_signbit_double + __builtin_signbitf(val); + // CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i + // LLVM: [[CONV:%.*]] = fptrunc double %{{.+}} to float + // LLVM: [[TMP1:%.*]] = bitcast float [[CONV]] to i32 + // LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0 + // LLVM: %{{.+}} = zext i1 [[TMP2]] to i32 +} +void test_signbit_long_double(long double val) { + // CIR: test_signbit_long_double + // LLVM: test_signbit_long_double + __builtin_signbitl(val); + // CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.long_double -> !s32i + // LLVM: [[TMP1:%.*]] = bitcast x86_fp80 %{{.+}} to i80 + // LLVM: [[TMP2:%.*]] = icmp slt i80 [[TMP1]], 0 + // LLVM: %{{.+}} = zext i1 [[TMP2]] to i32 +}