Coverage Report

Created: 2018-12-11 00:00

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/Analysis/ValueLattice.h
Line
Count
Source (jump to first uncovered line)
1
//===- ValueLattice.h - Value constraint analysis ---------------*- C++ -*-===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#ifndef LLVM_ANALYSIS_VALUELATTICE_H
11
#define LLVM_ANALYSIS_VALUELATTICE_H
12
13
#include "llvm/IR/ConstantRange.h"
14
#include "llvm/IR/Constants.h"
15
//
16
//===----------------------------------------------------------------------===//
17
//                               ValueLatticeElement
18
//===----------------------------------------------------------------------===//
19
20
/// This class represents lattice values for constants.
21
///
22
/// FIXME: This is basically just for bringup, this can be made a lot more rich
23
/// in the future.
24
///
25
26
namespace llvm {
27
class ValueLatticeElement {
28
  enum ValueLatticeElementTy {
29
    /// This Value has no known value yet.  As a result, this implies the
30
    /// producing instruction is dead.  Caution: We use this as the starting
31
    /// state in our local meet rules.  In this usage, it's taken to mean
32
    /// "nothing known yet".
33
    undefined,
34
35
    /// This Value has a specific constant value.  (For constant integers,
36
    /// constantrange is used instead.  Integer typed constantexprs can appear
37
    /// as constant.)
38
    constant,
39
40
    /// This Value is known to not have the specified value.  (For constant
41
    /// integers, constantrange is used instead.  As above, integer typed
42
    /// constantexprs can appear here.)
43
    notconstant,
44
45
    /// The Value falls within this range. (Used only for integer typed values.)
46
    constantrange,
47
48
    /// We can not precisely model the dynamic values this value might take.
49
    overdefined
50
  };
51
52
  ValueLatticeElementTy Tag;
53
54
  /// The union either stores a pointer to a constant or a constant range,
55
  /// associated to the lattice element. We have to ensure that Range is
56
  /// initialized or destroyed when changing state to or from constantrange.
57
  union {
58
    Constant *ConstVal;
59
    ConstantRange Range;
60
  };
61
62
public:
63
  // Const and Range are initialized on-demand.
64
259M
  ValueLatticeElement() : Tag(undefined) {}
65
66
  /// Custom destructor to ensure Range is properly destroyed, when the object
67
  /// is deallocated.
68
334M
  ~ValueLatticeElement() {
69
334M
    switch (Tag) {
70
334M
    case overdefined:
71
301M
    case undefined:
72
301M
    case constant:
73
301M
    case notconstant:
74
301M
      break;
75
301M
    case constantrange:
76
32.4M
      Range.~ConstantRange();
77
32.4M
      break;
78
334M
    };
79
334M
  }
80
81
  /// Custom copy constructor, to ensure Range gets initialized when
82
  /// copying a constant range lattice element.
83
74.5M
  ValueLatticeElement(const ValueLatticeElement &Other) : Tag(undefined) {
84
74.5M
    *this = Other;
85
74.5M
  }
86
87
  /// Custom assignment operator, to ensure Range gets initialized when
88
  /// assigning a constant range lattice element.
89
221M
  ValueLatticeElement &operator=(const ValueLatticeElement &Other) {
90
221M
    // If we change the state of this from constant range to non constant range,
91
221M
    // destroy Range.
92
221M
    if (isConstantRange() && 
!Other.isConstantRange()83.4k
)
93
1
      Range.~ConstantRange();
94
221M
95
221M
    // If we change the state of this from a valid ConstVal to another a state
96
221M
    // without a valid ConstVal, zero the pointer.
97
221M
    if ((isConstant() || 
isNotConstant()221M
) &&
!Other.isConstant()12.6k
&&
98
221M
        
!Other.isNotConstant()7.68k
)
99
0
      ConstVal = nullptr;
100
221M
101
221M
    switch (Other.Tag) {
102
221M
    case constantrange:
103
25.5M
      if (!isConstantRange())
104
25.5M
        new (&Range) ConstantRange(Other.Range);
105
83.4k
      else
106
83.4k
        Range = Other.Range;
107
25.5M
      break;
108
221M
    case constant:
109
44.1M
    case notconstant:
110
44.1M
      ConstVal = Other.ConstVal;
111
44.1M
      break;
112
151M
    case overdefined:
113
151M
    case undefined:
114
151M
      break;
115
221M
    }
116
221M
    Tag = Other.Tag;
117
221M
    return *this;
118
221M
  }
119
120
4.23M
  static ValueLatticeElement get(Constant *C) {
121
4.23M
    ValueLatticeElement Res;
122
4.23M
    if (!isa<UndefValue>(C))
123
4.22M
      Res.markConstant(C);
124
4.23M
    return Res;
125
4.23M
  }
126
3.98M
  static ValueLatticeElement getNot(Constant *C) {
127
3.98M
    ValueLatticeElement Res;
128
3.98M
    if (!isa<UndefValue>(C))
129
3.98M
      Res.markNotConstant(C);
130
3.98M
    return Res;
131
3.98M
  }
132
3.21M
  static ValueLatticeElement getRange(ConstantRange CR) {
133
3.21M
    ValueLatticeElement Res;
134
3.21M
    Res.markConstantRange(std::move(CR));
135
3.21M
    return Res;
136
3.21M
  }
137
91.7M
  static ValueLatticeElement getOverdefined() {
138
91.7M
    ValueLatticeElement Res;
139
91.7M
    Res.markOverdefined();
140
91.7M
    return Res;
141
91.7M
  }
142
143
81.3M
  bool isUndefined() const { return Tag == undefined; }
144
384M
  bool isConstant() const { return Tag == constant; }
145
333M
  bool isNotConstant() const { return Tag == notconstant; }
146
419M
  bool isConstantRange() const { return Tag == constantrange; }
147
237M
  bool isOverdefined() const { return Tag == overdefined; }
148
149
56.7k
  Constant *getConstant() const {
150
56.7k
    assert(isConstant() && "Cannot get the constant of a non-constant!");
151
56.7k
    return ConstVal;
152
56.7k
  }
153
154
4.24M
  Constant *getNotConstant() const {
155
4.24M
    assert(isNotConstant() && "Cannot get the constant of a non-notconstant!");
156
4.24M
    return ConstVal;
157
4.24M
  }
158
159
11.3M
  const ConstantRange &getConstantRange() const {
160
11.3M
    assert(isConstantRange() &&
161
11.3M
           "Cannot get the constant-range of a non-constant-range!");
162
11.3M
    return Range;
163
11.3M
  }
164
165
3.04M
  Optional<APInt> asConstantInteger() const {
166
3.04M
    if (isConstant() && 
isa<ConstantInt>(getConstant())407
) {
167
0
      return cast<ConstantInt>(getConstant())->getValue();
168
3.04M
    } else if (isConstantRange() && 
getConstantRange().isSingleElement()123k
) {
169
1.04k
      return *getConstantRange().getSingleElement();
170
1.04k
    }
171
3.04M
    return None;
172
3.04M
  }
173
174
private:
175
98.7M
  void markOverdefined() {
176
98.7M
    if (isOverdefined())
177
0
      return;
178
98.7M
    if (isConstant() || 
isNotConstant()98.7M
)
179
291k
      ConstVal = nullptr;
180
98.7M
    if (isConstantRange())
181
297k
      Range.~ConstantRange();
182
98.7M
    Tag = overdefined;
183
98.7M
  }
184
185
4.22M
  void markConstant(Constant *V) {
186
4.22M
    assert(V && "Marking constant with NULL");
187
4.22M
    if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
188
3.57M
      markConstantRange(ConstantRange(CI->getValue()));
189
3.57M
      return;
190
3.57M
    }
191
656k
    if (isa<UndefValue>(V))
192
0
      return;
193
656k
194
656k
    assert((!isConstant() || getConstant() == V) &&
195
656k
           "Marking constant with different value");
196
656k
    assert(isUndefined());
197
656k
    Tag = constant;
198
656k
    ConstVal = V;
199
656k
  }
200
201
3.98M
  void markNotConstant(Constant *V) {
202
3.98M
    assert(V && "Marking constant with NULL");
203
3.98M
    if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
204
482k
      markConstantRange(ConstantRange(CI->getValue() + 1, CI->getValue()));
205
482k
      return;
206
482k
    }
207
3.50M
    if (isa<UndefValue>(V))
208
0
      return;
209
3.50M
210
3.50M
    assert((!isConstant() || getConstant() != V) &&
211
3.50M
           "Marking constant !constant with same value");
212
3.50M
    assert((!isNotConstant() || getNotConstant() == V) &&
213
3.50M
           "Marking !constant with different value");
214
3.50M
    assert(isUndefined() || isConstant());
215
3.50M
    Tag = notconstant;
216
3.50M
    ConstVal = V;
217
3.50M
  }
