9
9
#ifndef LLVM_ANALYSIS_VALUELATTICE_H
10
10
#define LLVM_ANALYSIS_VALUELATTICE_H
11
11
12
+ #include " llvm/IR/ConstantFPRange.h"
12
13
#include " llvm/IR/ConstantRange.h"
13
14
#include " llvm/IR/Constants.h"
14
15
@@ -38,6 +39,7 @@ class ValueLatticeElement {
38
39
// / Transition allowed to the following states:
39
40
// / constant
40
41
// / constantrange_including_undef
42
+ // / constantfprange_including_undef
41
43
// / overdefined
42
44
undef,
43
45
@@ -70,6 +72,21 @@ class ValueLatticeElement {
70
72
// / overdefined
71
73
constantrange_including_undef,
72
74
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
+
73
90
// / We can not precisely model the dynamic values this value might take.
74
91
// / No transitions are allowed after reaching overdefined.
75
92
overdefined,
@@ -85,6 +102,7 @@ class ValueLatticeElement {
85
102
union {
86
103
Constant *ConstVal;
87
104
ConstantRange Range;
105
+ ConstantFPRange FPRange;
88
106
};
89
107
90
108
// / Destroy contents of lattice value, without destructing the object.
@@ -100,6 +118,10 @@ class ValueLatticeElement {
100
118
case constantrange:
101
119
Range.~ConstantRange ();
102
120
break ;
121
+ case constantfprange_including_undef:
122
+ case constantfprange:
123
+ FPRange.~ConstantFPRange ();
124
+ break ;
103
125
};
104
126
}
105
127
@@ -154,6 +176,11 @@ class ValueLatticeElement {
154
176
new (&Range) ConstantRange (Other.Range );
155
177
NumRangeExtensions = Other.NumRangeExtensions ;
156
178
break ;
179
+ case constantfprange:
180
+ case constantfprange_including_undef:
181
+ new (&FPRange) ConstantFPRange (Other.FPRange );
182
+ NumRangeExtensions = Other.NumRangeExtensions ;
183
+ break ;
157
184
case constant:
158
185
case notconstant:
159
186
ConstVal = Other.ConstVal ;
@@ -173,6 +200,11 @@ class ValueLatticeElement {
173
200
new (&Range) ConstantRange (std::move (Other.Range ));
174
201
NumRangeExtensions = Other.NumRangeExtensions ;
175
202
break ;
203
+ case constantfprange:
204
+ case constantfprange_including_undef:
205
+ new (&FPRange) ConstantFPRange (Other.FPRange );
206
+ NumRangeExtensions = Other.NumRangeExtensions ;
207
+ break ;
176
208
case constant:
177
209
case notconstant:
178
210
ConstVal = Other.ConstVal ;
@@ -225,6 +257,23 @@ class ValueLatticeElement {
225
257
MergeOptions ().setMayIncludeUndef (MayIncludeUndef));
226
258
return Res;
227
259
}
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
+ }
228
277
static ValueLatticeElement getOverdefined () {
229
278
ValueLatticeElement Res;
230
279
Res.markOverdefined ();
@@ -239,6 +288,9 @@ class ValueLatticeElement {
239
288
bool isConstantRangeIncludingUndef () const {
240
289
return Tag == constantrange_including_undef;
241
290
}
291
+ bool isConstantFPRangeIncludingUndef () const {
292
+ return Tag == constantfprange_including_undef;
293
+ }
242
294
// / Returns true if this value is a constant range. Use \p UndefAllowed to
243
295
// / exclude non-singleton constant ranges that may also be undef. Note that
244
296
// / this function also returns true if the range may include undef, but only
@@ -247,6 +299,16 @@ class ValueLatticeElement {
247
299
return Tag == constantrange || (Tag == constantrange_including_undef &&
248
300
(UndefAllowed || Range.isSingleElement ()));
249
301
}
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
+ }
250
312
bool isOverdefined () const { return Tag == overdefined; }
251
313
252
314
Constant *getConstant () const {
@@ -269,6 +331,17 @@ class ValueLatticeElement {
269
331
return Range;
270
332
}
271
333
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
+
272
345
std::optional<APInt> asConstantInteger () const {
273
346
if (isConstant () && isa<ConstantInt>(getConstant ())) {
274
347
return cast<ConstantInt>(getConstant ())->getValue ();
@@ -278,6 +351,15 @@ class ValueLatticeElement {
278
351
return std::nullopt;
279
352
}
280
353
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
+
281
363
ConstantRange asConstantRange (unsigned BW, bool UndefAllowed = false ) const {
282
364
if (isConstantRange (UndefAllowed))
283
365
return getConstantRange ();
@@ -288,11 +370,28 @@ class ValueLatticeElement {
288
370
return ConstantRange::getFull (BW);
289
371
}
290
372
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
+
291
384
ConstantRange asConstantRange (Type *Ty, bool UndefAllowed = false ) const {
292
385
assert (Ty->isIntOrIntVectorTy () && " Must be integer type" );
293
386
return asConstantRange (Ty->getScalarSizeInBits (), UndefAllowed);
294
387
}
295
388
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
+
296
395
bool markOverdefined () {
297
396
if (isOverdefined ())
298
397
return false ;
@@ -394,6 +493,51 @@ class ValueLatticeElement {
394
493
return true ;
395
494
}
396
495
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
+
397
541
// / Updates this object to approximate both this object and RHS. Returns
398
542
// / true if this object has been changed.
399
543
bool mergeIn (const ValueLatticeElement &RHS,
@@ -414,6 +558,9 @@ class ValueLatticeElement {
414
558
if (RHS.isConstantRange ())
415
559
return markConstantRange (RHS.getConstantRange (true ),
416
560
Opts.setMayIncludeUndef ());
561
+ if (RHS.isConstantFPRange ())
562
+ return markConstantFPRange (RHS.getConstantFPRange (true ),
563
+ Opts.setMayIncludeUndef ());
417
564
return markOverdefined ();
418
565
}
419
566
@@ -428,15 +575,26 @@ class ValueLatticeElement {
428
575
return false ;
429
576
if (RHS.isUndef ())
430
577
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
+ }
440
598
}
441
599
markOverdefined ();
442
600
return true ;
@@ -450,18 +608,35 @@ class ValueLatticeElement {
450
608
}
451
609
452
610
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 ()));
457
623
}
458
624
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
+ }
465
640
}
466
641
467
642
// Compares this symbolic value with Other using Pred and returns either
@@ -492,7 +667,7 @@ class ValueLatticeElement {
492
667
void setNumRangeExtensions (unsigned N) { NumRangeExtensions = N; }
493
668
};
494
669
495
- static_assert (sizeof (ValueLatticeElement) <= 40 ,
670
+ static_assert (sizeof (ValueLatticeElement) <= 80 ,
496
671
" size of ValueLatticeElement changed unexpectedly" );
497
672
498
673
raw_ostream &operator <<(raw_ostream &OS, const ValueLatticeElement &Val);
0 commit comments