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 22 namespace llvm { 23 24 std::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 37 std::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 64 std::optional<fp::ExceptionBehavior> 65 convertStrToExceptionBehavior(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 73 std::optional<StringRef> 74 convertExceptionBehaviorToStr(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 90 Intrinsic::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