1480093f4SDimitry Andric //===-- FPEnv.cpp ---- FP Environment -------------------------------------===// 2480093f4SDimitry Andric // 3480093f4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric // 7480093f4SDimitry Andric //===----------------------------------------------------------------------===// 8480093f4SDimitry Andric // 9480093f4SDimitry Andric /// @file 10480093f4SDimitry Andric /// This file contains the implementations of entities that describe floating 11480093f4SDimitry Andric /// point environment. 12480093f4SDimitry Andric // 13480093f4SDimitry Andric //===----------------------------------------------------------------------===// 14480093f4SDimitry Andric 15480093f4SDimitry Andric #include "llvm/IR/FPEnv.h" 165ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h" 17*81ad6265SDimitry Andric #include "llvm/IR/Instruction.h" 18*81ad6265SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 19*81ad6265SDimitry Andric #include "llvm/IR/Intrinsics.h" 20480093f4SDimitry Andric 21480093f4SDimitry Andric namespace llvm { 22480093f4SDimitry Andric 23349cc55cSDimitry Andric Optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) { 24480093f4SDimitry Andric // For dynamic rounding mode, we use round to nearest but we will set the 25480093f4SDimitry Andric // 'exact' SDNodeFlag so that the value will not be rounded. 265ffd83dbSDimitry Andric return StringSwitch<Optional<RoundingMode>>(RoundingArg) 275ffd83dbSDimitry Andric .Case("round.dynamic", RoundingMode::Dynamic) 285ffd83dbSDimitry Andric .Case("round.tonearest", RoundingMode::NearestTiesToEven) 295ffd83dbSDimitry Andric .Case("round.tonearestaway", RoundingMode::NearestTiesToAway) 305ffd83dbSDimitry Andric .Case("round.downward", RoundingMode::TowardNegative) 315ffd83dbSDimitry Andric .Case("round.upward", RoundingMode::TowardPositive) 325ffd83dbSDimitry Andric .Case("round.towardzero", RoundingMode::TowardZero) 33480093f4SDimitry Andric .Default(None); 34480093f4SDimitry Andric } 35480093f4SDimitry Andric 36349cc55cSDimitry Andric Optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) { 37480093f4SDimitry Andric Optional<StringRef> RoundingStr = None; 38480093f4SDimitry Andric switch (UseRounding) { 395ffd83dbSDimitry Andric case RoundingMode::Dynamic: 40480093f4SDimitry Andric RoundingStr = "round.dynamic"; 41480093f4SDimitry Andric break; 425ffd83dbSDimitry Andric case RoundingMode::NearestTiesToEven: 43480093f4SDimitry Andric RoundingStr = "round.tonearest"; 44480093f4SDimitry Andric break; 455ffd83dbSDimitry Andric case RoundingMode::NearestTiesToAway: 465ffd83dbSDimitry Andric RoundingStr = "round.tonearestaway"; 475ffd83dbSDimitry Andric break; 485ffd83dbSDimitry Andric case RoundingMode::TowardNegative: 49480093f4SDimitry Andric RoundingStr = "round.downward"; 50480093f4SDimitry Andric break; 515ffd83dbSDimitry Andric case RoundingMode::TowardPositive: 52480093f4SDimitry Andric RoundingStr = "round.upward"; 53480093f4SDimitry Andric break; 545ffd83dbSDimitry Andric case RoundingMode::TowardZero: 55480093f4SDimitry Andric RoundingStr = "round.towardzero"; 56480093f4SDimitry Andric break; 575ffd83dbSDimitry Andric default: 585ffd83dbSDimitry Andric break; 59480093f4SDimitry Andric } 60480093f4SDimitry Andric return RoundingStr; 61480093f4SDimitry Andric } 62480093f4SDimitry Andric 63349cc55cSDimitry Andric Optional<fp::ExceptionBehavior> 64349cc55cSDimitry Andric convertStrToExceptionBehavior(StringRef ExceptionArg) { 65480093f4SDimitry Andric return StringSwitch<Optional<fp::ExceptionBehavior>>(ExceptionArg) 66480093f4SDimitry Andric .Case("fpexcept.ignore", fp::ebIgnore) 67480093f4SDimitry Andric .Case("fpexcept.maytrap", fp::ebMayTrap) 68480093f4SDimitry Andric .Case("fpexcept.strict", fp::ebStrict) 69480093f4SDimitry Andric .Default(None); 70480093f4SDimitry Andric } 71480093f4SDimitry Andric 72349cc55cSDimitry Andric Optional<StringRef> 73349cc55cSDimitry Andric convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) { 74480093f4SDimitry Andric Optional<StringRef> ExceptStr = None; 75480093f4SDimitry Andric switch (UseExcept) { 76480093f4SDimitry Andric case fp::ebStrict: 77480093f4SDimitry Andric ExceptStr = "fpexcept.strict"; 78480093f4SDimitry Andric break; 79480093f4SDimitry Andric case fp::ebIgnore: 80480093f4SDimitry Andric ExceptStr = "fpexcept.ignore"; 81480093f4SDimitry Andric break; 82480093f4SDimitry Andric case fp::ebMayTrap: 83480093f4SDimitry Andric ExceptStr = "fpexcept.maytrap"; 84480093f4SDimitry Andric break; 85480093f4SDimitry Andric } 86480093f4SDimitry Andric return ExceptStr; 87480093f4SDimitry Andric } 88*81ad6265SDimitry Andric 89*81ad6265SDimitry Andric Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr) { 90*81ad6265SDimitry Andric Intrinsic::ID IID = Intrinsic::not_intrinsic; 91*81ad6265SDimitry Andric switch (Instr.getOpcode()) { 92*81ad6265SDimitry Andric case Instruction::FCmp: 93*81ad6265SDimitry Andric // Unlike other instructions FCmp can be mapped to one of two intrinsic 94*81ad6265SDimitry Andric // functions. We choose the non-signaling variant. 95*81ad6265SDimitry Andric IID = Intrinsic::experimental_constrained_fcmp; 96*81ad6265SDimitry Andric break; 97*81ad6265SDimitry Andric 98*81ad6265SDimitry Andric // Instructions 99*81ad6265SDimitry Andric #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 100*81ad6265SDimitry Andric case Instruction::NAME: \ 101*81ad6265SDimitry Andric IID = Intrinsic::INTRINSIC; \ 102*81ad6265SDimitry Andric break; 103*81ad6265SDimitry Andric #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) 104*81ad6265SDimitry Andric #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) 105*81ad6265SDimitry Andric #include "llvm/IR/ConstrainedOps.def" 106*81ad6265SDimitry Andric 107*81ad6265SDimitry Andric // Intrinsic calls. 108*81ad6265SDimitry Andric case Instruction::Call: 109*81ad6265SDimitry Andric if (auto *IntrinCall = dyn_cast<IntrinsicInst>(&Instr)) { 110*81ad6265SDimitry Andric switch (IntrinCall->getIntrinsicID()) { 111*81ad6265SDimitry Andric #define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ 112*81ad6265SDimitry Andric case Intrinsic::NAME: \ 113*81ad6265SDimitry Andric IID = Intrinsic::INTRINSIC; \ 114*81ad6265SDimitry Andric break; 115*81ad6265SDimitry Andric #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) 116*81ad6265SDimitry Andric #define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) 117*81ad6265SDimitry Andric #include "llvm/IR/ConstrainedOps.def" 118*81ad6265SDimitry Andric default: 119*81ad6265SDimitry Andric break; 120*81ad6265SDimitry Andric } 121*81ad6265SDimitry Andric } 122*81ad6265SDimitry Andric break; 123*81ad6265SDimitry Andric default: 124*81ad6265SDimitry Andric break; 125*81ad6265SDimitry Andric } 126*81ad6265SDimitry Andric 127*81ad6265SDimitry Andric return IID; 128*81ad6265SDimitry Andric } 129*81ad6265SDimitry Andric 1305ffd83dbSDimitry Andric } // namespace llvm 131