xref: /llvm-project/llvm/lib/IR/FPEnv.cpp (revision ab672e91737daa55f18662d569d8c1ae6e0b4dfe)
1ea8678d1SSerge Pavlov //===-- FPEnv.cpp ---- FP Environment -------------------------------------===//
2ea8678d1SSerge Pavlov //
3ea8678d1SSerge Pavlov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ea8678d1SSerge Pavlov // See https://llvm.org/LICENSE.txt for license information.
5ea8678d1SSerge Pavlov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ea8678d1SSerge Pavlov //
7ea8678d1SSerge Pavlov //===----------------------------------------------------------------------===//
8ea8678d1SSerge Pavlov //
9ea8678d1SSerge Pavlov /// @file
10ea8678d1SSerge Pavlov /// This file contains the implementations of entities that describe floating
11ea8678d1SSerge Pavlov /// point environment.
12ea8678d1SSerge Pavlov //
13ea8678d1SSerge Pavlov //===----------------------------------------------------------------------===//
14ea8678d1SSerge Pavlov 
15ea8678d1SSerge Pavlov #include "llvm/IR/FPEnv.h"
16e367c008SSimon Pilgrim #include "llvm/ADT/StringSwitch.h"
171e027375Sserge-sans-paille #include "llvm/IR/Instruction.h"
18881350a9SSerge Pavlov #include "llvm/IR/IntrinsicInst.h"
19881350a9SSerge Pavlov #include "llvm/IR/Intrinsics.h"
20*ab672e91SKrzysztof Parzyszek #include <optional>
21ea8678d1SSerge Pavlov 
22ea8678d1SSerge Pavlov namespace llvm {
23ea8678d1SSerge Pavlov 
convertStrToRoundingMode(StringRef RoundingArg)24*ab672e91SKrzysztof Parzyszek std::optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) {
25ea8678d1SSerge Pavlov   // For dynamic rounding mode, we use round to nearest but we will set the
26ea8678d1SSerge Pavlov   // 'exact' SDNodeFlag so that the value will not be rounded.
27*ab672e91SKrzysztof Parzyszek   return StringSwitch<std::optional<RoundingMode>>(RoundingArg)
28c7ff5b38SSerge Pavlov       .Case("round.dynamic", RoundingMode::Dynamic)
29c7ff5b38SSerge Pavlov       .Case("round.tonearest", RoundingMode::NearestTiesToEven)
30c7ff5b38SSerge Pavlov       .Case("round.tonearestaway", RoundingMode::NearestTiesToAway)
31c7ff5b38SSerge Pavlov       .Case("round.downward", RoundingMode::TowardNegative)
32c7ff5b38SSerge Pavlov       .Case("round.upward", RoundingMode::TowardPositive)
33c7ff5b38SSerge Pavlov       .Case("round.towardzero", RoundingMode::TowardZero)
34e842c06cSKazu Hirata       .Default(std::nullopt);
35ea8678d1SSerge Pavlov }
36ea8678d1SSerge Pavlov 
convertRoundingModeToStr(RoundingMode UseRounding)37*ab672e91SKrzysztof Parzyszek std::optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) {
38*ab672e91SKrzysztof Parzyszek   std::optional<StringRef> RoundingStr;
39ea8678d1SSerge Pavlov   switch (UseRounding) {
40c7ff5b38SSerge Pavlov   case RoundingMode::Dynamic:
41ea8678d1SSerge Pavlov     RoundingStr = "round.dynamic";
42ea8678d1SSerge Pavlov     break;
43c7ff5b38SSerge Pavlov   case RoundingMode::NearestTiesToEven:
44ea8678d1SSerge Pavlov     RoundingStr = "round.tonearest";
45ea8678d1SSerge Pavlov     break;
46c7ff5b38SSerge Pavlov   case RoundingMode::NearestTiesToAway:
47c7ff5b38SSerge Pavlov     RoundingStr = "round.tonearestaway";
48c7ff5b38SSerge Pavlov     break;
49c7ff5b38SSerge Pavlov   case RoundingMode::TowardNegative:
50ea8678d1SSerge Pavlov     RoundingStr = "round.downward";
51ea8678d1SSerge Pavlov     break;
52c7ff5b38SSerge Pavlov   case RoundingMode::TowardPositive:
53ea8678d1SSerge Pavlov     RoundingStr = "round.upward";
54ea8678d1SSerge Pavlov     break;
55c7ff5b38SSerge Pavlov   case RoundingMode::TowardZero:
56ea8678d1SSerge Pavlov     RoundingStr = "round.towardzero";
57ea8678d1SSerge Pavlov     break;
58c7ff5b38SSerge Pavlov   default:
59c7ff5b38SSerge Pavlov     break;
60ea8678d1SSerge Pavlov   }
61ea8678d1SSerge Pavlov   return RoundingStr;
62ea8678d1SSerge Pavlov }
63ea8678d1SSerge Pavlov 
64*ab672e91SKrzysztof Parzyszek std::optional<fp::ExceptionBehavior>
convertStrToExceptionBehavior(StringRef ExceptionArg)6597c23166SKevin P. Neal convertStrToExceptionBehavior(StringRef ExceptionArg) {
66*ab672e91SKrzysztof Parzyszek   return StringSwitch<std::optional<fp::ExceptionBehavior>>(ExceptionArg)
67ea8678d1SSerge Pavlov       .Case("fpexcept.ignore", fp::ebIgnore)
68ea8678d1SSerge Pavlov       .Case("fpexcept.maytrap", fp::ebMayTrap)
69ea8678d1SSerge Pavlov       .Case("fpexcept.strict", fp::ebStrict)
70e842c06cSKazu Hirata       .Default(std::nullopt);
71ea8678d1SSerge Pavlov }
72ea8678d1SSerge Pavlov 
73*ab672e91SKrzysztof Parzyszek std::optional<StringRef>
convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept)7497c23166SKevin P. Neal convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) {
75*ab672e91SKrzysztof Parzyszek   std::optional<StringRef> ExceptStr;
76ea8678d1SSerge Pavlov   switch (UseExcept) {
77ea8678d1SSerge Pavlov   case fp::ebStrict:
78ea8678d1SSerge Pavlov     ExceptStr = "fpexcept.strict";
79ea8678d1SSerge Pavlov     break;
80ea8678d1SSerge Pavlov   case fp::ebIgnore:
81ea8678d1SSerge Pavlov     ExceptStr = "fpexcept.ignore";
82ea8678d1SSerge Pavlov     break;
83ea8678d1SSerge Pavlov   case fp::ebMayTrap:
84ea8678d1SSerge Pavlov     ExceptStr = "fpexcept.maytrap";
85ea8678d1SSerge Pavlov     break;
86ea8678d1SSerge Pavlov   }
87ea8678d1SSerge Pavlov   return ExceptStr;
88ea8678d1SSerge Pavlov }
89881350a9SSerge Pavlov 
getConstrainedIntrinsicID(const Instruction & Instr)90881350a9SSerge Pavlov Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr) {
91881350a9SSerge Pavlov   Intrinsic::ID IID = Intrinsic::not_intrinsic;
92881350a9SSerge Pavlov   switch (Instr.getOpcode()) {
93881350a9SSerge Pavlov   case Instruction::FCmp:
94881350a9SSerge Pavlov     // Unlike other instructions FCmp can be mapped to one of two intrinsic
95881350a9SSerge Pavlov     // functions. We choose the non-signaling variant.
96881350a9SSerge Pavlov     IID = Intrinsic::experimental_constrained_fcmp;
97881350a9SSerge Pavlov     break;
98881350a9SSerge Pavlov 
99881350a9SSerge Pavlov     // Instructions
100881350a9SSerge Pavlov #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
101881350a9SSerge Pavlov   case Instruction::NAME:                                                      \
102881350a9SSerge Pavlov     IID = Intrinsic::INTRINSIC;                                                \
103881350a9SSerge Pavlov     break;
104881350a9SSerge Pavlov #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
105881350a9SSerge Pavlov #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
106881350a9SSerge Pavlov #include "llvm/IR/ConstrainedOps.def"
107881350a9SSerge Pavlov 
108881350a9SSerge Pavlov   // Intrinsic calls.
109881350a9SSerge Pavlov   case Instruction::Call:
110881350a9SSerge Pavlov     if (auto *IntrinCall = dyn_cast<IntrinsicInst>(&Instr)) {
111881350a9SSerge Pavlov       switch (IntrinCall->getIntrinsicID()) {
112881350a9SSerge Pavlov #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                            \
113881350a9SSerge Pavlov   case Intrinsic::NAME:                                                        \
114881350a9SSerge Pavlov     IID = Intrinsic::INTRINSIC;                                                \
115881350a9SSerge Pavlov     break;
116881350a9SSerge Pavlov #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
117881350a9SSerge Pavlov #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
118881350a9SSerge Pavlov #include "llvm/IR/ConstrainedOps.def"
119881350a9SSerge Pavlov       default:
120881350a9SSerge Pavlov         break;
121881350a9SSerge Pavlov       }
122881350a9SSerge Pavlov     }
123881350a9SSerge Pavlov     break;
124881350a9SSerge Pavlov   default:
125881350a9SSerge Pavlov     break;
126881350a9SSerge Pavlov   }
127881350a9SSerge Pavlov 
128881350a9SSerge Pavlov   return IID;
129881350a9SSerge Pavlov }
130881350a9SSerge Pavlov 
1318b52037cSSimon Pilgrim } // namespace llvm
132