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#include <optional> 21 22namespace llvm { 23 24std::optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) { 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. 27 return StringSwitch<std::optional<RoundingMode>>(RoundingArg) 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) 34 .Default(std::nullopt); 35} 36 37std::optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) { 38 std::optional<StringRef> RoundingStr; 39 switch (UseRounding) { 40 case RoundingMode::Dynamic: 41 RoundingStr = "round.dynamic"; 42 break; 43 case RoundingMode::NearestTiesToEven: 44 RoundingStr = "round.tonearest"; 45 break; 46 case RoundingMode::NearestTiesToAway: 47 RoundingStr = "round.tonearestaway"; 48 break; 49 case RoundingMode::TowardNegative: 50 RoundingStr = "round.downward"; 51 break; 52 case RoundingMode::TowardPositive: 53 RoundingStr = "round.upward"; 54 break; 55 case RoundingMode::TowardZero: 56 RoundingStr = "round.towardzero"; 57 break; 58 default: 59 break; 60 } 61 return RoundingStr; 62} 63 64std::optional<fp::ExceptionBehavior> 65convertStrToExceptionBehavior(StringRef ExceptionArg) { 66 return StringSwitch<std::optional<fp::ExceptionBehavior>>(ExceptionArg) 67 .Case("fpexcept.ignore", fp::ebIgnore) 68 .Case("fpexcept.maytrap", fp::ebMayTrap) 69 .Case("fpexcept.strict", fp::ebStrict) 70 .Default(std::nullopt); 71} 72 73std::optional<StringRef> 74convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) { 75 std::optional<StringRef> ExceptStr; 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} 89 90Intrinsic::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 131} // namespace llvm 132