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
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"
20
21 namespace llvm {
22
convertStrToRoundingMode(StringRef RoundingArg)23 Optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) {
24 // For dynamic rounding mode, we use round to nearest but we will set the
25 // 'exact' SDNodeFlag so that the value will not be rounded.
26 return StringSwitch<Optional<RoundingMode>>(RoundingArg)
27 .Case("round.dynamic", RoundingMode::Dynamic)
28 .Case("round.tonearest", RoundingMode::NearestTiesToEven)
29 .Case("round.tonearestaway", RoundingMode::NearestTiesToAway)
30 .Case("round.downward", RoundingMode::TowardNegative)
31 .Case("round.upward", RoundingMode::TowardPositive)
32 .Case("round.towardzero", RoundingMode::TowardZero)
33 .Default(None);
34 }
35
convertRoundingModeToStr(RoundingMode UseRounding)36 Optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) {
37 Optional<StringRef> RoundingStr = None;
38 switch (UseRounding) {
39 case RoundingMode::Dynamic:
40 RoundingStr = "round.dynamic";
41 break;
42 case RoundingMode::NearestTiesToEven:
43 RoundingStr = "round.tonearest";
44 break;
45 case RoundingMode::NearestTiesToAway:
46 RoundingStr = "round.tonearestaway";
47 break;
48 case RoundingMode::TowardNegative:
49 RoundingStr = "round.downward";
50 break;
51 case RoundingMode::TowardPositive:
52 RoundingStr = "round.upward";
53 break;
54 case RoundingMode::TowardZero:
55 RoundingStr = "round.towardzero";
56 break;
57 default:
58 break;
59 }
60 return RoundingStr;
61 }
62
63 Optional<fp::ExceptionBehavior>
convertStrToExceptionBehavior(StringRef ExceptionArg)64 convertStrToExceptionBehavior(StringRef ExceptionArg) {
65 return StringSwitch<Optional<fp::ExceptionBehavior>>(ExceptionArg)
66 .Case("fpexcept.ignore", fp::ebIgnore)
67 .Case("fpexcept.maytrap", fp::ebMayTrap)
68 .Case("fpexcept.strict", fp::ebStrict)
69 .Default(None);
70 }
71
72 Optional<StringRef>
convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept)73 convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) {
74 Optional<StringRef> ExceptStr = None;
75 switch (UseExcept) {
76 case fp::ebStrict:
77 ExceptStr = "fpexcept.strict";
78 break;
79 case fp::ebIgnore:
80 ExceptStr = "fpexcept.ignore";
81 break;
82 case fp::ebMayTrap:
83 ExceptStr = "fpexcept.maytrap";
84 break;
85 }
86 return ExceptStr;
87 }
88
getConstrainedIntrinsicID(const Instruction & Instr)89 Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr) {
90 Intrinsic::ID IID = Intrinsic::not_intrinsic;
91 switch (Instr.getOpcode()) {
92 case Instruction::FCmp:
93 // Unlike other instructions FCmp can be mapped to one of two intrinsic
94 // functions. We choose the non-signaling variant.
95 IID = Intrinsic::experimental_constrained_fcmp;
96 break;
97
98 // Instructions
99 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
100 case Instruction::NAME: \
101 IID = Intrinsic::INTRINSIC; \
102 break;
103 #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
104 #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
105 #include "llvm/IR/ConstrainedOps.def"
106
107 // Intrinsic calls.
108 case Instruction::Call:
109 if (auto *IntrinCall = dyn_cast<IntrinsicInst>(&Instr)) {
110 switch (IntrinCall->getIntrinsicID()) {
111 #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
112 case Intrinsic::NAME: \
113 IID = Intrinsic::INTRINSIC; \
114 break;
115 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
116 #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
117 #include "llvm/IR/ConstrainedOps.def"
118 default:
119 break;
120 }
121 }
122 break;
123 default:
124 break;
125 }
126
127 return IID;
128 }
129
130 } // namespace llvm
131