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