150
|
1 //===-- FPEnv.cpp ---- FP Environment -------------------------------------===//
|
|
2 //
|
|
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
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8 //
|
|
9 /// @file
|
|
10 /// This file contains the implementations of entities that describe floating
|
|
11 /// point environment.
|
|
12 //
|
|
13 //===----------------------------------------------------------------------===//
|
|
14
|
221
|
15 #include "llvm/IR/FPEnv.h"
|
150
|
16 #include "llvm/ADT/StringSwitch.h"
|
236
|
17 #include "llvm/IR/Instruction.h"
|
|
18 #include "llvm/IR/IntrinsicInst.h"
|
|
19 #include "llvm/IR/Intrinsics.h"
|
252
|
20 #include <optional>
|
150
|
21
|
|
22 namespace llvm {
|
|
23
|
252
|
24 std::optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) {
|
150
|
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.
|
252
|
27 return StringSwitch<std::optional<RoundingMode>>(RoundingArg)
|
173
|
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)
|
252
|
34 .Default(std::nullopt);
|
150
|
35 }
|
|
36
|
252
|
37 std::optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) {
|
|
38 std::optional<StringRef> RoundingStr;
|
150
|
39 switch (UseRounding) {
|
173
|
40 case RoundingMode::Dynamic:
|
150
|
41 RoundingStr = "round.dynamic";
|
|
42 break;
|
173
|
43 case RoundingMode::NearestTiesToEven:
|
150
|
44 RoundingStr = "round.tonearest";
|
|
45 break;
|
173
|
46 case RoundingMode::NearestTiesToAway:
|
|
47 RoundingStr = "round.tonearestaway";
|
|
48 break;
|
|
49 case RoundingMode::TowardNegative:
|
150
|
50 RoundingStr = "round.downward";
|
|
51 break;
|
173
|
52 case RoundingMode::TowardPositive:
|
150
|
53 RoundingStr = "round.upward";
|
|
54 break;
|
173
|
55 case RoundingMode::TowardZero:
|
150
|
56 RoundingStr = "round.towardzero";
|
|
57 break;
|
173
|
58 default:
|
|
59 break;
|
150
|
60 }
|
|
61 return RoundingStr;
|
|
62 }
|
|
63
|
252
|
64 std::optional<fp::ExceptionBehavior>
|
236
|
65 convertStrToExceptionBehavior(StringRef ExceptionArg) {
|
252
|
66 return StringSwitch<std::optional<fp::ExceptionBehavior>>(ExceptionArg)
|
150
|
67 .Case("fpexcept.ignore", fp::ebIgnore)
|
|
68 .Case("fpexcept.maytrap", fp::ebMayTrap)
|
|
69 .Case("fpexcept.strict", fp::ebStrict)
|
252
|
70 .Default(std::nullopt);
|
150
|
71 }
|
|
72
|
252
|
73 std::optional<StringRef>
|
236
|
74 convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) {
|
252
|
75 std::optional<StringRef> ExceptStr;
|
150
|
76 switch (UseExcept) {
|
|
77 case fp::ebStrict:
|
|
78 ExceptStr = "fpexcept.strict";
|
|
79 break;
|
|
80 case fp::ebIgnore:
|
|
81 ExceptStr = "fpexcept.ignore";
|
|
82 break;
|
|
83 case fp::ebMayTrap:
|
|
84 ExceptStr = "fpexcept.maytrap";
|
|
85 break;
|
|
86 }
|
|
87 return ExceptStr;
|
|
88 }
|
236
|
89
|
|
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;
|
|
97 break;
|
|
98
|
|
99 // Instructions
|
|
100 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
|
|
101 case Instruction::NAME: \
|
|
102 IID = Intrinsic::INTRINSIC; \
|
|
103 break;
|
|
104 #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
|
|
105 #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
|
|
106 #include "llvm/IR/ConstrainedOps.def"
|
|
107
|
|
108 // Intrinsic calls.
|
|
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; \
|
|
115 break;
|
|
116 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
|
|
117 #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
|
|
118 #include "llvm/IR/ConstrainedOps.def"
|
|
119 default:
|
|
120 break;
|
|
121 }
|
|
122 }
|
|
123 break;
|
|
124 default:
|
|
125 break;
|
|
126 }
|
|
127
|
|
128 return IID;
|
|
129 }
|
|
130
|
221
|
131 } // namespace llvm
|