llvm-project/llvm/lib/IR/FPEnv.cpp
Serge Pavlov 881350a92d Mapping of FP operations to constrained intrinsics
A new function 'getConstrainedIntrinsic' is added, which for any gived
instruction returns id of the corresponding constrained intrinsic. If
there is no constrained counterpart for the instruction or the instruction
is already a constrained intrinsic, the function returns zero.

This is recommit of 115b3ace369254f573ca28934ef30ab9d8f497ef, reverted in
8160dd582b67430a5c24c836a57ae3c15cfa973c.

Differential Revision: https://reviews.llvm.org/D69562
2022-03-31 11:07:47 +07:00

131 lines
4.2 KiB
C++

//===-- FPEnv.cpp ---- FP Environment -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// @file
/// This file contains the implementations of entities that describe floating
/// point environment.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/FPEnv.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
namespace llvm {
Optional<RoundingMode> convertStrToRoundingMode(StringRef RoundingArg) {
// For dynamic rounding mode, we use round to nearest but we will set the
// 'exact' SDNodeFlag so that the value will not be rounded.
return StringSwitch<Optional<RoundingMode>>(RoundingArg)
.Case("round.dynamic", RoundingMode::Dynamic)
.Case("round.tonearest", RoundingMode::NearestTiesToEven)
.Case("round.tonearestaway", RoundingMode::NearestTiesToAway)
.Case("round.downward", RoundingMode::TowardNegative)
.Case("round.upward", RoundingMode::TowardPositive)
.Case("round.towardzero", RoundingMode::TowardZero)
.Default(None);
}
Optional<StringRef> convertRoundingModeToStr(RoundingMode UseRounding) {
Optional<StringRef> RoundingStr = None;
switch (UseRounding) {
case RoundingMode::Dynamic:
RoundingStr = "round.dynamic";
break;
case RoundingMode::NearestTiesToEven:
RoundingStr = "round.tonearest";
break;
case RoundingMode::NearestTiesToAway:
RoundingStr = "round.tonearestaway";
break;
case RoundingMode::TowardNegative:
RoundingStr = "round.downward";
break;
case RoundingMode::TowardPositive:
RoundingStr = "round.upward";
break;
case RoundingMode::TowardZero:
RoundingStr = "round.towardzero";
break;
default:
break;
}
return RoundingStr;
}
Optional<fp::ExceptionBehavior>
convertStrToExceptionBehavior(StringRef ExceptionArg) {
return StringSwitch<Optional<fp::ExceptionBehavior>>(ExceptionArg)
.Case("fpexcept.ignore", fp::ebIgnore)
.Case("fpexcept.maytrap", fp::ebMayTrap)
.Case("fpexcept.strict", fp::ebStrict)
.Default(None);
}
Optional<StringRef>
convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) {
Optional<StringRef> ExceptStr = None;
switch (UseExcept) {
case fp::ebStrict:
ExceptStr = "fpexcept.strict";
break;
case fp::ebIgnore:
ExceptStr = "fpexcept.ignore";
break;
case fp::ebMayTrap:
ExceptStr = "fpexcept.maytrap";
break;
}
return ExceptStr;
}
Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr) {
Intrinsic::ID IID = Intrinsic::not_intrinsic;
switch (Instr.getOpcode()) {
case Instruction::FCmp:
// Unlike other instructions FCmp can be mapped to one of two intrinsic
// functions. We choose the non-signaling variant.
IID = Intrinsic::experimental_constrained_fcmp;
break;
// Instructions
#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
case Instruction::NAME: \
IID = Intrinsic::INTRINSIC; \
break;
#define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
#define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
#include "llvm/IR/ConstrainedOps.def"
// Intrinsic calls.
case Instruction::Call:
if (auto *IntrinCall = dyn_cast<IntrinsicInst>(&Instr)) {
switch (IntrinCall->getIntrinsicID()) {
#define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
case Intrinsic::NAME: \
IID = Intrinsic::INTRINSIC; \
break;
#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
#define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
#include "llvm/IR/ConstrainedOps.def"
default:
break;
}
}
break;
default:
break;
}
return IID;
}
} // namespace llvm