From ffa2b3c4cd4a437b7f3e6df9019920a181ad5888 Mon Sep 17 00:00:00 2001 From: ghehg <166402688+ghehg@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:49:16 -0400 Subject: [PATCH] [CIR][CIRGen] Support __builtin_huge_val for float type (#889) as title. The test cases are from [clang codegen test case](https://github.com/llvm/clangir/blob/52323c17c6a3708b3eb72651465f7d4b82f057e7/clang/test/CodeGen/builtins.c#L37) --- clang/lib/CIR/CodeGen/CIRGenBuilder.h | 9 ++++++++ clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 12 +++++++++-- clang/test/CIR/CodeGen/builtins.c | 28 +++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 clang/test/CIR/CodeGen/builtins.c diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index a02cdf26ee4d..1734f450d303 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -536,6 +536,15 @@ class CIRGenBuilderTy : public CIRBaseBuilderTy { mlir::cir::ConstantOp getConstInt(mlir::Location loc, mlir::Type t, uint64_t C); + + mlir::cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t, + llvm::APFloat fpVal) { + assert((mlir::isa(t)) && + "expected mlir::cir::SingleType or mlir::cir::DoubleType"); + return create(loc, t, + getAttr(t, fpVal)); + } + /// Create constant nullptr for pointer-to-data-member type ty. mlir::cir::ConstantOp getNullDataMemberPtr(mlir::cir::DataMemberType ty, mlir::Location loc) { diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 27816d833e91..0eaf2f53efc7 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -313,8 +313,16 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(builder.getConstInt(getLoc(E->getSourceRange()), Result.Val.getInt())); } - if (Result.Val.isFloat()) - llvm_unreachable("NYI"); + if (Result.Val.isFloat()) { + // Note: we are using result type of CallExpr to determine the type of + // the constant. Clang Codegen uses the result value to make judgement + // of the type. We feel it should be Ok to use expression type because + // it is hard to imagine a builtin function evaluates to + // a value that over/underflows its own defined type. + mlir::Type resTy = getCIRType(E->getType()); + return RValue::get(builder.getConstFP(getLoc(E->getExprLoc()), resTy, + Result.Val.getFloat())); + } } // If current long-double semantics is IEEE 128-bit, replace math builtins diff --git a/clang/test/CIR/CodeGen/builtins.c b/clang/test/CIR/CodeGen/builtins.c new file mode 100644 index 000000000000..c843f50bbdda --- /dev/null +++ b/clang/test/CIR/CodeGen/builtins.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck -check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s + + +void test1() { + float f; + double d; + f = __builtin_huge_valf(); + d = __builtin_huge_val(); +} + +// CIR-LABEL: test1 +// CIR: [[F:%.*]] = cir.alloca !cir.float, !cir.ptr, ["f"] {alignment = 4 : i64} +// CIR: [[D:%.*]] = cir.alloca !cir.double, !cir.ptr, ["d"] {alignment = 8 : i64} +// CIR: [[F_VAL:%.*]] = cir.const #cir.fp<0x7F800000> : !cir.float +// CIR: cir.store [[F_VAL]], [[F]] : !cir.float, !cir.ptr +// CIR: [[D_VAL:%.*]] = cir.const #cir.fp<0x7FF0000000000000> : !cir.double +// CIR: cir.store [[D_VAL]], [[D]] : !cir.double, !cir.ptr loc(#loc17) +// CIR: cir.return + +// LLVM-LABEL: test1 +// [[F:%.*]] = alloca float, align 4 +// [[D:%.*]] = alloca double, align 8 +// store float 0x7FF0000000000000, ptr [[F]], align 4 +// store double 0x7FF0000000000000, ptr[[D]], align 8 +// ret void