diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -323,6 +323,9 @@ BUILTIN(__builtin_truncl, "LdLd", "Fnc") BUILTIN(__builtin_truncf16, "hh", "Fnc") +// Access to floating point environment +BUILTIN(__builtin_flt_rounds, "i", "n") + // C99 complex builtins BUILTIN(__builtin_cabs, "dXd", "Fne") BUILTIN(__builtin_cabsf, "fXf", "Fne") @@ -517,7 +520,6 @@ BUILTIN(__builtin_extract_return_addr, "v*v*", "n") BUILTIN(__builtin_frame_address, "v*IUi", "n") BUILTIN(__builtin___clear_cache, "vc*c*", "n") -BUILTIN(__builtin_flt_rounds, "i", "nc") BUILTIN(__builtin_setjmp, "iv**", "j") BUILTIN(__builtin_longjmp, "vv**i", "r") BUILTIN(__builtin_unwind_init, "v", "") diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -18251,6 +18251,44 @@ would and handles error conditions in the same way. +Floating Point Environment Manipulation intrinsics +-------------------------------------------------- + +These functions read or write floating point environment, such as rounding +mode or state of floating point exceptions. Altering the floating point +environment requires special care. See :ref:`Floating Point Environment `. + +'``llvm.flt.rounds``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i32 @llvm.flt.rounds() + +Overview: +""""""""" + +The '``llvm.flt.rounds``' intrinsic reads current rounding mode. + +Semantics: +"""""""""" + +The '``llvm.flt.rounds``' intrinsic returns the current rounding mode. +Encoding of the returned values is same as the result of ``FLT_ROUNDS``, +specified by C standard: + +:: + + 0 - toward zero + 1 - to nearest, ties to even + 2 - toward positive infinity + 3 - toward negative infinity + 4 - to nearest, ties away from zero + + General Intrinsics ------------------ diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -611,6 +611,14 @@ [IntrNoMem, IntrSpeculatable, IntrWillReturn, ImmArg<1>, ImmArg<2>, ImmArg<3>]>, GCCBuiltin<"__builtin_object_size">; +//===--------------- Access to Floating Point Environment -----------------===// +// + +let IntrProperties = [IntrInaccessibleMemOnly, IntrWillReturn] in { + def int_flt_rounds : Intrinsic<[llvm_i32_ty], []>, + GCCBuiltin<"__builtin_flt_rounds">; +} + //===--------------- Constrained Floating Point Intrinsics ----------------===// // @@ -1114,8 +1122,6 @@ ///===-------------------------- Other Intrinsics --------------------------===// // -def int_flt_rounds : Intrinsic<[llvm_i32_ty]>, - GCCBuiltin<"__builtin_flt_rounds">; def int_trap : Intrinsic<[], [], [IntrNoReturn, IntrCold]>, GCCBuiltin<"__builtin_trap">; def int_debugtrap : Intrinsic<[]>, diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def --- a/llvm/include/llvm/IR/RuntimeLibcalls.def +++ b/llvm/include/llvm/IR/RuntimeLibcalls.def @@ -548,6 +548,9 @@ // Return address HANDLE_LIBCALL(RETURN_ADDRESS, nullptr) +// Floating-point Environment +HANDLE_LIBCALL(FLT_ROUNDS_, "__flt_rounds") + HANDLE_LIBCALL(UNKNOWN_LIBCALL, nullptr) #undef HANDLE_LIBCALL diff --git a/llvm/lib/CodeGen/IntrinsicLowering.cpp b/llvm/lib/CodeGen/IntrinsicLowering.cpp --- a/llvm/lib/CodeGen/IntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp @@ -426,10 +426,9 @@ break; } case Intrinsic::flt_rounds: - // Lower to "round to the nearest" - if (!CI->getType()->isVoidTy()) - CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 1)); - break; + ReplaceCallWith("__flt_rounds", CI, CI->arg_begin(), CI->arg_end(), + Type::getInt32Ty(CI->getContext())); + break; case Intrinsic::invariant_start: case Intrinsic::lifetime_start: // Discard region information. diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2814,10 +2814,16 @@ FA, Offset)); break; } - case ISD::FLT_ROUNDS_: - Results.push_back(DAG.getConstant(1, dl, Node->getValueType(0))); - Results.push_back(Node->getOperand(0)); + case ISD::FLT_ROUNDS_: { + EVT RetVT = Node->getValueType(0); + TargetLowering::MakeLibCallOptions CallOptions; + std::pair Tmp = TLI.makeLibCall( + DAG, RTLIB::FLT_ROUNDS_, RetVT, None, CallOptions, + SDLoc(Node), Node->getOperand(0)); + Results.push_back(Tmp.first); + Results.push_back(Tmp.second); break; + } case ISD::EH_RETURN: case ISD::EH_LABEL: case ISD::PREFETCH: diff --git a/llvm/test/CodeGen/MSP430/flt_rounds.ll b/llvm/test/CodeGen/MSP430/flt_rounds.ll --- a/llvm/test/CodeGen/MSP430/flt_rounds.ll +++ b/llvm/test/CodeGen/MSP430/flt_rounds.ll @@ -1,4 +1,4 @@ -; RUN: llc -verify-machineinstrs < %s -march=msp430 +; RUN: llc -verify-machineinstrs -march=msp430 < %s | FileCheck %s define i16 @foo() { entry: @@ -8,3 +8,5 @@ } declare i32 @llvm.flt.rounds() nounwind + +; CHECK: call #__flt_rounds diff --git a/llvm/test/CodeGen/RISCV/flt-rounds.ll b/llvm/test/CodeGen/RISCV/flt-rounds.ll --- a/llvm/test/CodeGen/RISCV/flt-rounds.ll +++ b/llvm/test/CodeGen/RISCV/flt-rounds.ll @@ -9,12 +9,20 @@ define i32 @test_flt_rounds() nounwind { ; RV32I-LABEL: test_flt_rounds: ; RV32I: # %bb.0: -; RV32I-NEXT: addi a0, zero, 1 +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: call __flt_rounds +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 ; RV32I-NEXT: ret ; ; RV64I-LABEL: test_flt_rounds: ; RV64I: # %bb.0: -; RV64I-NEXT: addi a0, zero, 1 +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: call __flt_rounds +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 ; RV64I-NEXT: ret %1 = call i32 @llvm.flt.rounds() ret i32 %1