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