1 //===-- FPEnv.cpp ---- FP Environment -------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file contains the implementations of entities that describe floating
11 /// point environment.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/IR/FPEnv.h"
16 #include "llvm/ADT/StringSwitch.h"
17 #include "llvm/IR/Instruction.h"
18 #include "llvm/IR/IntrinsicInst.h"
19 #include "llvm/IR/Intrinsics.h"
24 std::optional
<RoundingMode
> convertStrToRoundingMode(StringRef RoundingArg
) {
25 // For dynamic rounding mode, we use round to nearest but we will set the
26 // 'exact' SDNodeFlag so that the value will not be rounded.
27 return StringSwitch
<std::optional
<RoundingMode
>>(RoundingArg
)
28 .Case("round.dynamic", RoundingMode::Dynamic
)
29 .Case("round.tonearest", RoundingMode::NearestTiesToEven
)
30 .Case("round.tonearestaway", RoundingMode::NearestTiesToAway
)
31 .Case("round.downward", RoundingMode::TowardNegative
)
32 .Case("round.upward", RoundingMode::TowardPositive
)
33 .Case("round.towardzero", RoundingMode::TowardZero
)
34 .Default(std::nullopt
);
37 std::optional
<StringRef
> convertRoundingModeToStr(RoundingMode UseRounding
) {
38 std::optional
<StringRef
> RoundingStr
;
39 switch (UseRounding
) {
40 case RoundingMode::Dynamic
:
41 RoundingStr
= "round.dynamic";
43 case RoundingMode::NearestTiesToEven
:
44 RoundingStr
= "round.tonearest";
46 case RoundingMode::NearestTiesToAway
:
47 RoundingStr
= "round.tonearestaway";
49 case RoundingMode::TowardNegative
:
50 RoundingStr
= "round.downward";
52 case RoundingMode::TowardPositive
:
53 RoundingStr
= "round.upward";
55 case RoundingMode::TowardZero
:
56 RoundingStr
= "round.towardzero";
64 std::optional
<fp::ExceptionBehavior
>
65 convertStrToExceptionBehavior(StringRef ExceptionArg
) {
66 return StringSwitch
<std::optional
<fp::ExceptionBehavior
>>(ExceptionArg
)
67 .Case("fpexcept.ignore", fp::ebIgnore
)
68 .Case("fpexcept.maytrap", fp::ebMayTrap
)
69 .Case("fpexcept.strict", fp::ebStrict
)
70 .Default(std::nullopt
);
73 std::optional
<StringRef
>
74 convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept
) {
75 std::optional
<StringRef
> ExceptStr
;
78 ExceptStr
= "fpexcept.strict";
81 ExceptStr
= "fpexcept.ignore";
84 ExceptStr
= "fpexcept.maytrap";
90 Intrinsic::ID
getConstrainedIntrinsicID(const Instruction
&Instr
) {
91 Intrinsic::ID IID
= Intrinsic::not_intrinsic
;
92 switch (Instr
.getOpcode()) {
93 case Instruction::FCmp
:
94 // Unlike other instructions FCmp can be mapped to one of two intrinsic
95 // functions. We choose the non-signaling variant.
96 IID
= Intrinsic::experimental_constrained_fcmp
;
100 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
101 case Instruction::NAME: \
102 IID = Intrinsic::INTRINSIC; \
104 #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
105 #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
106 #include "llvm/IR/ConstrainedOps.def"
109 case Instruction::Call
:
110 if (auto *IntrinCall
= dyn_cast
<IntrinsicInst
>(&Instr
)) {
111 switch (IntrinCall
->getIntrinsicID()) {
112 #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
113 case Intrinsic::NAME: \
114 IID = Intrinsic::INTRINSIC; \
116 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
117 #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
118 #include "llvm/IR/ConstrainedOps.def"