218
219
7.51M
  void markConstantRange(ConstantRange NewR) {
220
7.51M
    if (isConstantRange()) {
221
251k
      if (NewR.isEmptySet())
222
0
        markOverdefined();
223
251k
      else {
224
251k
        Range = std::move(NewR);
225
251k
      }
226
251k
      return;
227
251k
    }
228
7.26M
229
7.26M
    assert(isUndefined());
230
7.26M
    if (NewR.isEmptySet())
231
70
      markOverdefined();
232
7.26M
    else {
233
7.26M
      Tag = constantrange;
234
7.26M
      new (&Range) ConstantRange(std::move(NewR));
235
7.26M
    }
236
7.26M
  }
237
238
public:
239
  /// Updates this object to approximate both this object and RHS. Returns
240
  /// true if this object has been changed.
241
16.5M
  bool mergeIn(const ValueLatticeElement &RHS, const DataLayout &DL) {
242
16.5M
    if (RHS.isUndefined() || 
isOverdefined()16.3M
)
243
591k
      return false;
244
15.9M
    if (RHS.isOverdefined()) {
245
6.81M
      markOverdefined();
246
6.81M
      return true;
247
6.81M
    }
248
9.13M
249
9.13M
    if (isUndefined()) {
250
5.95M
      *this = RHS;
251
5.95M
      return !RHS.isUndefined();
252
5.95M
    }
253
3.17M
254
3.17M
    if (isConstant()) {
255
25.7k
      if (RHS.isConstant() && 
getConstant() == RHS.getConstant()15.3k
)
256
11.8k
        return false;
257
13.9k
      markOverdefined();
258
13.9k
      return true;
259
13.9k
    }
260
3.14M
261
3.14M
    if (isNotConstant()) {
262
2.09M
      if (RHS.isNotConstant() && 
getNotConstant() == RHS.getNotConstant()2.08M
)
263
2.08M
        return false;
264
10.9k
      markOverdefined();
265
10.9k
      return true;
266
10.9k
    }
267
1.05M
268
1.05M
    assert(isConstantRange() && "New ValueLattice type?");
269
1.05M
    if (!RHS.isConstantRange()) {
270
8
      // We can get here if we've encountered a constantexpr of integer type
271
8
      // and merge it with a constantrange.
272
8
      markOverdefined();
273
8
      return true;
274
8
    }
275
1.05M
    ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange());
