xref: /freebsd/contrib/llvm-project/llvm/lib/Support/KnownFPClass.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===- llvm/Support/KnownFPClass.h - Stores known fplcass -------*- C++ -*-===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This file contains a class for representing known fpclasses used by
10*700637cbSDimitry Andric // computeKnownFPClass.
11*700637cbSDimitry Andric //
12*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
13*700637cbSDimitry Andric 
14*700637cbSDimitry Andric #include "llvm/Support/KnownFPClass.h"
15*700637cbSDimitry Andric #include "llvm/Support/ErrorHandling.h"
16*700637cbSDimitry Andric 
17*700637cbSDimitry Andric using namespace llvm;
18*700637cbSDimitry Andric 
19*700637cbSDimitry Andric /// Return true if it's possible to assume IEEE treatment of input denormals in
20*700637cbSDimitry Andric /// \p F for \p Val.
inputDenormalIsIEEE(DenormalMode Mode)21*700637cbSDimitry Andric static bool inputDenormalIsIEEE(DenormalMode Mode) {
22*700637cbSDimitry Andric   return Mode.Input == DenormalMode::IEEE;
23*700637cbSDimitry Andric }
24*700637cbSDimitry Andric 
inputDenormalIsIEEEOrPosZero(DenormalMode Mode)25*700637cbSDimitry Andric static bool inputDenormalIsIEEEOrPosZero(DenormalMode Mode) {
26*700637cbSDimitry Andric   return Mode.Input == DenormalMode::IEEE ||
27*700637cbSDimitry Andric          Mode.Input == DenormalMode::PositiveZero;
28*700637cbSDimitry Andric }
29*700637cbSDimitry Andric 
isKnownNeverLogicalZero(DenormalMode Mode) const30*700637cbSDimitry Andric bool KnownFPClass::isKnownNeverLogicalZero(DenormalMode Mode) const {
31*700637cbSDimitry Andric   return isKnownNeverZero() &&
32*700637cbSDimitry Andric          (isKnownNeverSubnormal() || inputDenormalIsIEEE(Mode));
33*700637cbSDimitry Andric }
34*700637cbSDimitry Andric 
isKnownNeverLogicalNegZero(DenormalMode Mode) const35*700637cbSDimitry Andric bool KnownFPClass::isKnownNeverLogicalNegZero(DenormalMode Mode) const {
36*700637cbSDimitry Andric   return isKnownNeverNegZero() &&
37*700637cbSDimitry Andric          (isKnownNeverNegSubnormal() || inputDenormalIsIEEEOrPosZero(Mode));
38*700637cbSDimitry Andric }
39*700637cbSDimitry Andric 
isKnownNeverLogicalPosZero(DenormalMode Mode) const40*700637cbSDimitry Andric bool KnownFPClass::isKnownNeverLogicalPosZero(DenormalMode Mode) const {
41*700637cbSDimitry Andric   if (!isKnownNeverPosZero())
42*700637cbSDimitry Andric     return false;
43*700637cbSDimitry Andric 
44*700637cbSDimitry Andric   // If we know there are no denormals, nothing can be flushed to zero.
45*700637cbSDimitry Andric   if (isKnownNeverSubnormal())
46*700637cbSDimitry Andric     return true;
47*700637cbSDimitry Andric 
48*700637cbSDimitry Andric   switch (Mode.Input) {
49*700637cbSDimitry Andric   case DenormalMode::IEEE:
50*700637cbSDimitry Andric     return true;
51*700637cbSDimitry Andric   case DenormalMode::PreserveSign:
52*700637cbSDimitry Andric     // Negative subnormal won't flush to +0
53*700637cbSDimitry Andric     return isKnownNeverPosSubnormal();
54*700637cbSDimitry Andric   case DenormalMode::PositiveZero:
55*700637cbSDimitry Andric   default:
56*700637cbSDimitry Andric     // Both positive and negative subnormal could flush to +0
57*700637cbSDimitry Andric     return false;
58*700637cbSDimitry Andric   }
59*700637cbSDimitry Andric 
60*700637cbSDimitry Andric   llvm_unreachable("covered switch over denormal mode");
61*700637cbSDimitry Andric }
62*700637cbSDimitry Andric 
propagateDenormal(const KnownFPClass & Src,DenormalMode Mode)63*700637cbSDimitry Andric void KnownFPClass::propagateDenormal(const KnownFPClass &Src,
64*700637cbSDimitry Andric                                      DenormalMode Mode) {
65*700637cbSDimitry Andric   KnownFPClasses = Src.KnownFPClasses;
66*700637cbSDimitry Andric   // If we aren't assuming the source can't be a zero, we don't have to check if
67*700637cbSDimitry Andric   // a denormal input could be flushed.
68*700637cbSDimitry Andric   if (!Src.isKnownNeverPosZero() && !Src.isKnownNeverNegZero())
69*700637cbSDimitry Andric     return;
70*700637cbSDimitry Andric 
71*700637cbSDimitry Andric   // If we know the input can't be a denormal, it can't be flushed to 0.
72*700637cbSDimitry Andric   if (Src.isKnownNeverSubnormal())
73*700637cbSDimitry Andric     return;
74*700637cbSDimitry Andric 
75*700637cbSDimitry Andric   if (!Src.isKnownNeverPosSubnormal() && Mode != DenormalMode::getIEEE())
76*700637cbSDimitry Andric     KnownFPClasses |= fcPosZero;
77*700637cbSDimitry Andric 
78*700637cbSDimitry Andric   if (!Src.isKnownNeverNegSubnormal() && Mode != DenormalMode::getIEEE()) {
79*700637cbSDimitry Andric     if (Mode != DenormalMode::getPositiveZero())
80*700637cbSDimitry Andric       KnownFPClasses |= fcNegZero;
81*700637cbSDimitry Andric 
82*700637cbSDimitry Andric     if (Mode.Input == DenormalMode::PositiveZero ||
83*700637cbSDimitry Andric         Mode.Output == DenormalMode::PositiveZero ||
84*700637cbSDimitry Andric         Mode.Input == DenormalMode::Dynamic ||
85*700637cbSDimitry Andric         Mode.Output == DenormalMode::Dynamic)
86*700637cbSDimitry Andric       KnownFPClasses |= fcPosZero;
87*700637cbSDimitry Andric   }
88*700637cbSDimitry Andric }
89*700637cbSDimitry Andric 
propagateCanonicalizingSrc(const KnownFPClass & Src,DenormalMode Mode)90*700637cbSDimitry Andric void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
91*700637cbSDimitry Andric                                               DenormalMode Mode) {
92*700637cbSDimitry Andric   propagateDenormal(Src, Mode);
93*700637cbSDimitry Andric   propagateNaN(Src, /*PreserveSign=*/true);
94*700637cbSDimitry Andric }
95