Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- ValueLattice.h - Value constraint analysis ---------------*- 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
#ifndef LLVM_ANALYSIS_VALUELATTICE_H
10
#define LLVM_ANALYSIS_VALUELATTICE_H
11
 
12
#include "llvm/IR/Constants.h"
13
#include "llvm/IR/ConstantRange.h"
14
#include "llvm/IR/Instructions.h"
15
 
16
//===----------------------------------------------------------------------===//
17
//                               ValueLatticeElement
18
//===----------------------------------------------------------------------===//
19
 
20
namespace llvm {
21
 
22
class Constant;
23
 
24
/// This class represents lattice values for constants.
25
///
26
/// FIXME: This is basically just for bringup, this can be made a lot more rich
27
/// in the future.
28
///
29
class ValueLatticeElement {
30
  enum ValueLatticeElementTy {
31
    /// This Value has no known value yet.  As a result, this implies the
32
    /// producing instruction is dead.  Caution: We use this as the starting
33
    /// state in our local meet rules.  In this usage, it's taken to mean
34
    /// "nothing known yet".
35
    /// Transition to any other state allowed.
36
    unknown,
37
 
38
    /// This Value is an UndefValue constant or produces undef. Undefined values
39
    /// can be merged with constants (or single element constant ranges),
40
    /// assuming all uses of the result will be replaced.
41
    /// Transition allowed to the following states:
42
    ///  constant
43
    ///  constantrange_including_undef
44
    ///  overdefined
45
    undef,
46
 
47
    /// This Value has a specific constant value.  The constant cannot be undef.
48
    /// (For constant integers, constantrange is used instead. Integer typed
49
    /// constantexprs can appear as constant.) Note that the constant state
50
    /// can be reached by merging undef & constant states.
51
    /// Transition allowed to the following states:
52
    ///  overdefined
53
    constant,
54
 
55
    /// This Value is known to not have the specified value. (For constant
56
    /// integers, constantrange is used instead.  As above, integer typed
57
    /// constantexprs can appear here.)
58
    /// Transition allowed to the following states:
59
    ///  overdefined
60
    notconstant,
61
 
62
    /// The Value falls within this range. (Used only for integer typed values.)
63
    /// Transition allowed to the following states:
64
    ///  constantrange (new range must be a superset of the existing range)
65
    ///  constantrange_including_undef
66
    ///  overdefined
67
    constantrange,
68
 
69
    /// This Value falls within this range, but also may be undef.
70
    /// Merging it with other constant ranges results in
71
    /// constantrange_including_undef.
72
    /// Transition allowed to the following states:
73
    ///  overdefined
74
    constantrange_including_undef,
75
 
76
    /// We can not precisely model the dynamic values this value might take.
77
    /// No transitions are allowed after reaching overdefined.
78
    overdefined,
79
  };
80
 
81
  ValueLatticeElementTy Tag : 8;
82
  /// Number of times a constant range has been extended with widening enabled.
83
  unsigned NumRangeExtensions : 8;
84
 
85
  /// The union either stores a pointer to a constant or a constant range,
86
  /// associated to the lattice element. We have to ensure that Range is
87
  /// initialized or destroyed when changing state to or from constantrange.
88
  union {
89
    Constant *ConstVal;
90
    ConstantRange Range;
91
  };
92
 
93
  /// Destroy contents of lattice value, without destructing the object.
94
  void destroy() {
95
    switch (Tag) {
96
    case overdefined:
97
    case unknown:
98
    case undef:
99
    case constant:
100
    case notconstant:
101
      break;
102
    case constantrange_including_undef:
103
    case constantrange:
104
      Range.~ConstantRange();
105
      break;
106
    };
107
  }
108
 
109
public:
110
  /// Struct to control some aspects related to merging constant ranges.
111
  struct MergeOptions {
112
    /// The merge value may include undef.
113
    bool MayIncludeUndef;
114
 
115
    /// Handle repeatedly extending a range by going to overdefined after a
116
    /// number of steps.
117
    bool CheckWiden;
118
 
119
    /// The number of allowed widening steps (including setting the range
120
    /// initially).
121
    unsigned MaxWidenSteps;
122
 
123
    MergeOptions() : MergeOptions(false, false) {}
124
 
125
    MergeOptions(bool MayIncludeUndef, bool CheckWiden,
126
                 unsigned MaxWidenSteps = 1)
127
        : MayIncludeUndef(MayIncludeUndef), CheckWiden(CheckWiden),
128
          MaxWidenSteps(MaxWidenSteps) {}
129
 
130
    MergeOptions &setMayIncludeUndef(bool V = true) {
131
      MayIncludeUndef = V;
132
      return *this;
133
    }
134
 
135
    MergeOptions &setCheckWiden(bool V = true) {
136
      CheckWiden = V;
137
      return *this;
138
    }
139
 
140
    MergeOptions &setMaxWidenSteps(unsigned Steps = 1) {
141
      CheckWiden = true;
142
      MaxWidenSteps = Steps;
143
      return *this;
144
    }
145
  };
146
 
147
  // ConstVal and Range are initialized on-demand.
148
  ValueLatticeElement() : Tag(unknown), NumRangeExtensions(0) {}
149
 
150
  ~ValueLatticeElement() { destroy(); }
151
 
152
  ValueLatticeElement(const ValueLatticeElement &Other)
153
      : Tag(Other.Tag), NumRangeExtensions(0) {
154
    switch (Other.Tag) {
155
    case constantrange:
156
    case constantrange_including_undef:
157
      new (&Range) ConstantRange(Other.Range);
158
      NumRangeExtensions = Other.NumRangeExtensions;
159
      break;
160
    case constant:
161
    case notconstant:
162
      ConstVal = Other.ConstVal;
163
      break;
164
    case overdefined:
165
    case unknown:
166
    case undef:
167
      break;
168
    }
169
  }
170
 
171
  ValueLatticeElement(ValueLatticeElement &&Other)
172
      : Tag(Other.Tag), NumRangeExtensions(0) {
173
    switch (Other.Tag) {
174
    case constantrange:
175
    case constantrange_including_undef:
176
      new (&Range) ConstantRange(std::move(Other.Range));
177
      NumRangeExtensions = Other.NumRangeExtensions;
178
      break;
179
    case constant:
180
    case notconstant:
181
      ConstVal = Other.ConstVal;
182
      break;
183
    case overdefined:
184
    case unknown:
185
    case undef:
186
      break;
187
    }
188
    Other.Tag = unknown;
189
  }
190
 
191
  ValueLatticeElement &operator=(const ValueLatticeElement &Other) {
192
    destroy();
193
    new (this) ValueLatticeElement(Other);
194
    return *this;
195
  }
196
 
197
  ValueLatticeElement &operator=(ValueLatticeElement &&Other) {
198
    destroy();
199
    new (this) ValueLatticeElement(std::move(Other));
200
    return *this;
201
  }
202
 
203
  static ValueLatticeElement get(Constant *C) {
204
    ValueLatticeElement Res;
205
    if (isa<UndefValue>(C))
206
      Res.markUndef();
207
    else
208
      Res.markConstant(C);
209
    return Res;
210
  }
211
  static ValueLatticeElement getNot(Constant *C) {
212
    ValueLatticeElement Res;
213
    assert(!isa<UndefValue>(C) && "!= undef is not supported");
214
    Res.markNotConstant(C);
215
    return Res;
216
  }
217
  static ValueLatticeElement getRange(ConstantRange CR,
218
                                      bool MayIncludeUndef = false) {
219
    if (CR.isFullSet())
220
      return getOverdefined();
221
 
222
    if (CR.isEmptySet()) {
223
      ValueLatticeElement Res;
224
      if (MayIncludeUndef)
225
        Res.markUndef();
226
      return Res;
227
    }
228
 
229
    ValueLatticeElement Res;
230
    Res.markConstantRange(std::move(CR),
231
                          MergeOptions().setMayIncludeUndef(MayIncludeUndef));
232
    return Res;
233
  }
234
  static ValueLatticeElement getOverdefined() {
235
    ValueLatticeElement Res;
236
    Res.markOverdefined();
237
    return Res;
238
  }
239
 
240
  bool isUndef() const { return Tag == undef; }
241
  bool isUnknown() const { return Tag == unknown; }
242
  bool isUnknownOrUndef() const { return Tag == unknown || Tag == undef; }
243
  bool isConstant() const { return Tag == constant; }
244
  bool isNotConstant() const { return Tag == notconstant; }
245
  bool isConstantRangeIncludingUndef() const {
246
    return Tag == constantrange_including_undef;
247
  }
248
  /// Returns true if this value is a constant range. Use \p UndefAllowed to
249
  /// exclude non-singleton constant ranges that may also be undef. Note that
250
  /// this function also returns true if the range may include undef, but only
251
  /// contains a single element. In that case, it can be replaced by a constant.
252
  bool isConstantRange(bool UndefAllowed = true) const {
253
    return Tag == constantrange || (Tag == constantrange_including_undef &&
254
                                    (UndefAllowed || Range.isSingleElement()));
255
  }
256
  bool isOverdefined() const { return Tag == overdefined; }
257
 
258
  Constant *getConstant() const {
259
    assert(isConstant() && "Cannot get the constant of a non-constant!");
260
    return ConstVal;
261
  }
262
 
263
  Constant *getNotConstant() const {
264
    assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
265
    return ConstVal;
266
  }
267
 
268
  /// Returns the constant range for this value. Use \p UndefAllowed to exclude
269
  /// non-singleton constant ranges that may also be undef. Note that this
270
  /// function also returns a range if the range may include undef, but only
271
  /// contains a single element. In that case, it can be replaced by a constant.
272
  const ConstantRange &getConstantRange(bool UndefAllowed = true) const {
273
    assert(isConstantRange(UndefAllowed) &&
274
           "Cannot get the constant-range of a non-constant-range!");
275
    return Range;
276
  }
277
 
278
  std::optional<APInt> asConstantInteger() const {
279
    if (isConstant() && isa<ConstantInt>(getConstant())) {
280
      return cast<ConstantInt>(getConstant())->getValue();
281
    } else if (isConstantRange() && getConstantRange().isSingleElement()) {
282
      return *getConstantRange().getSingleElement();
283
    }
284
    return std::nullopt;
285
  }
286
 
287
  bool markOverdefined() {
288
    if (isOverdefined())
289
      return false;
290
    destroy();
291
    Tag = overdefined;
292
    return true;
293
  }
294
 
295
  bool markUndef() {
296
    if (isUndef())
297
      return false;
298
 
299
    assert(isUnknown());
300
    Tag = undef;
301
    return true;
302
  }
303
 
304
  bool markConstant(Constant *V, bool MayIncludeUndef = false) {
305
    if (isa<UndefValue>(V))
306
      return markUndef();
307
 
308
    if (isConstant()) {
309
      assert(getConstant() == V && "Marking constant with different value");
310
      return false;
311
    }
312
 
313
    if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
314
      return markConstantRange(
315
          ConstantRange(CI->getValue()),
316
          MergeOptions().setMayIncludeUndef(MayIncludeUndef));
317
 
318
    assert(isUnknown() || isUndef());
319
    Tag = constant;
320
    ConstVal = V;
321
    return true;
322
  }
323
 
324
  bool markNotConstant(Constant *V) {
325
    assert(V && "Marking constant with NULL");
326
    if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
327
      return markConstantRange(
328
          ConstantRange(CI->getValue() + 1, CI->getValue()));
329
 
330
    if (isa<UndefValue>(V))
331
      return false;
332
 
333
    if (isNotConstant()) {
334
      assert(getNotConstant() == V && "Marking !constant with different value");
335
      return false;
336
    }
337
 
338
    assert(isUnknown());
339
    Tag = notconstant;
340
    ConstVal = V;
341
    return true;
342
  }
343
 
344
  /// Mark the object as constant range with \p NewR. If the object is already a
345
  /// constant range, nothing changes if the existing range is equal to \p
346
  /// NewR and the tag. Otherwise \p NewR must be a superset of the existing
347
  /// range or the object must be undef. The tag is set to
348
  /// constant_range_including_undef if either the existing value or the new
349
  /// range may include undef.
350
  bool markConstantRange(ConstantRange NewR,
351
                         MergeOptions Opts = MergeOptions()) {
352
    assert(!NewR.isEmptySet() && "should only be called for non-empty sets");
353
 
354
    if (NewR.isFullSet())
355
      return markOverdefined();
356
 
357
    ValueLatticeElementTy OldTag = Tag;
358
    ValueLatticeElementTy NewTag =
359
        (isUndef() || isConstantRangeIncludingUndef() || Opts.MayIncludeUndef)
360
            ? constantrange_including_undef
361
            : constantrange;
362
    if (isConstantRange()) {
363
      Tag = NewTag;
364
      if (getConstantRange() == NewR)
365
        return Tag != OldTag;
366
 
367
      // Simple form of widening. If a range is extended multiple times, go to
368
      // overdefined.
369
      if (Opts.CheckWiden && ++NumRangeExtensions > Opts.MaxWidenSteps)
370
        return markOverdefined();
371
 
372
      assert(NewR.contains(getConstantRange()) &&
373
             "Existing range must be a subset of NewR");
374
      Range = std::move(NewR);
375
      return true;
376
    }
377
 
378
    assert(isUnknown() || isUndef());
379
 
380
    NumRangeExtensions = 0;
381
    Tag = NewTag;
382
    new (&Range) ConstantRange(std::move(NewR));
383
    return true;
384
  }
385
 
386
  /// Updates this object to approximate both this object and RHS. Returns
387
  /// true if this object has been changed.
388
  bool mergeIn(const ValueLatticeElement &RHS,
389
               MergeOptions Opts = MergeOptions()) {
390
    if (RHS.isUnknown() || isOverdefined())
391
      return false;
392
    if (RHS.isOverdefined()) {
393
      markOverdefined();
394
      return true;
395
    }
396
 
397
    if (isUndef()) {
398
      assert(!RHS.isUnknown());
399
      if (RHS.isUndef())
400
        return false;
401
      if (RHS.isConstant())
402
        return markConstant(RHS.getConstant(), true);
403
      if (RHS.isConstantRange())
404
        return markConstantRange(RHS.getConstantRange(true),
405
                                 Opts.setMayIncludeUndef());
406
      return markOverdefined();
407
    }
408
 
409
    if (isUnknown()) {
410
      assert(!RHS.isUnknown() && "Unknow RHS should be handled earlier");
411
      *this = RHS;
412
      return true;
413
    }
414
 
415
    if (isConstant()) {
416
      if (RHS.isConstant() && getConstant() == RHS.getConstant())
417
        return false;
418
      if (RHS.isUndef())
419
        return false;
420
      markOverdefined();
421
      return true;
422
    }
423
 
424
    if (isNotConstant()) {
425
      if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant())
426
        return false;
427
      markOverdefined();
428
      return true;
429
    }
430
 
431
    auto OldTag = Tag;
432
    assert(isConstantRange() && "New ValueLattice type?");
433
    if (RHS.isUndef()) {
434
      Tag = constantrange_including_undef;
435
      return OldTag != Tag;
436
    }
437
 
438
    if (!RHS.isConstantRange()) {
439
      // We can get here if we've encountered a constantexpr of integer type
440
      // and merge it with a constantrange.
441
      markOverdefined();
442
      return true;
443
    }
444
 
445
    ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
446
    return markConstantRange(
447
        std::move(NewR),
448
        Opts.setMayIncludeUndef(RHS.isConstantRangeIncludingUndef()));
449
  }
450
 
451
  // Compares this symbolic value with Other using Pred and returns either
452
  /// true, false or undef constants, or nullptr if the comparison cannot be
453
  /// evaluated.
454
  Constant *getCompare(CmpInst::Predicate Pred, Type *Ty,
455
                       const ValueLatticeElement &Other,
456
                       const DataLayout &DL) const;
457
 
458
  unsigned getNumRangeExtensions() const { return NumRangeExtensions; }
459
  void setNumRangeExtensions(unsigned N) { NumRangeExtensions = N; }
460
};
461
 
462
static_assert(sizeof(ValueLatticeElement) <= 40,
463
              "size of ValueLatticeElement changed unexpectedly");
464
 
465
raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val);
466
} // end namespace llvm
467
#endif