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