//===- llvm/Support/KnownFPClass.h - Stores known fplcass -------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// // // This file contains a class for representing known fpclasses used by // computeKnownFPClass. // //===----------------------------------------------------------------------===// #include "llvm/Support/KnownFPClass.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; /// Return true if it's possible to assume IEEE treatment of input denormals in /// \p F for \p Val. static bool inputDenormalIsIEEE(DenormalMode Mode) { return Mode.Input == DenormalMode::IEEE; } static bool inputDenormalIsIEEEOrPosZero(DenormalMode Mode) { return Mode.Input == DenormalMode::IEEE || Mode.Input == DenormalMode::PositiveZero; } bool KnownFPClass::isKnownNeverLogicalZero(DenormalMode Mode) const { return isKnownNeverZero() && (isKnownNeverSubnormal() || inputDenormalIsIEEE(Mode)); } bool KnownFPClass::isKnownNeverLogicalNegZero(DenormalMode Mode) const { return isKnownNeverNegZero() && (isKnownNeverNegSubnormal() || inputDenormalIsIEEEOrPosZero(Mode)); } bool KnownFPClass::isKnownNeverLogicalPosZero(DenormalMode Mode) const { if (!isKnownNeverPosZero()) return false; // If we know there are no denormals, nothing can be flushed to zero. if (isKnownNeverSubnormal()) return true; switch (Mode.Input) { case DenormalMode::IEEE: return true; case DenormalMode::PreserveSign: // Negative subnormal won't flush to +0 return isKnownNeverPosSubnormal(); case DenormalMode::PositiveZero: default: // Both positive and negative subnormal could flush to +0 return false; } llvm_unreachable("covered switch over denormal mode"); } void KnownFPClass::propagateDenormal(const KnownFPClass &Src, DenormalMode Mode) { KnownFPClasses = Src.KnownFPClasses; // If we aren't assuming the source can't be a zero, we don't have to check if // a denormal input could be flushed. if (!Src.isKnownNeverPosZero() && !Src.isKnownNeverNegZero()) return; // If we know the input can't be a denormal, it can't be flushed to 0. if (Src.isKnownNeverSubnormal()) return; if (!Src.isKnownNeverPosSubnormal() && Mode != DenormalMode::getIEEE()) KnownFPClasses |= fcPosZero; if (!Src.isKnownNeverNegSubnormal() && Mode != DenormalMode::getIEEE()) { if (Mode != DenormalMode::getPositiveZero()) KnownFPClasses |= fcNegZero; if (Mode.Input == DenormalMode::PositiveZero || Mode.Output == DenormalMode::PositiveZero || Mode.Input == DenormalMode::Dynamic || Mode.Output == DenormalMode::Dynamic) KnownFPClasses |= fcPosZero; } } void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src, DenormalMode Mode) { propagateDenormal(Src, Mode); propagateNaN(Src, /*PreserveSign=*/true); }