llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Ayokunle Amodu (ayokunle321)

<details>
<summary>Changes</summary>

This adds CIR codegen and lowering support for `__builtin_isinf_sign`.

---
Full diff: https://github.com/llvm/llvm-project/pull/183977.diff


7 Files Affected:

- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+5) 
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+17) 
- (modified) clang/include/clang/CIR/MissingFeatures.h (+1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+24-1) 
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+29) 
- (added) clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c (+41) 
- (added) clang/test/CIR/CodeGenBuiltins/builtin-signbit.cpp (+40) 


``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index efae3d9d894ed..9b14d3ed10a6b 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -544,6 +544,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
     return cir::VecInsertOp::create(*this, loc, vec, newElt, idxVal);
   }
 
+  cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) {
+    mlir::Type 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 a5a5197cd3ea6..bde065fb30c30 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 e6a33f56d518f..8c115853fe98a 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -278,6 +278,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 a27e66e0989fa..1de10ec70e91c 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));
@@ -1541,7 +1548,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 absArg = cir::FAbsOp::create(builder, loc, arg.getType(), arg);
+    mlir::Value isInf =
+        builder.createIsFPClass(loc, absArg, cir::FPClassTest::Infinity);
+    mlir::Value isNeg = emitSignBit(loc, *this, arg);
+    auto intTy = convertType(e->getType());
+    auto zero = builder.getNullValue(intTy, loc);
+    auto one = builder.getConstant(loc, cir::IntAttr::get(intTy, 1));
+    auto negativeOne = builder.getConstant(loc, cir::IntAttr::get(intTy, -1));
+    auto signResult = builder.createSelect(loc, isNeg, negativeOne, one);
+    auto 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 3318638b8a03d..d316162508d29 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -835,6 +835,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..e2a6d97b14480
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-isinf-sign.c
@@ -0,0 +1,41 @@
+// 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: %[[ABS:.*]] = cir.fabs %[[ARG]] : !cir.float
+  // CIR: %[[IS_INF:.*]] = cir.is_fp_class %[[ABS]], 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: %[[ABS:.*]] = call float @llvm.fabs.f32(float %[[ARG]])
+  // LLVM: %[[IS_INF:.*]] = call i1 @llvm.is.fpclass.f32(float %[[ABS]], 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);
+}
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-signbit.cpp 
b/clang/test/CIR/CodeGenBuiltins/builtin-signbit.cpp
new file mode 100644
index 0000000000000..1b568e9adeff0
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-signbit.cpp
@@ -0,0 +1,40 @@
+// 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.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+void test_signbit_float(float val) {
+    // CIR-LABEL: test_signbit_float
+    // CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
+
+    // LLVM-LABEL: test_signbit_float
+    // LLVM: [[TMP1:%.*]] = bitcast float %{{.+}} to i32
+    // LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
+    // LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
+
+    // OGCG-LABEL: test_signbit_float
+    // OGCG: [[TMP1:%.*]] = bitcast float %{{.+}} to i32
+    // OGCG: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
+    // OGCG: %{{.+}} = zext i1 [[TMP2]] to i32
+    __builtin_signbit(val);
+}
+
+void test_signbit_double(double val) {
+    // CIR-LABEL: test_signbit_double
+    // CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
+
+    // LLVM-LABEL: test_signbit_double
+    // 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
+    
+    // OGCG-LABEL: test_signbit_double
+    // OGCG: [[CONV:%.*]] = fptrunc double %{{.+}} to float
+    // OGCG: [[TMP1:%.*]] = bitcast float [[CONV]] to i32
+    // OGCG: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
+    // OGCG: %{{.+}} = zext i1 [[TMP2]] to i32
+    __builtin_signbitf(val);
+}
\ No newline at end of file

``````````

</details>


https://github.com/llvm/llvm-project/pull/183977
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to