diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index a8589baa5ae0..6815031623b1 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -489,6 +489,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return createCast(cir::CastKind::int_to_ptr, src, newTy); } + mlir::Value createIntToBoolCast(mlir::Value v) { + return createCast(cir::CastKind::int_to_bool, v, getBoolTy()); + } + mlir::Value createGetMemberOp(mlir::Location &loc, mlir::Value structPtr, const char *fldName, unsigned idx) { diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 55619a8d935a..9ab77f478053 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1385,6 +1385,27 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_matrix_column_major_store: llvm_unreachable("BI__builtin_matrix_column_major_store NYI"); + case Builtin::BI__builtin_isinf_sign: { + CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, E); + mlir::Location Loc = getLoc(E->getBeginLoc()); + mlir::Value V = emitScalarExpr(E->getArg(0)); + mlir::Value IsInf = builder.createIsFPClass(Loc, V, FPClassTest::fcInf); + // FIMXE: CIR now will convert cir::BoolType to i8 type unconditionally. + // see https://github.com/llvm/clangir/issues/480 + // fix the issue can eliminate lots of redundant cast instruction + // for IsInf, i1 -> i8 -> i1 + // for IsNeg, i1 -> i8 -> i32 -> i1 + mlir::Value IsNeg = emitSignBit(Loc, *this, V); + IsNeg = builder.createIntToBoolCast(IsNeg); + 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: llvm_unreachable("BI__builtin_flt_rounds NYI"); diff --git a/clang/test/CIR/CodeGen/builtin-isinf-sign.c b/clang/test/CIR/CodeGen/builtin-isinf-sign.c new file mode 100644 index 000000000000..196e8a0401c2 --- /dev/null +++ b/clang/test/CIR/CodeGen/builtin-isinf-sign.c @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s + +int test_float_isinf_sign(float x) { + // CIR-LABEL: test_float_isinf_sign + // CIR: %[[TMP0:.*]] = cir.load %{{.*}} : !cir.ptr, !cir.float + // CIR: %[[IS_INF:.*]] = cir.is_fp_class %[[TMP0]], 516 : (!cir.float) -> !cir.bool + // CIR: %[[TMP1:.*]] = cir.signbit %[[TMP0]] : !cir.float -> !s32i + // CIR: %[[IS_NEG:.*]] = cir.cast(int_to_bool, %[[TMP1]] : !s32i), !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: %[[TMP4:.*]] = cir.select if %[[IS_NEG]] then %[[C_m1]] else %[[C_1]] : (!cir.bool, !s32i, !s32i) -> !s32i + // CIR: %10 = cir.select if %[[IS_INF]] then %[[TMP4]] else %[[C_0]] : (!cir.bool, !s32i, !s32i) -> !s32i + + // LLVM-LABEL: test_float_isinf_sign + // LLVM: %[[TMP0:.*]] = load float, ptr %{{.*}} + // LLVM: %[[IS_INF:.*]] = call i1 @llvm.is.fpclass.f32(float %[[TMP0]], i32 516) + // LLVM: %[[IS_INF_I8:.*]] = zext i1 %[[IS_INF]] to i8 + // LLVM: %[[TMP1:.*]] = bitcast float %[[TMP0]] to i32 + // LLVM: %[[IS_NEG:.*]] = icmp slt i32 %[[TMP1]], 0 + // FIXME: eliminate the redundant instruction + // [[IS_NEG]] changes bool -> i8 -> i32 -> i1 + // LLVM: %[[TMP2:.*]] = select i1 %{{.*}}, i32 -1, i32 1 + // LLVM: %[[IS_INF_I1:.*]] = trunc i8 %[[IS_INF_I8]] to i1 + // LLVM: %{{.*}} = select i1 %[[IS_INF_I1]], i32 %[[TMP2]], i32 0 + return __builtin_isinf_sign(x); +}