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 21 namespace llvm { 22 23 Optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) { 24 // For dynamic rounding mode, we use round to nearest but we will set the 25 // 'exact' SDNodeFlag so that the value will not be rounded. 26 return StringSwitch<Optional<RoundingMode>>(RoundingArg) 27 .Case("round.dynamic", RoundingMode::Dynamic) 28 .Case("round.tonearest", RoundingMode::NearestTiesToEven) 29 .Case("round.tonearestaway", RoundingMode::NearestTiesToAway) 30 .Case("round.downward", RoundingMode::TowardNegative) 31 .Case("round.upward", RoundingMode::TowardPositive) 32 .Case("round.towardzero", RoundingMode::TowardZero) 33 .Default(None); 34 } 35 36 Optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) { 37 Optional<StringRef> RoundingStr = None; 38 switch (UseRounding) { 39 case RoundingMode::Dynamic: 40 RoundingStr = "round.dynamic"; 41 break; 42 case RoundingMode::NearestTiesToEven: 43 RoundingStr = "round.tonearest"; 44 break; 45 case RoundingMode::NearestTiesToAway: 46 RoundingStr = "round.tonearestaway"; 47 break; 48 case RoundingMode::TowardNegative: 49 RoundingStr = "round.downward"; 50 break; 51 case RoundingMode::TowardPositive: 52 RoundingStr = "round.upward"; 53 break; 54 case RoundingMode::TowardZero: 55 RoundingStr = "round.towardzero"; 56 break; 57 default: 58 break; 59 } 60 return RoundingStr; 61 } 62 63 Optional<fp::ExceptionBehavior> 64 convertStrToExceptionBehavior(StringRef ExceptionArg) { 65 return StringSwitch<Optional<fp::ExceptionBehavior>>(ExceptionArg) 66 .Case("fpexcept.ignore", fp::ebIgnore) 67 .Case("fpexcept.maytrap", fp::ebMayTrap) 68 .Case("fpexcept.strict", fp::ebStrict) 69 .Default(None); 70 } 71 72 Optional<StringRef> 73 convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) { 74 Optional<StringRef> ExceptStr = None; 75 switch (UseExcept) { 76 case fp::ebStrict: 77 ExceptStr = "fpexcept.strict"; 78 break; 79 case fp::ebIgnore: 80 ExceptStr = "fpexcept.ignore"; 81 break; 82 case fp::ebMayTrap: 83 ExceptStr = "fpexcept.maytrap"; 84 break; 85 } 86 return ExceptStr; 87 } 88 89 Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr) { 90 Intrinsic::ID IID = Intrinsic::not_intrinsic; 91 switch (Instr.getOpcode()) { 92 case Instruction::FCmp: 93 // Unlike other instructions FCmp can be mapped to one of two intrinsic 94 // functions. We choose the non-signaling variant. 95 IID = Intrinsic::experimental_constrained_fcmp; 96 break; 97 98 // Instructions 99 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 100 case Instruction::NAME: \ 101 IID = Intrinsic::INTRINSIC; \ 102 break; 103 #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) 104 #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) 105 #include "llvm/IR/ConstrainedOps.def" 106 107 // Intrinsic calls. 108 case Instruction::Call: 109 if (auto *IntrinCall = dyn_cast<IntrinsicInst>(&Instr)) { 110 switch (IntrinCall->getIntrinsicID()) { 111 #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 112 case Intrinsic::NAME: \ 113 IID = Intrinsic::INTRINSIC; \ 114 break; 115 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) 116 #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) 117 #include "llvm/IR/ConstrainedOps.def" 118 default: 119 break; 120 } 121 } 122 break; 123 default: 124 break; 125 } 126 127 return IID; 128 } 129 130 } // namespace llvm 131