276
1.05M
    if (NewR.isFullSet())
277
148k
      markOverdefined();
278
902k
    else if (NewR == getConstantRange())
279
651k
      return false;
280
251k
    else
281
251k
      markConstantRange(std::move(NewR));
282
1.05M
    
return true399k
;
283
1.05M
  }
284
285
  ConstantInt *getConstantInt() const {
286
    assert(isConstant() && isa<ConstantInt>(getConstant()) &&
287
           "No integer constant");
288
    return cast<ConstantInt>(getConstant());
289
  }
290
291
  /// Compares this symbolic value with Other using Pred and returns either
292
  /// true, false or undef constants, or nullptr if the comparison cannot be
293
  /// evaluated.
294
  Constant *getCompare(CmpInst::Predicate Pred, Type *Ty,
295
2.68M
                       const ValueLatticeElement &Other) const {
296
2.68M
    if (isUndefined() || 
Other.isUndefined()2.62M
)
297
93.1k
      return UndefValue::get(Ty);
298
2.59M
299
2.59M
    if (isConstant() && 
Other.isConstant()6.45k
)
300
5.96k
      return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant());
301
2.58M
302
2.58M
    // Integer constants are represented as ConstantRanges with single
303
2.58M
    // elements.
304
2.58M
    if (!isConstantRange() || 
!Other.isConstantRange()267k
)
305
2.48M
      return nullptr;
306
102k
307
102k
    const auto &CR = getConstantRange();
308
102k
    const auto &OtherCR = Other.getConstantRange();
309
102k
    if (ConstantRange::makeSatisfyingICmpRegion(Pred, OtherCR).contains(CR))
310
53.0k
      return ConstantInt::getTrue(Ty);
311
49.3k
    if (ConstantRange::makeSatisfyingICmpRegion(
312
49.3k
            CmpInst::getInversePredicate(Pred), OtherCR)
313
49.3k
            .contains(CR))
314
49.0k
      return ConstantInt::getFalse(Ty);
315
245
316
245
    return nullptr;
317
245
  }
318
};
319
320
raw_ostream &operator<<(raw_ostream &OS, const ValueLatticeElement &Val);
321
322
} // end namespace llvm
323
#endif