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. |
21 | static bool inputDenormalIsIEEE(DenormalMode Mode) { |
22 | return Mode.Input == DenormalMode::IEEE; |
23 | } |
24 | |
25 | static bool inputDenormalIsIEEEOrPosZero(DenormalMode Mode) { |
26 | return Mode.Input == DenormalMode::IEEE || |
27 | Mode.Input == DenormalMode::PositiveZero; |
28 | } |
29 | |
30 | bool KnownFPClass::isKnownNeverLogicalZero(DenormalMode Mode) const { |
31 | return isKnownNeverZero() && |
32 | (isKnownNeverSubnormal() || inputDenormalIsIEEE(Mode)); |
33 | } |
34 | |
35 | bool KnownFPClass::isKnownNeverLogicalNegZero(DenormalMode Mode) const { |
36 | return isKnownNeverNegZero() && |
37 | (isKnownNeverNegSubnormal() || inputDenormalIsIEEEOrPosZero(Mode)); |
38 | } |
39 | |
40 | 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 | |
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 | |
90 | void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src, |
91 | DenormalMode Mode) { |
92 | propagateDenormal(Src, Mode); |
93 | propagateNaN(Src, /*PreserveSign=*/true); |
94 | } |
95 |