ValueLattice.h 15 KB

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