brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · f3e38eb Raw
175 lines · cpp
1//===- APFloatWrappers.cpp - Software Implementation of FP Arithmetics --- ===//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// This file exposes the APFloat infrastructure to MLIR programs as a runtime10// library. APFloat is a software implementation of floating point arithmetics.11//12// On the MLIR side, floating-point values must be bitcasted to 64-bit integers13// before calling a runtime function. If a floating-point type has less than14// 64 bits, it must be zero-extended to 64 bits after bitcasting it to an15// integer.16//17// Runtime functions receive the floating-point operands of the arithmeic18// operation in the form of 64-bit integers, along with the APFloat semantics19// in the form of a 32-bit integer, which will be interpreted as an20// APFloatBase::Semantics enum value.21//22#include "llvm/ADT/APFloat.h"23#include "llvm/ADT/APSInt.h"24 25#ifdef _WIN3226#ifndef MLIR_APFLOAT_WRAPPERS_EXPORT27#ifdef mlir_apfloat_wrappers_EXPORTS28// We are building this library29#define MLIR_APFLOAT_WRAPPERS_EXPORT __declspec(dllexport)30#else31// We are using this library32#define MLIR_APFLOAT_WRAPPERS_EXPORT __declspec(dllimport)33#endif // mlir_apfloat_wrappers_EXPORTS34#endif // MLIR_APFLOAT_WRAPPERS_EXPORT35#else36// Non-windows: use visibility attributes.37#define MLIR_APFLOAT_WRAPPERS_EXPORT __attribute__((visibility("default")))38#endif // _WIN3239 40/// Binary operations without rounding mode.41#define APFLOAT_BINARY_OP(OP)                                                  \42  MLIR_APFLOAT_WRAPPERS_EXPORT int64_t _mlir_apfloat_##OP(                     \43      int32_t semantics, uint64_t a, uint64_t b) {                             \44    const llvm::fltSemantics &sem = llvm::APFloatBase::EnumToSemantics(        \45        static_cast<llvm::APFloatBase::Semantics>(semantics));                 \46    unsigned bitWidth = llvm::APFloatBase::semanticsSizeInBits(sem);           \47    llvm::APFloat lhs(sem, llvm::APInt(bitWidth, a));                          \48    llvm::APFloat rhs(sem, llvm::APInt(bitWidth, b));                          \49    lhs.OP(rhs);                                                               \50    return lhs.bitcastToAPInt().getZExtValue();                                \51  }52 53/// Binary operations with rounding mode.54#define APFLOAT_BINARY_OP_ROUNDING_MODE(OP, ROUNDING_MODE)                     \55  MLIR_APFLOAT_WRAPPERS_EXPORT uint64_t _mlir_apfloat_##OP(                    \56      int32_t semantics, uint64_t a, uint64_t b) {                             \57    const llvm::fltSemantics &sem = llvm::APFloatBase::EnumToSemantics(        \58        static_cast<llvm::APFloatBase::Semantics>(semantics));                 \59    unsigned bitWidth = llvm::APFloatBase::semanticsSizeInBits(sem);           \60    llvm::APFloat lhs(sem, llvm::APInt(bitWidth, a));                          \61    llvm::APFloat rhs(sem, llvm::APInt(bitWidth, b));                          \62    lhs.OP(rhs, ROUNDING_MODE);                                                \63    return lhs.bitcastToAPInt().getZExtValue();                                \64  }65 66extern "C" {67 68#define BIN_OPS_WITH_ROUNDING(X)                                               \69  X(add, llvm::RoundingMode::NearestTiesToEven)                                \70  X(subtract, llvm::RoundingMode::NearestTiesToEven)                           \71  X(multiply, llvm::RoundingMode::NearestTiesToEven)                           \72  X(divide, llvm::RoundingMode::NearestTiesToEven)73 74BIN_OPS_WITH_ROUNDING(APFLOAT_BINARY_OP_ROUNDING_MODE)75#undef BIN_OPS_WITH_ROUNDING76#undef APFLOAT_BINARY_OP_ROUNDING_MODE77 78APFLOAT_BINARY_OP(remainder)79 80#undef APFLOAT_BINARY_OP81 82MLIR_APFLOAT_WRAPPERS_EXPORT void printApFloat(int32_t semantics, uint64_t a) {83  const llvm::fltSemantics &sem = llvm::APFloatBase::EnumToSemantics(84      static_cast<llvm::APFloatBase::Semantics>(semantics));85  unsigned bitWidth = llvm::APFloatBase::semanticsSizeInBits(sem);86  llvm::APFloat x(sem, llvm::APInt(bitWidth, a));87  double d = x.convertToDouble();88  fprintf(stdout, "%lg", d);89}90 91MLIR_APFLOAT_WRAPPERS_EXPORT uint64_t92_mlir_apfloat_convert(int32_t inSemantics, int32_t outSemantics, uint64_t a) {93  const llvm::fltSemantics &inSem = llvm::APFloatBase::EnumToSemantics(94      static_cast<llvm::APFloatBase::Semantics>(inSemantics));95  const llvm::fltSemantics &outSem = llvm::APFloatBase::EnumToSemantics(96      static_cast<llvm::APFloatBase::Semantics>(outSemantics));97  unsigned bitWidthIn = llvm::APFloatBase::semanticsSizeInBits(inSem);98  llvm::APFloat val(inSem, llvm::APInt(bitWidthIn, a));99  // TODO: Custom rounding modes are not supported yet.100  bool losesInfo;101  val.convert(outSem, llvm::RoundingMode::NearestTiesToEven, &losesInfo);102  llvm::APInt result = val.bitcastToAPInt();103  return result.getZExtValue();104}105 106MLIR_APFLOAT_WRAPPERS_EXPORT uint64_t _mlir_apfloat_convert_to_int(107    int32_t semantics, int32_t resultWidth, bool isUnsigned, uint64_t a) {108  const llvm::fltSemantics &sem = llvm::APFloatBase::EnumToSemantics(109      static_cast<llvm::APFloatBase::Semantics>(semantics));110  unsigned inputWidth = llvm::APFloatBase::semanticsSizeInBits(sem);111  llvm::APFloat val(sem, llvm::APInt(inputWidth, a));112  llvm::APSInt result(resultWidth, isUnsigned);113  bool isExact;114  // TODO: Custom rounding modes are not supported yet.115  val.convertToInteger(result, llvm::RoundingMode::NearestTiesToEven, &isExact);116  // This function always returns uint64_t, regardless of the desired result117  // width. It does not matter whether we zero-extend or sign-extend the APSInt118  // to 64 bits because the generated IR in arith-to-apfloat will truncate the119  // result to the desired result width.120  return result.getZExtValue();121}122 123MLIR_APFLOAT_WRAPPERS_EXPORT uint64_t _mlir_apfloat_convert_from_int(124    int32_t semantics, int32_t inputWidth, bool isUnsigned, uint64_t a) {125  llvm::APInt val(inputWidth, a, /*isSigned=*/!isUnsigned);126  const llvm::fltSemantics &sem = llvm::APFloatBase::EnumToSemantics(127      static_cast<llvm::APFloatBase::Semantics>(semantics));128  llvm::APFloat result(sem);129  // TODO: Custom rounding modes are not supported yet.130  result.convertFromAPInt(val, /*IsSigned=*/!isUnsigned,131                          llvm::RoundingMode::NearestTiesToEven);132  return result.bitcastToAPInt().getZExtValue();133}134 135MLIR_APFLOAT_WRAPPERS_EXPORT int8_t _mlir_apfloat_compare(int32_t semantics,136                                                          uint64_t a,137                                                          uint64_t b) {138  const llvm::fltSemantics &sem = llvm::APFloatBase::EnumToSemantics(139      static_cast<llvm::APFloatBase::Semantics>(semantics));140  unsigned bitWidth = llvm::APFloatBase::semanticsSizeInBits(sem);141  llvm::APFloat x(sem, llvm::APInt(bitWidth, a));142  llvm::APFloat y(sem, llvm::APInt(bitWidth, b));143  return static_cast<int8_t>(x.compare(y));144}145 146MLIR_APFLOAT_WRAPPERS_EXPORT uint64_t _mlir_apfloat_neg(int32_t semantics, uint64_t a) {147  const llvm::fltSemantics &sem = llvm::APFloatBase::EnumToSemantics(148      static_cast<llvm::APFloatBase::Semantics>(semantics));149  unsigned bitWidth = llvm::APFloatBase::semanticsSizeInBits(sem);150  llvm::APFloat x(sem, llvm::APInt(bitWidth, a));151  x.changeSign();152  return x.bitcastToAPInt().getZExtValue();153}154 155/// Min/max operations.156#define APFLOAT_MIN_MAX_OP(OP)                                                 \157  MLIR_APFLOAT_WRAPPERS_EXPORT uint64_t _mlir_apfloat_##OP(                    \158      int32_t semantics, uint64_t a, uint64_t b) {                             \159    const llvm::fltSemantics &sem = llvm::APFloatBase::EnumToSemantics(        \160        static_cast<llvm::APFloatBase::Semantics>(semantics));                 \161    unsigned bitWidth = llvm::APFloatBase::semanticsSizeInBits(sem);           \162    llvm::APFloat lhs(sem, llvm::APInt(bitWidth, a));                          \163    llvm::APFloat rhs(sem, llvm::APInt(bitWidth, b));                          \164    llvm::APFloat result = llvm::OP(lhs, rhs);                                 \165    return result.bitcastToAPInt().getZExtValue();                             \166  }167 168APFLOAT_MIN_MAX_OP(minimum)169APFLOAT_MIN_MAX_OP(maximum)170APFLOAT_MIN_MAX_OP(minnum)171APFLOAT_MIN_MAX_OP(maxnum)172 173#undef APFLOAT_MIN_MAX_OP174}175