xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/FPEnv.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1480093f4SDimitry Andric //===-- FPEnv.cpp ---- FP Environment -------------------------------------===//
2480093f4SDimitry Andric //
3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6480093f4SDimitry Andric //
7480093f4SDimitry Andric //===----------------------------------------------------------------------===//
8480093f4SDimitry Andric //
9480093f4SDimitry Andric /// @file
10480093f4SDimitry Andric /// This file contains the implementations of entities that describe floating
11480093f4SDimitry Andric /// point environment.
12480093f4SDimitry Andric //
13480093f4SDimitry Andric //===----------------------------------------------------------------------===//
14480093f4SDimitry Andric 
15480093f4SDimitry Andric #include "llvm/IR/FPEnv.h"
165ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h"
17*81ad6265SDimitry Andric #include "llvm/IR/Instruction.h"
18*81ad6265SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
19*81ad6265SDimitry Andric #include "llvm/IR/Intrinsics.h"
20480093f4SDimitry Andric 
21480093f4SDimitry Andric namespace llvm {
22480093f4SDimitry Andric 
23349cc55cSDimitry Andric Optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) {
24480093f4SDimitry Andric   // For dynamic rounding mode, we use round to nearest but we will set the
25480093f4SDimitry Andric   // 'exact' SDNodeFlag so that the value will not be rounded.
265ffd83dbSDimitry Andric   return StringSwitch<Optional<RoundingMode>>(RoundingArg)
275ffd83dbSDimitry Andric       .Case("round.dynamic", RoundingMode::Dynamic)
285ffd83dbSDimitry Andric       .Case("round.tonearest", RoundingMode::NearestTiesToEven)
295ffd83dbSDimitry Andric       .Case("round.tonearestaway", RoundingMode::NearestTiesToAway)
305ffd83dbSDimitry Andric       .Case("round.downward", RoundingMode::TowardNegative)
315ffd83dbSDimitry Andric       .Case("round.upward", RoundingMode::TowardPositive)
325ffd83dbSDimitry Andric       .Case("round.towardzero", RoundingMode::TowardZero)
33480093f4SDimitry Andric       .Default(None);
34480093f4SDimitry Andric }
35480093f4SDimitry Andric 
36349cc55cSDimitry Andric Optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) {
37480093f4SDimitry Andric   Optional<StringRef> RoundingStr = None;
38480093f4SDimitry Andric   switch (UseRounding) {
395ffd83dbSDimitry Andric   case RoundingMode::Dynamic:
40480093f4SDimitry Andric     RoundingStr = "round.dynamic";
41480093f4SDimitry Andric     break;
425ffd83dbSDimitry Andric   case RoundingMode::NearestTiesToEven:
43480093f4SDimitry Andric     RoundingStr = "round.tonearest";
44480093f4SDimitry Andric     break;
455ffd83dbSDimitry Andric   case RoundingMode::NearestTiesToAway:
465ffd83dbSDimitry Andric     RoundingStr = "round.tonearestaway";
475ffd83dbSDimitry Andric     break;
485ffd83dbSDimitry Andric   case RoundingMode::TowardNegative:
49480093f4SDimitry Andric     RoundingStr = "round.downward";
50480093f4SDimitry Andric     break;
515ffd83dbSDimitry Andric   case RoundingMode::TowardPositive:
52480093f4SDimitry Andric     RoundingStr = "round.upward";
53480093f4SDimitry Andric     break;
545ffd83dbSDimitry Andric   case RoundingMode::TowardZero:
55480093f4SDimitry Andric     RoundingStr = "round.towardzero";
56480093f4SDimitry Andric     break;
575ffd83dbSDimitry Andric   default:
585ffd83dbSDimitry Andric     break;
59480093f4SDimitry Andric   }
60480093f4SDimitry Andric   return RoundingStr;
61480093f4SDimitry Andric }
62480093f4SDimitry Andric 
63349cc55cSDimitry Andric Optional<fp::ExceptionBehavior>
64349cc55cSDimitry Andric convertStrToExceptionBehavior(StringRef ExceptionArg) {
65480093f4SDimitry Andric   return StringSwitch<Optional<fp::ExceptionBehavior>>(ExceptionArg)
66480093f4SDimitry Andric       .Case("fpexcept.ignore", fp::ebIgnore)
67480093f4SDimitry Andric       .Case("fpexcept.maytrap", fp::ebMayTrap)
68480093f4SDimitry Andric       .Case("fpexcept.strict", fp::ebStrict)
69480093f4SDimitry Andric       .Default(None);
70480093f4SDimitry Andric }
71480093f4SDimitry Andric 
72349cc55cSDimitry Andric Optional<StringRef>
73349cc55cSDimitry Andric convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) {
74480093f4SDimitry Andric   Optional<StringRef> ExceptStr = None;
75480093f4SDimitry Andric   switch (UseExcept) {
76480093f4SDimitry Andric   case fp::ebStrict:
77480093f4SDimitry Andric     ExceptStr = "fpexcept.strict";
78480093f4SDimitry Andric     break;
79480093f4SDimitry Andric   case fp::ebIgnore:
80480093f4SDimitry Andric     ExceptStr = "fpexcept.ignore";
81480093f4SDimitry Andric     break;
82480093f4SDimitry Andric   case fp::ebMayTrap:
83480093f4SDimitry Andric     ExceptStr = "fpexcept.maytrap";
84480093f4SDimitry Andric     break;
85480093f4SDimitry Andric   }
86480093f4SDimitry Andric   return ExceptStr;
87480093f4SDimitry Andric }
88*81ad6265SDimitry Andric 
89*81ad6265SDimitry Andric Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr) {
90*81ad6265SDimitry Andric   Intrinsic::ID IID = Intrinsic::not_intrinsic;
91*81ad6265SDimitry Andric   switch (Instr.getOpcode()) {
92*81ad6265SDimitry Andric   case Instruction::FCmp:
93*81ad6265SDimitry Andric     // Unlike other instructions FCmp can be mapped to one of two intrinsic
94*81ad6265SDimitry Andric     // functions. We choose the non-signaling variant.
95*81ad6265SDimitry Andric     IID = Intrinsic::experimental_constrained_fcmp;
96*81ad6265SDimitry Andric     break;
97*81ad6265SDimitry Andric 
98*81ad6265SDimitry Andric     // Instructions
99*81ad6265SDimitry Andric #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
100*81ad6265SDimitry Andric   case Instruction::NAME:                                                      \
101*81ad6265SDimitry Andric     IID = Intrinsic::INTRINSIC;                                                \
102*81ad6265SDimitry Andric     break;
103*81ad6265SDimitry Andric #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
104*81ad6265SDimitry Andric #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
105*81ad6265SDimitry Andric #include "llvm/IR/ConstrainedOps.def"
106*81ad6265SDimitry Andric 
107*81ad6265SDimitry Andric   // Intrinsic calls.
108*81ad6265SDimitry Andric   case Instruction::Call:
109*81ad6265SDimitry Andric     if (auto *IntrinCall = dyn_cast<IntrinsicInst>(&Instr)) {
110*81ad6265SDimitry Andric       switch (IntrinCall->getIntrinsicID()) {
111*81ad6265SDimitry Andric #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                            \
112*81ad6265SDimitry Andric   case Intrinsic::NAME:                                                        \
113*81ad6265SDimitry Andric     IID = Intrinsic::INTRINSIC;                                                \
114*81ad6265SDimitry Andric     break;
115*81ad6265SDimitry Andric #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
116*81ad6265SDimitry Andric #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
117*81ad6265SDimitry Andric #include "llvm/IR/ConstrainedOps.def"
118*81ad6265SDimitry Andric       default:
119*81ad6265SDimitry Andric         break;
120*81ad6265SDimitry Andric       }
121*81ad6265SDimitry Andric     }
122*81ad6265SDimitry Andric     break;
123*81ad6265SDimitry Andric   default:
124*81ad6265SDimitry Andric     break;
125*81ad6265SDimitry Andric   }
126*81ad6265SDimitry Andric 
127*81ad6265SDimitry Andric   return IID;
128*81ad6265SDimitry Andric }
129*81ad6265SDimitry Andric 
1305ffd83dbSDimitry Andric } // namespace llvm
131