| //===- 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); |
| } |