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