Author: Ayokunle Amodu Date: 2026-03-03T14:01:49-08:00 New Revision: 1953b87a31a9b7de9e34deaa7e94ee59b3e7de39
URL: https://github.com/llvm/llvm-project/commit/1953b87a31a9b7de9e34deaa7e94ee59b3e7de39 DIFF: https://github.com/llvm/llvm-project/commit/1953b87a31a9b7de9e34deaa7e94ee59b3e7de39.diff LOG: [CIR][CodeGen] Upstream support for `__builtin_isinf_sign` (#183977) This adds CIR codegen and lowering support for `__builtin_isinf_sign`. Added: clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c Modified: clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h clang/include/clang/CIR/Dialect/IR/CIROps.td clang/include/clang/CIR/MissingFeatures.h clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp Removed: ################################################################################ diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 72de34ffad77b..f51bea894d2ae 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -547,6 +547,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return cir::VecInsertOp::create(*this, loc, vec, newElt, idxVal); } + cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) { + auto resTy = cir::BoolType::get(getContext()); + return cir::SignBitOp::create(*this, loc, resTy, val); + } + //===--------------------------------------------------------------------===// // Binary Operators //===--------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 3a17b0a381a76..7f73c606f1537 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -484,6 +484,23 @@ def CIR_ConstantOp : CIR_Op<"const", [ let isLLVMLoweringRecursive = true; } +//===----------------------------------------------------------------------===// +// SignBitOp +//===----------------------------------------------------------------------===// + +def SignBitOp : CIR_Op<"signbit", [Pure]> { + let summary = "Checks the sign of a floating-point number"; + let description = [{ + It returns whether the sign bit (i.e. the highest bit) of the input operand + is set. + }]; + let arguments = (ins CIR_AnyFloatType:$input); + let results = (outs CIR_BoolType:$res); + let assemblyFormat = [{ + $input attr-dict `:` type($input) `->` qualified(type($res)) + }]; +} + //===----------------------------------------------------------------------===// // C/C++ memory order definitions //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index ab05d2191d9b0..d206503d914f5 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -272,6 +272,7 @@ struct MissingFeatures { static bool emitNullabilityCheck() { return false; } static bool emitTypeCheck() { return false; } static bool emitTypeMetadataCodeForVCall() { return false; } + static bool isPPC_FP128Ty() { return false; } // Fast math. static bool fastMathGuard() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index b11d8f4783db0..3b7ad5c4929fe 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -86,6 +86,13 @@ static mlir::Value emitFromInt(CIRGenFunction &cgf, mlir::Value v, QualType t, return v; } +static mlir::Value emitSignBit(mlir::Location loc, CIRGenFunction &cgf, + mlir::Value val) { + assert(!::cir::MissingFeatures::isPPC_FP128Ty()); + cir::SignBitOp returnValue = cgf.getBuilder().createSignBit(loc, val); + return returnValue->getResult(0); +} + static Address checkAtomicAlignment(CIRGenFunction &cgf, const CallExpr *e) { ASTContext &astContext = cgf.getContext(); Address ptr = cgf.emitPointerWithAlignment(e->getArg(0)); @@ -1540,7 +1547,23 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, case Builtin::BI__builtin_masked_store: case Builtin::BI__builtin_masked_compress_store: case Builtin::BI__builtin_masked_scatter: - case Builtin::BI__builtin_isinf_sign: + return errorBuiltinNYI(*this, e, builtinID); + case Builtin::BI__builtin_isinf_sign: { + CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e); + mlir::Location loc = getLoc(e->getBeginLoc()); + mlir::Value arg = emitScalarExpr(e->getArg(0)); + mlir::Value isInf = + builder.createIsFPClass(loc, arg, cir::FPClassTest::Infinity); + mlir::Value isNeg = emitSignBit(loc, *this, arg); + mlir::Type intTy = convertType(e->getType()); + cir::ConstantOp zero = builder.getNullValue(intTy, loc); + cir::ConstantOp one = builder.getConstant(loc, cir::IntAttr::get(intTy, 1)); + cir::ConstantOp negativeOne = + builder.getConstant(loc, cir::IntAttr::get(intTy, -1)); + mlir::Value signResult = builder.createSelect(loc, isNeg, negativeOne, one); + mlir::Value result = builder.createSelect(loc, isInf, signResult, zero); + return RValue::get(result); + } case Builtin::BI__builtin_flt_rounds: case Builtin::BI__builtin_set_flt_rounds: case Builtin::BI__builtin_fpclassify: diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 37cc6c113ff89..accb60df3799e 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -838,6 +838,35 @@ mlir::LogicalResult CIRToLLVMIsFPClassOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMSignBitOpLowering::matchAndRewrite( + cir::SignBitOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + assert(!cir::MissingFeatures::isPPC_FP128Ty()); + + mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>()); + int width = layout.getTypeSizeInBits(op.getInput().getType()); + if (auto longDoubleType = + mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) { + if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) { + // If the underlying type of LongDouble is FP80Type, + // DataLayout::getTypeSizeInBits returns 128. + // See https://github.com/llvm/clangir/issues/1057. + // Set the width to 80 manually. + width = 80; + } + } + mlir::Type intTy = mlir::IntegerType::get(rewriter.getContext(), width); + auto bitcast = mlir::LLVM::BitcastOp::create(rewriter, op->getLoc(), intTy, + adaptor.getInput()); + + auto zero = mlir::LLVM::ConstantOp::create(rewriter, op->getLoc(), intTy, 0); + auto cmpResult = mlir::LLVM::ICmpOp::create(rewriter, op.getLoc(), + mlir::LLVM::ICmpPredicate::slt, + bitcast.getResult(), zero); + rewriter.replaceOp(op, cmpResult); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMAssumeOpLowering::matchAndRewrite( cir::AssumeOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c b/clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c new file mode 100644 index 0000000000000..27c6730ca996a --- /dev/null +++ b/clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.cir.ll +// RUN: FileCheck --input-file=%t.cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +int test_float_isinf_sign(float x) { + // CIR-LABEL: test_float_isinf_sign + // CIR: %[[ARG:.*]] = cir.load align(4) %{{.*}} : !cir.ptr<!cir.float>, !cir.float + // CIR: %[[IS_INF:.*]] = cir.is_fp_class %[[ARG]], fcInf : (!cir.float) -> !cir.bool + // CIR: %[[IS_NEG:.*]] = cir.signbit %[[ARG]] : !cir.float -> !cir.bool + // CIR: %[[C_0:.*]] = cir.const #cir.int<0> : !s32i + // CIR: %[[C_1:.*]] = cir.const #cir.int<1> : !s32i + // CIR: %[[C_m1:.*]] = cir.const #cir.int<-1> : !s32i + // CIR: %[[SIGN:.*]] = cir.select if %[[IS_NEG]] then %[[C_m1]] else %[[C_1]] : (!cir.bool, !s32i, !s32i) -> !s32i + // CIR: %[[RET:.*]] = cir.select if %[[IS_INF]] then %[[SIGN]] else %[[C_0]] : (!cir.bool, !s32i, !s32i) -> !s32i + // CIR: cir.store %[[RET]], %{{.*}} : !s32i, !cir.ptr<!s32i> + + // LLVM-LABEL: test_float_isinf_sign + // LLVM: %[[ARG:.*]] = load float, ptr %{{.*}} + // LLVM: %[[IS_INF:.*]] = call i1 @llvm.is.fpclass.f32(float %[[ARG]], i32 516) + // LLVM: %[[BITCAST:.*]] = bitcast float %[[ARG]] to i32 + // LLVM: %[[IS_NEG:.*]] = icmp slt i32 %[[BITCAST]], 0 + // LLVM: %[[SIGN:.*]] = select i1 %[[IS_NEG]], i32 -1, i32 1 + // LLVM: %[[RET:.*]] = select i1 %[[IS_INF]], i32 %[[SIGN]], i32 0 + // LLVM: store i32 %[[RET]], ptr %{{.*}}, align 4 + + // OGCG-LABEL: test_float_isinf_sign + // OGCG: %[[ARG:.*]] = load float, ptr %{{.*}} + // OGCG: %[[ABS:.*]] = call float @llvm.fabs.f32(float %[[ARG]]) + // OGCG: %[[IS_INF:.*]] = fcmp oeq float %[[ABS]], 0x7FF0000000000000 + // OGCG: %[[BITCAST:.*]] = bitcast float %[[ARG]] to i32 + // OGCG: %[[IS_NEG:.*]] = icmp slt i32 %[[BITCAST]], 0 + // OGCG: %[[SIGN:.*]] = select i1 %[[IS_NEG]], i32 -1, i32 1 + // OGCG: %[[RET:.*]] = select i1 %[[IS_INF]], i32 %[[SIGN]], i32 0 + // OGCG: ret i32 %[[RET]] + return __builtin_isinf_sign(x); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
