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#include " llvm/Support/Compiler.h"
@@ -39,6 +40,7 @@ class ValueLatticeElement {
3940 // / Transition allowed to the following states:
4041 // / constant
4142 // / constantrange_including_undef
43+ // / constantfprange_including_undef
4244 // / overdefined
4345 undef,
4446
@@ -71,6 +73,21 @@ class ValueLatticeElement {
7173 // / overdefined
7274 constantrange_including_undef,
7375
76+ // / The Value falls within this range. (Used only for floating point typed
77+ // / values.)
78+ // / Transition allowed to the following states:
79+ // / constantfprange (new range must be a superset of the existing range)
80+ // / constantfprange_including_undef
81+ // / overdefined
82+ constantfprange,
83+
84+ // / This Value falls within this range, but also may be undef.
85+ // / Merging it with other constant ranges results in
86+ // / constantfprange_including_undef.
87+ // / Transition allowed to the following states:
88+ // / overdefined
89+ constantfprange_including_undef,
90+
7491 // / We can not precisely model the dynamic values this value might take.
7592 // / No transitions are allowed after reaching overdefined.
7693 overdefined,
@@ -86,6 +103,7 @@ class ValueLatticeElement {
86103 union {
87104 Constant *ConstVal;
88105 ConstantRange Range;
106+ ConstantFPRange FPRange;
89107 };
90108
91109 // / Destroy contents of lattice value, without destructing the object.
@@ -101,6 +119,10 @@ class ValueLatticeElement {
101119 case constantrange:
102120 Range.~ConstantRange ();
103121 break ;
122+ case constantfprange_including_undef:
123+ case constantfprange:
124+ FPRange.~ConstantFPRange ();
125+ break ;
104126 };
105127 }
106128
@@ -155,6 +177,11 @@ class ValueLatticeElement {
155177 new (&Range) ConstantRange (Other.Range );
156178 NumRangeExtensions = Other.NumRangeExtensions ;
157179 break ;
180+ case constantfprange:
181+ case constantfprange_including_undef:
182+ new (&FPRange) ConstantFPRange (Other.FPRange );
183+ NumRangeExtensions = Other.NumRangeExtensions ;
184+ break ;
158185 case constant:
159186 case notconstant:
160187 ConstVal = Other.ConstVal ;
@@ -174,6 +201,11 @@ class ValueLatticeElement {
174201 new (&Range) ConstantRange (std::move (Other.Range ));
175202 NumRangeExtensions = Other.NumRangeExtensions ;
176203 break ;
204+ case constantfprange:
205+ case constantfprange_including_undef:
206+ new (&FPRange) ConstantFPRange (std::move (Other.FPRange ));
207+ NumRangeExtensions = Other.NumRangeExtensions ;
208+ break ;
177209 case constant:
178210 case notconstant:
179211 ConstVal = Other.ConstVal ;
@@ -226,6 +258,23 @@ class ValueLatticeElement {
226258 MergeOptions ().setMayIncludeUndef (MayIncludeUndef));
227259 return Res;
228260 }
261+ static ValueLatticeElement getFPRange (ConstantFPRange CR,
262+ bool MayIncludeUndef = false ) {
263+ if (CR.isFullSet ())
264+ return getOverdefined ();
265+
266+ if (CR.isEmptySet ()) {
267+ ValueLatticeElement Res;
268+ if (MayIncludeUndef)
269+ Res.markUndef ();
270+ return Res;
271+ }
272+
273+ ValueLatticeElement Res;
274+ Res.markConstantFPRange (std::move (CR),
275+ MergeOptions ().setMayIncludeUndef (MayIncludeUndef));
276+ return Res;
277+ }
229278 static ValueLatticeElement getOverdefined () {
230279 ValueLatticeElement Res;
231280 Res.markOverdefined ();
@@ -240,6 +289,9 @@ class ValueLatticeElement {
240289 bool isConstantRangeIncludingUndef () const {
241290 return Tag == constantrange_including_undef;
242291 }
292+ bool isConstantFPRangeIncludingUndef () const {
293+ return Tag == constantfprange_including_undef;
294+ }
243295 // / Returns true if this value is a constant range. Use \p UndefAllowed to
244296 // / exclude non-singleton constant ranges that may also be undef. Note that
245297 // / this function also returns true if the range may include undef, but only
@@ -248,6 +300,16 @@ class ValueLatticeElement {
248300 return Tag == constantrange || (Tag == constantrange_including_undef &&
249301 (UndefAllowed || Range.isSingleElement ()));
250302 }
303+ // / Returns true if this value is a constant floating point range. Use \p
304+ // / UndefAllowed to exclude non-singleton constant ranges that may also be
305+ // / undef. Note that this function also returns true if the range may include
306+ // / undef, but only contains a single element. In that case, it can be
307+ // / replaced by a constant.
308+ bool isConstantFPRange (bool UndefAllowed = true ) const {
309+ return Tag == constantfprange ||
310+ (Tag == constantfprange_including_undef &&
311+ (UndefAllowed || FPRange.isSingleElement ()));
312+ }
251313 bool isOverdefined () const { return Tag == overdefined; }
252314
253315 Constant *getConstant () const {
@@ -270,6 +332,17 @@ class ValueLatticeElement {
270332 return Range;
271333 }
272334
335+ // / Returns the constant floating point range for this value. Use \p
336+ // / UndefAllowed to exclude non-singleton constant ranges that may also be
337+ // / undef. Note that this function also returns a range if the range may
338+ // / include undef, but only contains a single element. In that case, it can be
339+ // / replaced by a constant.
340+ const ConstantFPRange &getConstantFPRange (bool UndefAllowed = true ) const {
341+ assert (isConstantFPRange (UndefAllowed) &&
342+ " Cannot get the constant-fprange of a non-constant-fprange!" );
343+ return FPRange;
344+ }
345+
273346 std::optional<APInt> asConstantInteger () const {
274347 if (isConstant () && isa<ConstantInt>(getConstant ())) {
275348 return cast<ConstantInt>(getConstant ())->getValue ();
@@ -279,6 +352,15 @@ class ValueLatticeElement {
279352 return std::nullopt ;
280353 }
281354
355+ std::optional<APFloat> asConstantFP () const {
356+ if (isConstant () && isa<ConstantFP>(getConstant ())) {
357+ return cast<ConstantFP>(getConstant ())->getValue ();
358+ } else if (isConstantFPRange () && getConstantFPRange ().isSingleElement ()) {
359+ return *getConstantFPRange ().getSingleElement ();
360+ }
361+ return std::nullopt ;
362+ }
363+
282364 ConstantRange asConstantRange (unsigned BW, bool UndefAllowed = false ) const {
283365 if (isConstantRange (UndefAllowed))
284366 return getConstantRange ();
@@ -289,11 +371,28 @@ class ValueLatticeElement {
289371 return ConstantRange::getFull (BW);
290372 }
291373
374+ ConstantFPRange asConstantFPRange (const fltSemantics &Sem,
375+ bool UndefAllowed = false ) const {
376+ if (isConstantFPRange (UndefAllowed))
377+ return getConstantFPRange ();
378+ if (isConstant ())
379+ return getConstant ()->toConstantFPRange ();
380+ if (isUnknown ())
381+ return ConstantFPRange::getEmpty (Sem);
382+ return ConstantFPRange::getFull (Sem);
383+ }
384+
292385 ConstantRange asConstantRange (Type *Ty, bool UndefAllowed = false ) const {
293386 assert (Ty->isIntOrIntVectorTy () && " Must be integer type" );
294387 return asConstantRange (Ty->getScalarSizeInBits (), UndefAllowed);
295388 }
296389
390+ ConstantFPRange asConstantFPRange (Type *Ty, bool UndefAllowed = false ) const {
391+ assert (Ty->isFPOrFPVectorTy () && " Must be floating point type" );
392+ return asConstantFPRange (Ty->getScalarType ()->getFltSemantics (),
393+ UndefAllowed);
394+ }
395+
297396 bool markOverdefined () {
298397 if (isOverdefined ())
299398 return false ;
@@ -395,6 +494,51 @@ class ValueLatticeElement {
395494 return true ;
396495 }
397496
497+ // / Mark the object as constant floating point range with \p NewR. If the
498+ // / object is already a constant range, nothing changes if the existing range
499+ // / is equal to \p NewR and the tag. Otherwise \p NewR must be a superset of
500+ // / the existing range or the object must be undef. The tag is set to
501+ // / constant_range_including_undef if either the existing value or the new
502+ // / range may include undef.
503+ bool markConstantFPRange (ConstantFPRange NewR,
504+ MergeOptions Opts = MergeOptions()) {
505+ assert (!NewR.isEmptySet () && " should only be called for non-empty sets" );
506+
507+ if (NewR.isFullSet ())
508+ return markOverdefined ();
509+
510+ ValueLatticeElementTy OldTag = Tag;
511+ ValueLatticeElementTy NewTag =
512+ (isUndef () || isConstantFPRangeIncludingUndef () || Opts.MayIncludeUndef )
513+ ? constantfprange_including_undef
514+ : constantfprange;
515+ if (isConstantFPRange ()) {
516+ Tag = NewTag;
517+ if (getConstantFPRange () == NewR)
518+ return Tag != OldTag;
519+
520+ // Simple form of widening. If a range is extended multiple times, go to
521+ // overdefined.
522+ if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps )
523+ return markOverdefined ();
524+
525+ assert (NewR.contains (getConstantFPRange ()) &&
526+ " Existing range must be a subset of NewR" );
527+ FPRange = std::move (NewR);
528+ return true ;
529+ }
530+
531+ assert (isUnknown () || isUndef () || isConstant ());
532+ assert (
533+ (!isConstant () || NewR.contains (getConstant ()->toConstantFPRange ())) &&
534+ " Constant must be subset of new range" );
535+
536+ NumRangeExtensions = 0 ;
537+ Tag = NewTag;
538+ new (&FPRange) ConstantFPRange (std::move (NewR));
539+ return true ;
540+ }
541+
398542 // / Updates this object to approximate both this object and RHS. Returns
399543 // / true if this object has been changed.
400544 bool mergeIn (const ValueLatticeElement &RHS,
@@ -415,6 +559,9 @@ class ValueLatticeElement {
415559 if (RHS.isConstantRange ())
416560 return markConstantRange (RHS.getConstantRange (true ),
417561 Opts.setMayIncludeUndef ());
562+ if (RHS.isConstantFPRange ())
563+ return markConstantFPRange (RHS.getConstantFPRange (true ),
564+ Opts.setMayIncludeUndef ());
418565 return markOverdefined ();
419566 }
420567
@@ -429,15 +576,26 @@ class ValueLatticeElement {
429576 return false ;
430577 if (RHS.isUndef ())
431578 return false ;
432- // If the constant is a vector of integers, try to treat it as a range.
433- if (getConstant ()->getType ()->isVectorTy () &&
434- getConstant ()->getType ()->getScalarType ()->isIntegerTy ()) {
435- ConstantRange L = getConstant ()->toConstantRange ();
436- ConstantRange NewR = L.unionWith (
437- RHS.asConstantRange (L.getBitWidth (), /* UndefAllowed=*/ true ));
438- return markConstantRange (
439- std::move (NewR),
440- Opts.setMayIncludeUndef (RHS.isConstantRangeIncludingUndef ()));
579+ // If the constant is a vector of integers/floating point values, try to
580+ // treat it as a range.
581+ if (getConstant ()->getType ()->isVectorTy ()) {
582+ Type *ScalarTy = getConstant ()->getType ()->getScalarType ();
583+ if (ScalarTy->isIntegerTy ()) {
584+ ConstantRange L = getConstant ()->toConstantRange ();
585+ ConstantRange NewR = L.unionWith (
586+ RHS.asConstantRange (L.getBitWidth (), /* UndefAllowed=*/ true ));
587+ return markConstantRange (
588+ std::move (NewR),
589+ Opts.setMayIncludeUndef (RHS.isConstantRangeIncludingUndef ()));
590+ }
591+ if (ScalarTy->isFloatingPointTy ()) {
592+ ConstantFPRange L = getConstant ()->toConstantFPRange ();
593+ ConstantFPRange NewR = L.unionWith (
594+ RHS.asConstantFPRange (L.getSemantics (), /* UndefAllowed=*/ true ));
595+ return markConstantFPRange (
596+ std::move (NewR),
597+ Opts.setMayIncludeUndef (RHS.isConstantFPRangeIncludingUndef ()));
598+ }
441599 }
442600 markOverdefined ();
443601 return true ;
@@ -451,18 +609,35 @@ class ValueLatticeElement {
451609 }
452610
453611 auto OldTag = Tag;
454- assert (isConstantRange () && " New ValueLattice type?" );
455- if (RHS.isUndef ()) {
456- Tag = constantrange_including_undef;
457- return OldTag != Tag;
612+ if (isConstantRange ()) {
613+ if (RHS.isUndef ()) {
614+ Tag = constantrange_including_undef;
615+ return OldTag != Tag;
616+ }
617+
618+ const ConstantRange &L = getConstantRange ();
619+ ConstantRange NewR = L.unionWith (
620+ RHS.asConstantRange (L.getBitWidth (), /* UndefAllowed=*/ true ));
621+ return markConstantRange (
622+ std::move (NewR),
623+ Opts.setMayIncludeUndef (RHS.isConstantRangeIncludingUndef ()));
458624 }
459625
460- const ConstantRange &L = getConstantRange ();
461- ConstantRange NewR = L.unionWith (
462- RHS.asConstantRange (L.getBitWidth (), /* UndefAllowed=*/ true ));
463- return markConstantRange (
464- std::move (NewR),
465- Opts.setMayIncludeUndef (RHS.isConstantRangeIncludingUndef ()));
626+ if (isConstantFPRange ()) {
627+ if (RHS.isUndef ()) {
628+ Tag = constantfprange_including_undef;
629+ return OldTag != Tag;
630+ }
631+
632+ const ConstantFPRange &L = getConstantFPRange ();
633+ ConstantFPRange NewR = L.unionWith (
634+ RHS.asConstantFPRange (L.getSemantics (), /* UndefAllowed=*/ true ));
635+ return markConstantFPRange (
636+ std::move (NewR),
637+ Opts.setMayIncludeUndef (RHS.isConstantFPRangeIncludingUndef ()));
638+ } else {
639+ llvm_unreachable (" New ValueLattice type?" );
640+ }
466641 }
467642
468643 // Compares this symbolic value with Other using Pred and returns either
@@ -494,7 +669,7 @@ class ValueLatticeElement {
494669 void setNumRangeExtensions (unsigned N) { NumRangeExtensions = N; }
495670};
496671
497- static_assert (sizeof (ValueLatticeElement) <= 40 ,
672+ static_assert (sizeof (ValueLatticeElement) <= 64 ,
498673 " size of ValueLatticeElement changed unexpectedly" );
499674
500675LLVM_ABI raw_ostream &operator <<(raw_ostream &OS,
0 commit comments