|
| 1 | +//===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===// |
| 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 | +#include "llvm/IR/ConstantFPRange.h" |
| 10 | +#include "llvm/ADT/BitVector.h" |
| 11 | +#include "llvm/ADT/Sequence.h" |
| 12 | +#include "llvm/ADT/SmallBitVector.h" |
| 13 | +#include "llvm/Analysis/ValueTracking.h" |
| 14 | +#include "llvm/IR/Instructions.h" |
| 15 | +#include "llvm/IR/Operator.h" |
| 16 | +#include "llvm/Support/KnownBits.h" |
| 17 | +#include "gtest/gtest.h" |
| 18 | + |
| 19 | +using namespace llvm; |
| 20 | + |
| 21 | +namespace { |
| 22 | + |
| 23 | +class ConstantFPRangeTest : public ::testing::Test { |
| 24 | +protected: |
| 25 | + static const fltSemantics &Sem; |
| 26 | + static ConstantFPRange Full; |
| 27 | + static ConstantFPRange Empty; |
| 28 | + static ConstantFPRange Finite; |
| 29 | + static ConstantFPRange One; |
| 30 | + static ConstantFPRange PosZero; |
| 31 | + static ConstantFPRange NegZero; |
| 32 | + static ConstantFPRange Zero; |
| 33 | + static ConstantFPRange PosInf; |
| 34 | + static ConstantFPRange NegInf; |
| 35 | + static ConstantFPRange Denormal; |
| 36 | + static ConstantFPRange NaN; |
| 37 | + static ConstantFPRange SNaN; |
| 38 | + static ConstantFPRange QNaN; |
| 39 | + static ConstantFPRange Some; |
| 40 | + static ConstantFPRange SomePos; |
| 41 | + static ConstantFPRange SomeNeg; |
| 42 | +}; |
| 43 | + |
| 44 | +const fltSemantics &ConstantFPRangeTest::Sem = APFloat::IEEEdouble(); |
| 45 | +ConstantFPRange ConstantFPRangeTest::Full = |
| 46 | + ConstantFPRange::getFull(APFloat::IEEEdouble()); |
| 47 | +ConstantFPRange ConstantFPRangeTest::Empty = |
| 48 | + ConstantFPRange::getEmpty(APFloat::IEEEdouble()); |
| 49 | +ConstantFPRange ConstantFPRangeTest::Finite = |
| 50 | + ConstantFPRange::getFinite(APFloat::IEEEdouble()); |
| 51 | +ConstantFPRange ConstantFPRangeTest::One = ConstantFPRange(APFloat(1.0)); |
| 52 | +ConstantFPRange ConstantFPRangeTest::PosZero = ConstantFPRange( |
| 53 | + APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/false)); |
| 54 | +ConstantFPRange ConstantFPRangeTest::NegZero = |
| 55 | + ConstantFPRange(APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/true)); |
| 56 | +ConstantFPRange ConstantFPRangeTest::Zero = ConstantFPRange::getNonNaN( |
| 57 | + APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/true), |
| 58 | + APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/false)); |
| 59 | +ConstantFPRange ConstantFPRangeTest::Denormal = |
| 60 | + ConstantFPRange(APFloat::getSmallest(APFloat::IEEEdouble())); |
| 61 | +ConstantFPRange ConstantFPRangeTest::PosInf = |
| 62 | + ConstantFPRange(APFloat::getInf(APFloat::IEEEdouble(), /*Negative=*/false)); |
| 63 | +ConstantFPRange ConstantFPRangeTest::NegInf = |
| 64 | + ConstantFPRange(APFloat::getInf(APFloat::IEEEdouble(), /*Negative=*/true)); |
| 65 | +ConstantFPRange ConstantFPRangeTest::NaN = |
| 66 | + ConstantFPRange(APFloat(1.0), APFloat(-1.0)); |
| 67 | +ConstantFPRange ConstantFPRangeTest::SNaN = |
| 68 | + ConstantFPRange(APFloat::getSNaN(APFloat::IEEEdouble())); |
| 69 | +ConstantFPRange ConstantFPRangeTest::QNaN = |
| 70 | + ConstantFPRange(APFloat::getQNaN(APFloat::IEEEdouble())); |
| 71 | +ConstantFPRange ConstantFPRangeTest::Some = |
| 72 | + ConstantFPRange::getNonNaN(APFloat(-3.0), APFloat(3.0)); |
| 73 | +ConstantFPRange ConstantFPRangeTest::SomePos = ConstantFPRange::getNonNaN( |
| 74 | + APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/false), APFloat(3.0)); |
| 75 | +ConstantFPRange ConstantFPRangeTest::SomeNeg = ConstantFPRange::getNonNaN( |
| 76 | + APFloat(-3.0), APFloat::getZero(APFloat::IEEEdouble(), /*Negative=*/true)); |
| 77 | + |
| 78 | +TEST_F(ConstantFPRangeTest, Basics) { |
| 79 | + EXPECT_TRUE(Full.isFullSet()); |
| 80 | + EXPECT_FALSE(Full.isEmptySet()); |
| 81 | + EXPECT_TRUE(Full.contains(APFloat::getNaN(Sem))); |
| 82 | + EXPECT_TRUE(Full.contains(APFloat::getInf(Sem, /*Negative=*/false))); |
| 83 | + EXPECT_TRUE(Full.contains(APFloat::getInf(Sem, /*Negative=*/true))); |
| 84 | + EXPECT_TRUE(Full.contains(APFloat::getZero(Sem, /*Negative=*/false))); |
| 85 | + EXPECT_TRUE(Full.contains(APFloat::getZero(Sem, /*Negative=*/true))); |
| 86 | + EXPECT_TRUE(Full.contains(APFloat::getSmallest(Sem))); |
| 87 | + EXPECT_TRUE(Full.contains(APFloat(2.0))); |
| 88 | + EXPECT_TRUE(Full.contains(Full)); |
| 89 | + EXPECT_TRUE(Full.contains(Empty)); |
| 90 | + EXPECT_TRUE(Full.contains(Finite)); |
| 91 | + EXPECT_TRUE(Full.contains(Zero)); |
| 92 | + EXPECT_TRUE(Full.contains(Some)); |
| 93 | + |
| 94 | + EXPECT_FALSE(Empty.isFullSet()); |
| 95 | + EXPECT_TRUE(Empty.isEmptySet()); |
| 96 | + EXPECT_FALSE(Empty.contains(APFloat::getNaN(Sem))); |
| 97 | + EXPECT_FALSE(Empty.contains(APFloat::getInf(Sem, /*Negative=*/false))); |
| 98 | + EXPECT_FALSE(Empty.contains(APFloat::getZero(Sem, /*Negative=*/true))); |
| 99 | + EXPECT_FALSE(Empty.contains(APFloat(2.0))); |
| 100 | + EXPECT_TRUE(Empty.contains(Empty)); |
| 101 | + |
| 102 | + EXPECT_FALSE(Finite.isFullSet()); |
| 103 | + EXPECT_FALSE(Finite.isEmptySet()); |
| 104 | + EXPECT_FALSE(Finite.contains(APFloat::getNaN(Sem))); |
| 105 | + EXPECT_FALSE(Finite.contains(APFloat::getInf(Sem, /*Negative=*/false))); |
| 106 | + EXPECT_FALSE(Finite.contains(APFloat::getInf(Sem, /*Negative=*/true))); |
| 107 | + EXPECT_TRUE(Finite.contains(APFloat::getLargest(Sem, /*Negative=*/false))); |
| 108 | + EXPECT_TRUE(Finite.contains(APFloat::getLargest(Sem, /*Negative=*/true))); |
| 109 | + EXPECT_TRUE(Finite.contains(Finite)); |
| 110 | + EXPECT_TRUE(Finite.contains(Some)); |
| 111 | + EXPECT_TRUE(Finite.contains(Denormal)); |
| 112 | + EXPECT_TRUE(Finite.contains(Zero)); |
| 113 | + EXPECT_FALSE(Finite.contains(PosInf)); |
| 114 | + EXPECT_FALSE(Finite.contains(NaN)); |
| 115 | + |
| 116 | + EXPECT_TRUE(One.contains(APFloat(1.0))); |
| 117 | + EXPECT_FALSE(One.contains(APFloat(1.1))); |
| 118 | + |
| 119 | + EXPECT_TRUE(PosZero.contains(APFloat::getZero(Sem, /*Negative=*/false))); |
| 120 | + EXPECT_FALSE(PosZero.contains(APFloat::getZero(Sem, /*Negative=*/true))); |
| 121 | + EXPECT_TRUE(NegZero.contains(APFloat::getZero(Sem, /*Negative=*/true))); |
| 122 | + EXPECT_FALSE(NegZero.contains(APFloat::getZero(Sem, /*Negative=*/false))); |
| 123 | + EXPECT_TRUE(Zero.contains(PosZero)); |
| 124 | + EXPECT_TRUE(Zero.contains(NegZero)); |
| 125 | + EXPECT_TRUE(Denormal.contains(APFloat::getSmallest(Sem))); |
| 126 | + EXPECT_FALSE(Denormal.contains(APFloat::getSmallestNormalized(Sem))); |
| 127 | + EXPECT_TRUE(PosInf.contains(APFloat::getInf(Sem, /*Negative=*/false))); |
| 128 | + EXPECT_TRUE(NegInf.contains(APFloat::getInf(Sem, /*Negative=*/true))); |
| 129 | + EXPECT_TRUE(NaN.contains(APFloat::getQNaN(Sem))); |
| 130 | + EXPECT_TRUE(NaN.contains(APFloat::getSNaN(Sem))); |
| 131 | + EXPECT_TRUE(NaN.contains(SNaN)); |
| 132 | + EXPECT_TRUE(NaN.contains(QNaN)); |
| 133 | + |
| 134 | + EXPECT_TRUE(Some.contains(APFloat(3.0))); |
| 135 | + EXPECT_TRUE(Some.contains(APFloat(-3.0))); |
| 136 | + EXPECT_FALSE(Some.contains(APFloat(4.0))); |
| 137 | + APFloat Next1(3.0); |
| 138 | + Next1.next(/*nextDown=*/true); |
| 139 | + EXPECT_TRUE(Some.contains(Next1)); |
| 140 | + APFloat Next2(3.0); |
| 141 | + Next2.next(/*nextDown=*/false); |
| 142 | + EXPECT_FALSE(Some.contains(Next2)); |
| 143 | + EXPECT_TRUE(Some.contains(Zero)); |
| 144 | + EXPECT_TRUE(Some.contains(Some)); |
| 145 | + EXPECT_TRUE(Some.contains(One)); |
| 146 | + EXPECT_FALSE(Some.contains(NaN)); |
| 147 | + EXPECT_FALSE(Some.contains(PosInf)); |
| 148 | + EXPECT_TRUE(SomePos.contains(APFloat(3.0))); |
| 149 | + EXPECT_FALSE(SomeNeg.contains(APFloat(3.0))); |
| 150 | + EXPECT_TRUE(SomeNeg.contains(APFloat(-3.0))); |
| 151 | + EXPECT_FALSE(SomePos.contains(APFloat(-3.0))); |
| 152 | + EXPECT_TRUE(Some.contains(SomePos)); |
| 153 | + EXPECT_TRUE(Some.contains(SomeNeg)); |
| 154 | +} |
| 155 | + |
| 156 | +TEST_F(ConstantFPRangeTest, Equality) { |
| 157 | + EXPECT_EQ(Full, Full); |
| 158 | + EXPECT_EQ(Empty, Empty); |
| 159 | + EXPECT_EQ(One, One); |
| 160 | + EXPECT_EQ(Some, Some); |
| 161 | + EXPECT_NE(Full, Empty); |
| 162 | + EXPECT_NE(Zero, PosZero); |
| 163 | + EXPECT_NE(One, NaN); |
| 164 | + EXPECT_NE(Some, One); |
| 165 | + EXPECT_NE(SNaN, QNaN); |
| 166 | +} |
| 167 | + |
| 168 | +TEST_F(ConstantFPRangeTest, SingleElement) { |
| 169 | + EXPECT_EQ(Full.getSingleElement(), static_cast<APFloat *>(nullptr)); |
| 170 | + EXPECT_EQ(Empty.getSingleElement(), static_cast<APFloat *>(nullptr)); |
| 171 | + EXPECT_EQ(Finite.getSingleElement(), static_cast<APFloat *>(nullptr)); |
| 172 | + EXPECT_EQ(Zero.getSingleElement(), static_cast<APFloat *>(nullptr)); |
| 173 | + EXPECT_EQ(NaN.getSingleElement(), static_cast<APFloat *>(nullptr)); |
| 174 | + EXPECT_EQ(SNaN.getSingleElement(), static_cast<APFloat *>(nullptr)); |
| 175 | + EXPECT_EQ(QNaN.getSingleElement(), static_cast<APFloat *>(nullptr)); |
| 176 | + |
| 177 | + EXPECT_EQ(*One.getSingleElement(), APFloat(1.0)); |
| 178 | + EXPECT_EQ(*PosZero.getSingleElement(), APFloat::getZero(Sem)); |
| 179 | + EXPECT_EQ(*PosInf.getSingleElement(), APFloat::getInf(Sem)); |
| 180 | + |
| 181 | + EXPECT_FALSE(Full.isSingleElement()); |
| 182 | + EXPECT_FALSE(Empty.isSingleElement()); |
| 183 | + EXPECT_TRUE(One.isSingleElement()); |
| 184 | + EXPECT_FALSE(Some.isSingleElement()); |
| 185 | + EXPECT_FALSE(Zero.isSingleElement()); |
| 186 | +} |
| 187 | + |
| 188 | +TEST_F(ConstantFPRangeTest, IntersectWith) { |
| 189 | + EXPECT_EQ(Empty.intersectWith(Full), Empty); |
| 190 | + EXPECT_EQ(Empty.intersectWith(Empty), Empty); |
| 191 | + EXPECT_EQ(Empty.intersectWith(One), Empty); |
| 192 | + EXPECT_EQ(Empty.intersectWith(Some), Empty); |
| 193 | + EXPECT_EQ(Full.intersectWith(Full), Full); |
| 194 | + EXPECT_EQ(Some.intersectWith(Some), Some); |
| 195 | + EXPECT_EQ(Some.intersectWith(One), One); |
| 196 | + EXPECT_EQ(Full.intersectWith(One), One); |
| 197 | + EXPECT_EQ(Full.intersectWith(Some), Some); |
| 198 | + EXPECT_EQ(Some.intersectWith(SomePos), SomePos); |
| 199 | + EXPECT_EQ(Some.intersectWith(SomeNeg), SomeNeg); |
| 200 | + EXPECT_EQ(NaN.intersectWith(Finite), Empty); |
| 201 | + EXPECT_EQ(NaN.intersectWith(SNaN), SNaN); |
| 202 | + EXPECT_EQ(NaN.intersectWith(QNaN), QNaN); |
| 203 | + EXPECT_EQ(Finite.intersectWith(One), One); |
| 204 | + EXPECT_EQ(Some.intersectWith(Zero), Zero); |
| 205 | + EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(4.0)) |
| 206 | + .intersectWith( |
| 207 | + ConstantFPRange::getNonNaN(APFloat(3.0), APFloat(6.0))), |
| 208 | + ConstantFPRange::getNonNaN(APFloat(3.0), APFloat(4.0))); |
| 209 | + EXPECT_EQ(ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0)) |
| 210 | + .intersectWith( |
| 211 | + ConstantFPRange::getNonNaN(APFloat(5.0), APFloat(6.0))), |
| 212 | + Empty); |
| 213 | +} |
| 214 | + |
| 215 | +TEST_F(ConstantFPRangeTest, UnionWith) { |
| 216 | + EXPECT_EQ(Empty.unionWith(Full), Full); |
| 217 | + EXPECT_EQ(Empty.unionWith(Empty), Empty); |
| 218 | + EXPECT_EQ(Empty.unionWith(One), One); |
| 219 | + EXPECT_EQ(Empty.unionWith(Some), Some); |
| 220 | + EXPECT_EQ(Full.unionWith(Full), Full); |
| 221 | + EXPECT_EQ(Some.unionWith(Some), Some); |
| 222 | + EXPECT_EQ(Some.unionWith(One), Some); |
| 223 | + EXPECT_EQ(Full.unionWith(Some), Full); |
| 224 | + EXPECT_EQ(Some.unionWith(SomePos), Some); |
| 225 | + EXPECT_EQ(Some.unionWith(SomeNeg), Some); |
| 226 | + EXPECT_EQ(Finite.unionWith(One), Finite); |
| 227 | + EXPECT_EQ(Some.unionWith(Zero), Some); |
| 228 | + EXPECT_EQ(Finite.unionWith(PosInf).unionWith(NegInf).unionWith(NaN), Full); |
| 229 | + EXPECT_EQ(PosZero.unionWith(NegZero), Zero); |
| 230 | + EXPECT_EQ(NaN.unionWith(SNaN), NaN); |
| 231 | + EXPECT_EQ(NaN.unionWith(QNaN), NaN); |
| 232 | + EXPECT_EQ(SNaN.unionWith(QNaN), NaN); |
| 233 | + EXPECT_EQ( |
| 234 | + ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(4.0)) |
| 235 | + .unionWith(ConstantFPRange::getNonNaN(APFloat(3.0), APFloat(6.0))), |
| 236 | + ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(6.0))); |
| 237 | + EXPECT_EQ( |
| 238 | + ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(2.0)) |
| 239 | + .unionWith(ConstantFPRange::getNonNaN(APFloat(5.0), APFloat(6.0))), |
| 240 | + ConstantFPRange::getNonNaN(APFloat(1.0), APFloat(6.0))); |
| 241 | +} |
| 242 | + |
| 243 | +TEST_F(ConstantFPRangeTest, FPClassify) { |
| 244 | + EXPECT_EQ(Empty.classify(), fcNone); |
| 245 | + EXPECT_EQ(Full.classify(), fcAllFlags); |
| 246 | + EXPECT_EQ(Finite.classify(), fcFinite); |
| 247 | + EXPECT_EQ(Zero.classify(), fcZero); |
| 248 | + EXPECT_EQ(NaN.classify(), fcNan); |
| 249 | + EXPECT_EQ(SNaN.classify(), fcSNan); |
| 250 | + EXPECT_EQ(QNaN.classify(), fcQNan); |
| 251 | + EXPECT_EQ(One.classify(), fcPosNormal); |
| 252 | + EXPECT_EQ(Some.classify(), fcFinite); |
| 253 | + EXPECT_EQ(SomePos.classify(), fcPosFinite); |
| 254 | + EXPECT_EQ(SomeNeg.classify(), fcNegFinite); |
| 255 | + EXPECT_EQ(PosInf.classify(), fcPosInf); |
| 256 | + EXPECT_EQ(NegInf.classify(), fcNegInf); |
| 257 | + EXPECT_TRUE(SomePos.toKnownFPClass().cannotBeOrderedLessThanZero()); |
| 258 | + EXPECT_EQ(Finite.getSignBit(), std::nullopt); |
| 259 | + EXPECT_EQ(PosZero.getSignBit(), false); |
| 260 | + EXPECT_EQ(NegZero.getSignBit(), true); |
| 261 | + EXPECT_EQ(SomePos.getSignBit(), false); |
| 262 | + EXPECT_EQ(SomeNeg.getSignBit(), true); |
| 263 | + EXPECT_EQ(SomePos.toKnownFPClass().SignBit, false); |
| 264 | + EXPECT_EQ(SomeNeg.toKnownFPClass().SignBit, true); |
| 265 | +} |
| 266 | + |
| 267 | +TEST_F(ConstantFPRangeTest, Print) { |
| 268 | + auto ToString = [](const ConstantFPRange &CR) { |
| 269 | + std::string Str; |
| 270 | + raw_string_ostream OS(Str); |
| 271 | + CR.print(OS); |
| 272 | + return Str; |
| 273 | + }; |
| 274 | + |
| 275 | + EXPECT_EQ(ToString(Full), "full-set"); |
| 276 | + EXPECT_EQ(ToString(Empty), "empty-set"); |
| 277 | + EXPECT_EQ(ToString(NaN), "NaN"); |
| 278 | + EXPECT_EQ(ToString(SNaN), "SNaN"); |
| 279 | + EXPECT_EQ(ToString(QNaN), "QNaN"); |
| 280 | + EXPECT_EQ(ToString(One), "[1, 1]"); |
| 281 | + EXPECT_EQ(ToString(Some.unionWith(SNaN)), "[-3, 3] with SNaN"); |
| 282 | +} |
| 283 | + |
| 284 | +} // anonymous namespace |
0 commit comments