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
17using namespace llvm;
18
19/// Return true if it's possible to assume IEEE treatment of input denormals in
20/// \p F for \p Val.
21static bool inputDenormalIsIEEE(DenormalMode Mode) {
22 return Mode.Input == DenormalMode::IEEE;
23}
24
25static bool inputDenormalIsIEEEOrPosZero(DenormalMode Mode) {
26 return Mode.Input == DenormalMode::IEEE ||
27 Mode.Input == DenormalMode::PositiveZero;
28}
29
30bool KnownFPClass::isKnownNeverLogicalZero(DenormalMode Mode) const {
31 return isKnownNeverZero() &&
32 (isKnownNeverSubnormal() || inputDenormalIsIEEE(Mode));
33}
34
35bool KnownFPClass::isKnownNeverLogicalNegZero(DenormalMode Mode) const {
36 return isKnownNeverNegZero() &&
37 (isKnownNeverNegSubnormal() || inputDenormalIsIEEEOrPosZero(Mode));
38}
39
40bool 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
63void 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
90void KnownFPClass::propagateCanonicalizingSrc(const KnownFPClass &Src,
91 DenormalMode Mode) {
92 propagateDenormal(Src, Mode);
93 propagateNaN(Src, /*PreserveSign=*/true);
94}
95