99#ifndef LLVM_ANALYSIS_VALUELATTICE_H
1010#define LLVM_ANALYSIS_VALUELATTICE_H
1111
12+ #include " llvm/IR/ConstantFPRange.h"
1213#include " llvm/IR/ConstantRange.h"
1314#include " llvm/IR/Constants.h"
1415
@@ -38,6 +39,7 @@ class ValueLatticeElement {
3839 // / Transition allowed to the following states:
3940 // / constant
4041 // / constantrange_including_undef
42+ // / constantfprange_including_undef
4143 // / overdefined
4244 undef,
4345
@@ -70,6 +72,21 @@ class ValueLatticeElement {
7072 // / overdefined
7173 constantrange_including_undef,
7274
75+ // / The Value falls within this range. (Used only for floating point typed
76+ // / values.)
77+ // / Transition allowed to the following states:
78+ // / constantfprange (new range must be a superset of the existing range)
79+ // / constantfprange_including_undef
80+ // / overdefined
81+ constantfprange,
82+
83+ // / This Value falls within this range, but also may be undef.
84+ // / Merging it with other constant ranges results in
85+ // / constantfprange_including_undef.
86+ // / Transition allowed to the following states:
87+ // / overdefined
88+ constantfprange_including_undef,
89+
7390 // / We can not precisely model the dynamic values this value might take.
7491 // / No transitions are allowed after reaching overdefined.
7592 overdefined,
@@ -85,6 +102,7 @@ class ValueLatticeElement {
85102 union {
86103 Constant *ConstVal;
87104 ConstantRange Range;
105+ ConstantFPRange FPRange;
88106 };
89107
90108 // / Destroy contents of lattice value, without destructing the object.
@@ -100,6 +118,10 @@ class ValueLatticeElement {
100118 case constantrange:
101119 Range.~ConstantRange ();
102120 break ;
121+ case constantfprange_including_undef:
122+ case constantfprange:
123+ FPRange.~ConstantFPRange ();
124+ break ;
103125 };
104126 }
105127
@@ -154,6 +176,11 @@ class ValueLatticeElement {
154176 new (&Range) ConstantRange (Other.Range );
155177 NumRangeExtensions = Other.NumRangeExtensions ;
156178 break ;
179+ case constantfprange:
180+ case constantfprange_including_undef:
181+ new (&FPRange) ConstantFPRange (Other.FPRange );
182+ NumRangeExtensions = Other.NumRangeExtensions ;
183+ break ;
157184 case constant:
158185 case notconstant:
159186 ConstVal = Other.ConstVal ;
@@ -173,6 +200,11 @@ class ValueLatticeElement {
173200 new (&Range) ConstantRange (std::move (Other.Range ));
174201 NumRangeExtensions = Other.NumRangeExtensions ;
175202 break ;
203+ case constantfprange:
204+ case constantfprange_including_undef:
205+ new (&FPRange) ConstantFPRange (Other.FPRange );
206+ NumRangeExtensions = Other.NumRangeExtensions ;
207+ break ;
176208 case constant:
177209 case notconstant:
178210 ConstVal = Other.ConstVal ;
@@ -225,6 +257,23 @@ class ValueLatticeElement {
225257 MergeOptions ().setMayIncludeUndef (MayIncludeUndef));
226258 return Res;
227259 }
260+ static ValueLatticeElement getFPRange (ConstantFPRange CR,
261+ bool MayIncludeUndef = false ) {
262+ if (CR.isFullSet ())
263+ return getOverdefined ();
264+
265+ if (CR.isEmptySet ()) {
266+ ValueLatticeElement Res;
267+ if (MayIncludeUndef)
268+ Res.markUndef ();
269+ return Res;
270+ }
271+
272+ ValueLatticeElement Res;
273+ Res.markConstantFPRange (std::move (CR),
274+ MergeOptions ().setMayIncludeUndef (MayIncludeUndef));
275+ return Res;
276+ }
228277 static ValueLatticeElement getOverdefined () {
229278 ValueLatticeElement Res;
230279 Res.markOverdefined ();
@@ -239,6 +288,9 @@ class ValueLatticeElement {
239288 bool isConstantRangeIncludingUndef () const {
240289 return Tag == constantrange_including_undef;
241290 }
291+ bool isConstantFPRangeIncludingUndef () const {
292+ return Tag == constantfprange_including_undef;
293+ }
242294 // / Returns true if this value is a constant range. Use \p UndefAllowed to
243295 // / exclude non-singleton constant ranges that may also be undef. Note that
244296 // / this function also returns true if the range may include undef, but only
@@ -247,6 +299,16 @@ class ValueLatticeElement {
247299 return Tag == constantrange || (Tag == constantrange_including_undef &&
248300 (UndefAllowed || Range.isSingleElement ()));
249301 }
302+ // / Returns true if this value is a constant floating point range. Use \p
303+ // / UndefAllowed to exclude non-singleton constant ranges that may also be
304+ // / undef. Note that this function also returns true if the range may include
305+ // / undef, but only contains a single element. In that case, it can be
306+ // / replaced by a constant.
307+ bool isConstantFPRange (bool UndefAllowed = true ) const {
308+ return Tag == constantfprange ||
309+ (Tag == constantfprange_including_undef &&
310+ (UndefAllowed || FPRange.isSingleElement ()));
311+ }
250312 bool isOverdefined () const { return Tag == overdefined; }
251313
252314 Constant *getConstant () const {
@@ -269,6 +331,17 @@ class ValueLatticeElement {
269331 return Range;
270332 }
271333
334+ // / Returns the constant floating point range for this value. Use \p
335+ // / UndefAllowed to exclude non-singleton constant ranges that may also be
336+ // / undef. Note that this function also returns a range if the range may
337+ // / include undef, but only contains a single element. In that case, it can be
338+ // / replaced by a constant.
339+ const ConstantFPRange &getConstantFPRange (bool UndefAllowed = true ) const {
340+ assert (isConstantFPRange (UndefAllowed) &&
341+ " Cannot get the constant-fprange of a non-constant-fprange!" );
342+ return FPRange;
343+ }
344+
272345 std::optional<APInt> asConstantInteger () const {
273346 if (isConstant () && isa<ConstantInt>(getConstant ())) {
274347 return cast<ConstantInt>(getConstant ())->getValue ();
@@ -278,6 +351,15 @@ class ValueLatticeElement {
278351 return std::nullopt ;
279352 }
280353
354+ std::optional<APFloat> asConstantFP () const {
355+ if (isConstant () && isa<ConstantFP>(getConstant ())) {
356+ return cast<ConstantFP>(getConstant ())->getValue ();
357+ } else if (isConstantFPRange () && getConstantFPRange ().isSingleElement ()) {
358+ return *getConstantFPRange ().getSingleElement ();
359+ }
360+ return std::nullopt ;
361+ }
362+
281363 ConstantRange asConstantRange (unsigned BW, bool UndefAllowed = false ) const {
282364 if (isConstantRange (UndefAllowed))
283365 return getConstantRange ();
@@ -288,11 +370,28 @@ class ValueLatticeElement {
288370 return ConstantRange::getFull (BW);
289371 }
290372
373+ ConstantFPRange asConstantFPRange (const fltSemantics &Sem,
374+ bool UndefAllowed = false ) const {
375+ if (isConstantFPRange (UndefAllowed))
376+ return getConstantFPRange ();
377+ if (isConstant ())
378+ return getConstant ()->toConstantFPRange ();
379+ if (isUnknown ())
380+ return ConstantFPRange::getEmpty (Sem);
381+ return ConstantFPRange::getFull (Sem);
382+ }
383+
291384 ConstantRange asConstantRange (Type *Ty, bool UndefAllowed = false ) const {
292385 assert (Ty->isIntOrIntVectorTy () && " Must be integer type" );
293386 return asConstantRange (Ty->getScalarSizeInBits (), UndefAllowed);
294387 }
295388
389+ ConstantFPRange asConstantFPRange (Type *Ty, bool UndefAllowed = false ) const {
390+ assert (Ty->isFPOrFPVectorTy () && " Must be floating point type" );
391+ return asConstantFPRange (Ty->getScalarType ()->getFltSemantics (),
392+ UndefAllowed);
393+ }
394+
296395 bool markOverdefined () {
297396 if (isOverdefined ())
298397 return false ;
@@ -394,6 +493,51 @@ class ValueLatticeElement {
394493 return true ;
395494 }
396495
496+ // / Mark the object as constant floating point range with \p NewR. If the
497+ // / object is already a constant range, nothing changes if the existing range
498+ // / is equal to \p NewR and the tag. Otherwise \p NewR must be a superset of
499+ // / the existing range or the object must be undef. The tag is set to
500+ // / constant_range_including_undef if either the existing value or the new
501+ // / range may include undef.
502+ bool markConstantFPRange (ConstantFPRange NewR,
503+ MergeOptions Opts = MergeOptions()) {
504+ assert (!NewR.isEmptySet () && " should only be called for non-empty sets" );
505+
506+ if (NewR.isFullSet ())
507+ return markOverdefined ();
508+
509+ ValueLatticeElementTy OldTag = Tag;
510+ ValueLatticeElementTy NewTag =
511+ (isUndef () || isConstantFPRangeIncludingUndef () || Opts.MayIncludeUndef )
512+ ? constantfprange_including_undef
513+ : constantfprange;
514+ if (isConstantFPRange ()) {
515+ Tag = NewTag;
516+ if (getConstantFPRange () == NewR)
517+ return Tag != OldTag;
518+
519+ // Simple form of widening. If a range is extended multiple times, go to
520+ // overdefined.
521+ if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps )
522+ return markOverdefined ();
523+
524+ assert (NewR.contains (getConstantFPRange ()) &&
525+ " Existing range must be a subset of NewR" );
526+ FPRange = std::move (NewR);
527+ return true ;
528+ }
529+
530+ assert (isUnknown () || isUndef () || isConstant ());
531+ assert (
532+ (!isConstant () || NewR.contains (getConstant ()->toConstantFPRange ())) &&
533+ " Constant must be subset of new range" );
534+
535+ NumRangeExtensions = 0 ;
536+ Tag = NewTag;
537+ new (&FPRange) ConstantFPRange (std::move (NewR));
538+ return true ;
539+ }
540+
397541 // / Updates this object to approximate both this object and RHS. Returns
398542 // / true if this object has been changed.
399543 bool mergeIn (const ValueLatticeElement &RHS,
@@ -414,6 +558,9 @@ class ValueLatticeElement {
414558 if (RHS.isConstantRange ())
415559 return markConstantRange (RHS.getConstantRange (true ),
416560 Opts.setMayIncludeUndef ());
561+ if (RHS.isConstantFPRange ())
562+ return markConstantFPRange (RHS.getConstantFPRange (true ),
563+ Opts.setMayIncludeUndef ());
417564 return markOverdefined ();
418565 }
419566
@@ -428,15 +575,26 @@ class ValueLatticeElement {
428575 return false ;
429576 if (RHS.isUndef ())
430577 return false ;
431- // If the constant is a vector of integers, try to treat it as a range.
432- if (getConstant ()->getType ()->isVectorTy () &&
433- getConstant ()->getType ()->getScalarType ()->isIntegerTy ()) {
434- ConstantRange L = getConstant ()->toConstantRange ();
435- ConstantRange NewR = L.unionWith (
436- RHS.asConstantRange (L.getBitWidth (), /* UndefAllowed=*/ true ));
437- return markConstantRange (
438- std::move (NewR),
439- Opts.setMayIncludeUndef (RHS.isConstantRangeIncludingUndef ()));
578+ // If the constant is a vector of integers/floating point values, try to
579+ // treat it as a range.
580+ if (getConstant ()->getType ()->isVectorTy ()) {
581+ Type *ScalarTy = getConstant ()->getType ()->getScalarType ();
582+ if (ScalarTy->isIntegerTy ()) {
583+ ConstantRange L = getConstant ()->toConstantRange ();
584+ ConstantRange NewR = L.unionWith (
585+ RHS.asConstantRange (L.getBitWidth (), /* UndefAllowed=*/ true ));
586+ return markConstantRange (
587+ std::move (NewR),
588+ Opts.setMayIncludeUndef (RHS.isConstantRangeIncludingUndef ()));
589+ }
590+ if (ScalarTy->isFloatingPointTy ()) {
591+ ConstantFPRange L = getConstant ()->toConstantFPRange ();
592+ ConstantFPRange NewR = L.unionWith (
593+ RHS.asConstantFPRange (L.getSemantics (), /* UndefAllowed=*/ true ));
594+ return markConstantFPRange (
595+ std::move (NewR),
596+ Opts.setMayIncludeUndef (RHS.isConstantFPRangeIncludingUndef ()));
597+ }
440598 }
441599 markOverdefined ();
442600 return true ;
@@ -450,18 +608,35 @@ class ValueLatticeElement {
450608 }
451609
452610 auto OldTag = Tag;
453- assert (isConstantRange () && " New ValueLattice type?" );
454- if (RHS.isUndef ()) {
455- Tag = constantrange_including_undef;
456- return OldTag != Tag;
611+ if (isConstantRange ()) {
612+ if (RHS.isUndef ()) {
613+ Tag = constantrange_including_undef;
614+ return OldTag != Tag;
615+ }
616+
617+ const ConstantRange &L = getConstantRange ();
618+ ConstantRange NewR = L.unionWith (
619+ RHS.asConstantRange (L.getBitWidth (), /* UndefAllowed=*/ true ));
620+ return markConstantRange (
621+ std::move (NewR),
622+ Opts.setMayIncludeUndef (RHS.isConstantRangeIncludingUndef ()));
457623 }
458624
459- const ConstantRange &L = getConstantRange ();
460- ConstantRange NewR = L.unionWith (
461- RHS.asConstantRange (L.getBitWidth (), /* UndefAllowed=*/ true ));
462- return markConstantRange (
463- std::move (NewR),
464- Opts.setMayIncludeUndef (RHS.isConstantRangeIncludingUndef ()));
625+ if (isConstantFPRange ()) {
626+ if (RHS.isUndef ()) {
627+ Tag = constantfprange_including_undef;
628+ return OldTag != Tag;
629+ }
630+
631+ const ConstantFPRange &L = getConstantFPRange ();
632+ ConstantFPRange NewR = L.unionWith (
633+ RHS.asConstantFPRange (L.getSemantics (), /* UndefAllowed=*/ true ));
634+ return markConstantFPRange (
635+ std::move (NewR),
636+ Opts.setMayIncludeUndef (RHS.isConstantFPRangeIncludingUndef ()));
637+ } else {
638+ llvm_unreachable (" New ValueLattice type?" );
639+ }
465640 }
466641
467642 // Compares this symbolic value with Other using Pred and returns either
@@ -492,7 +667,7 @@ class ValueLatticeElement {
492667 void setNumRangeExtensions (unsigned N) { NumRangeExtensions = N; }
493668};
494669
495- static_assert (sizeof (ValueLatticeElement) <= 40 ,
670+ static_assert (sizeof (ValueLatticeElement) <= 64 ,
496671 " size of ValueLatticeElement changed unexpectedly" );
497672
498673raw_ostream &operator <<(raw_ostream &OS, const ValueLatticeElement &Val);
0 commit comments