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