[clang] 1953b87 - [CIR][CodeGen] Upstream support for `__builtin_isinf_sign` (#183977)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 3 14:01:54 PST 2026
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);
+}
More information about the cfe-commits
mailing list