31#ifndef ENZYME_TYPE_ANALYSIS_TYPE_TREE_H
32#define ENZYME_TYPE_ANALYSIS_TYPE_TREE_H 1
34#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/raw_ostream.h"
53static inline std::string
to_string(
const std::vector<int> x) {
54 std::string out =
"[";
55 for (
unsigned i = 0; i < x.size(); ++i) {
58 out += std::to_string(x[i]);
72class TypeTree :
public std::enable_shared_from_this<TypeTree> {
76 std::vector<int> minIndices;
82 mapping.insert(std::pair<
const std::vector<int>,
ConcreteType>({}, dat));
88 assert(
str[0] ==
'{');
98 assert(
str[0] ==
'[');
101 std::vector<int> idxs;
103 while (
str[0] ==
' ')
111 bool failed =
str.consumeInteger(10, idx);
116 while (
str[0] ==
' ')
124 while (
str[0] ==
' ')
127 assert(
str[0] ==
':');
130 while (
str[0] ==
' ')
133 auto endval =
str.find(
',');
134 auto endval2 =
str.find(
'}');
135 auto endval3 =
str.find(
' ');
137 if (endval2 != StringRef::npos &&
138 (endval == StringRef::npos || endval2 < endval))
140 if (endval3 != StringRef::npos &&
141 (endval == StringRef::npos || endval3 < endval))
143 assert(endval != StringRef::npos);
145 auto tystr =
str.substr(0, endval);
149 Result.mapping.emplace(idxs, CT);
150 if (Result.minIndices.size() < idxs.size()) {
151 for (
size_t i = Result.minIndices.size(), end = idxs.size(); i < end;
153 Result.minIndices.push_back(idxs[i]);
156 for (
size_t i = 0, end = idxs.size(); i < end; ++i) {
157 if (idxs[i] < Result.minIndices[i])
158 Result.minIndices[i] = idxs[i];
161 while (
str[0] ==
' ')
178 auto Found0 = mapping.find(Seq);
179 if (Found0 != mapping.end())
180 return Found0->second;
181 size_t Len = Seq.size();
185 std::vector<std::vector<int>> todo[2];
186 todo[0].push_back({});
188 for (
size_t i = 0, Len = Seq.size(); i < Len - 1; ++i) {
189 for (
auto prev : todo[parity]) {
191 if (mapping.find(prev) != mapping.end())
192 todo[1 - parity].push_back(prev);
194 prev.back() = Seq[i];
195 if (mapping.find(prev) != mapping.end())
196 todo[1 - parity].push_back(prev);
199 todo[parity].clear();
204 for (
auto prev : todo[parity]) {
206 auto Found = mapping.find(prev);
207 if (Found != mapping.end())
208 return Found->second;
210 prev.back() = Seq[i];
211 Found = mapping.find(prev);
212 if (Found != mapping.end())
213 return Found->second;
222 std::vector<int> offsets = {-1};
224 auto found = mapping.find(offsets);
225 if (found == mapping.end())
229 offsets.push_back(-1);
235 bool PointerIntSame =
false) {
236 size_t SeqSize = Seq.size();
245 <<
" pointer lookups deep dt:" <<
str()
252 mapping.insert(std::pair<
const std::vector<int>,
ConcreteType>(Seq, CT));
259 std::vector<int> tmp(Seq);
260 while (tmp.size() > 0) {
261 tmp.erase(tmp.end() - 1);
262 auto found = mapping.find(tmp);
263 if (found != mapping.end()) {
267 llvm::errs() <<
"FAILED CT: " <<
str()
268 <<
" adding Seq: " <<
to_string(Seq) <<
": "
276 bool changed =
false;
280 for (
const auto &pair : llvm::make_early_inc_range(mapping)) {
281 if (pair.first.size() == SeqSize) {
284 bool newMoreGeneralThanOld =
true;
287 bool oldMoreGeneralThanNew =
true;
288 for (
unsigned i = 0; i < SeqSize; i++) {
289 if (pair.first[i] == Seq[i])
292 oldMoreGeneralThanNew =
false;
293 }
else if (pair.first[i] == -1) {
294 newMoreGeneralThanOld =
false;
296 oldMoreGeneralThanNew =
false;
297 newMoreGeneralThanOld =
false;
302 if (oldMoreGeneralThanNew) {
304 if (CT == pair.second)
326 llvm::errs() <<
"inserting into : " <<
str() <<
" with "
328 llvm_unreachable(
"illegal insertion");
329 }
else if (newMoreGeneralThanOld) {
337 mapping.erase(pair.first);
349 mapping.erase(pair.first);
361 llvm::errs() <<
"inserting into : " <<
str() <<
" with "
363 llvm_unreachable(
"illegal insertion");
369 bool possibleDeletion =
false;
371 (minIndices.size() <= SeqSize) ? minIndices.size() : SeqSize;
372 for (
size_t i = 0; i < minLen; i++) {
373 if (minIndices[i] > Seq[i]) {
375 possibleDeletion =
true;
376 minIndices[i] = Seq[i];
380 if (minIndices.size() < SeqSize) {
381 for (
size_t i = minIndices.size(), end = SeqSize; i < end; ++i) {
382 minIndices.push_back(Seq[i]);
386 if (possibleDeletion) {
387 for (
const auto &pair : llvm::make_early_inc_range(mapping)) {
389 bool mustKeep =
false;
390 bool considerErase =
false;
391 for (
int val : pair.first) {
393 if (val == minIndices[i]) {
397 considerErase =
true;
401 if (!mustKeep && considerErase) {
402 mapping.erase(pair.first);
410 bool considerErase =
false;
411 for (
auto val : Seq) {
413 if (val == minIndices[i]) {
417 considerErase =
true;
421 if (considerErase && !keep)
423 mapping.insert(std::pair<
const std::vector<int>,
ConcreteType>(Seq, CT));
433 for (
const auto &pair : mapping) {
436 assert(pair.second.isKnown());
439 return mapping.size() != 0;
444 for (
auto &pair : mapping) {
447 assert(pair.second.isKnown());
448 if (pair.first.size() == 0) {
461 for (
auto &pair : mapping) {
463 vd.
insert(pair.first, pair.second);
473 Result.minIndices.reserve(1 + minIndices.size());
474 Result.minIndices.push_back(Off);
475 for (
auto midx : minIndices)
476 Result.minIndices.push_back(midx);
479 Result.minIndices.pop_back();
486 EmitWarning(
"TypeAnalysisDepthLimit", *orig, *orig,
488 " pointer lookups deep dt: ",
str(),
" only(", Off,
")");
491 <<
" pointer lookups deep dt:" <<
str() <<
" only("
498 for (
const auto &pair : mapping) {
501 std::vector<int> Vec;
502 Vec.reserve(pair.first.size() + 1);
504 for (
auto Val : pair.first)
506 Result.mapping.insert(
507 std::pair<
const std::vector<int>,
ConcreteType>(Vec, pair.second));
516 for (
const auto &pair : mapping) {
517 if (pair.first.size() == 0) {
518 llvm::errs() <<
str() <<
"\n";
520 assert(pair.first.size() != 0);
522 if (pair.first[0] == -1) {
523 std::vector<int> next(pair.first.begin() + 1, pair.first.end());
524 Result.mapping.insert(
525 std::pair<
const std::vector<int>,
ConcreteType>(next, pair.second));
526 for (
size_t i = 0, Len = next.size(); i < Len; ++i) {
527 if (i == Result.minIndices.size())
528 Result.minIndices.push_back(next[i]);
529 else if (next[i] < Result.minIndices[i])
530 Result.minIndices[i] = next[i];
534 for (
const auto &pair : mapping) {
535 if (pair.first[0] == 0) {
536 std::vector<int> next(pair.first.begin() + 1, pair.first.end());
540 Result.
orIn(next, pair.second);
563 for (
const auto &pair : mapping) {
564 assert(pair.first.size() != 0);
566 if (pair.first[0] == -1) {
569 auto next = pair.first;
570 for (
size_t i = 0; i < start; ++i) {
572 Result.
orIn(next, pair.second);
574 for (
size_t i = end; i < len; ++i) {
576 Result.
orIn(next, pair.second);
578 }
else if ((
size_t)pair.first[0] < start ||
579 ((
size_t)pair.first[0] >= end &&
580 (
size_t)pair.first[0] < len)) {
583 Result.
insert(pair.first, pair.second);
596 std::map<std::vector<int>, std::map<ConcreteType, std::set<int>>> staging;
598 for (
const auto &pair : mapping) {
599 assert(pair.first.size() != 0);
602 if (pair.first[0] != 0 && pair.first[0] != -1)
605 if (pair.first.size() == 1) {
611 if (pair.first[1] == -1) {
613 if ((
size_t)pair.first[1] >= len)
617 std::vector<int> next(pair.first.begin() + 2, pair.first.end());
619 staging[next][pair.second].insert(pair.first[1]);
623 for (
auto &pair : staging) {
624 auto &pnext = pair.first;
625 for (
auto &pair2 : pair.second) {
626 auto dt = pair2.first;
627 const auto &set = pair2.second;
629 bool legalCombine = set.count(-1);
635 if (pnext.size() > 0) {
636 chunk = dl.getPointerSizeInBits() / 8;
638 if (
auto flt = dt.isFloat()) {
639 chunk = dl.getTypeSizeInBits(flt) / 8;
641 chunk = dl.getPointerSizeInBits() / 8;
646 for (
size_t i = 0; i < len; i += chunk) {
648 legalCombine =
false;
654 std::vector<int> next;
655 next.reserve(pnext.size() + 1);
661 Result.
insert(next, dt,
true);
677 bool canonicalized =
true;
678 for (
const auto &pair : mapping) {
679 assert(pair.first.size() != 0);
680 if (pair.first[0] != -1) {
681 canonicalized =
false;
689 std::map<const std::vector<int>, std::map<ConcreteType, std::set<int>>>
692 for (
const auto &pair : mapping) {
694 std::vector<int> next(pair.first.begin() + 1, pair.first.end());
695 if (pair.first[0] != -1) {
696 if ((
size_t)pair.first[0] >= len) {
697 llvm::errs() <<
str() <<
"\n";
698 llvm::errs() <<
" canonicalizing " << len <<
"\n";
699 llvm::report_fatal_error(
"Canonicalization failed");
702 staging[next][pair.second].insert(pair.first[0]);
706 std::map<const std::vector<int>,
ConcreteType> unCombinedToAdd;
709 std::map<const std::vector<int>,
ConcreteType> combinedToAdd;
711 for (
const auto &pair : staging) {
712 auto &pnext = pair.first;
713 for (
const auto &pair2 : pair.second) {
714 auto dt = pair2.first;
715 const auto &set = pair2.second;
717 bool legalCombine =
false;
720 if (!set.count(-1)) {
722 if (pnext.size() > 0) {
723 chunk = dl.getPointerSizeInBits() / 8;
725 if (
auto flt = dt.isFloat()) {
726 chunk = dl.getTypeSizeInBits(flt) / 8;
728 chunk = dl.getPointerSizeInBits() / 8;
733 for (
size_t i = 0; i < len; i += chunk) {
735 legalCombine =
false;
741 std::vector<int> next;
742 next.reserve(pnext.size() + 1);
748 combinedToAdd.emplace(next, dt);
752 unCombinedToAdd.emplace(next, dt);
760 if (combinedToAdd.size() == 0) {
766 mapping = std::move(unCombinedToAdd);
767 if (minIndices.size() > 0) {
777 for (
const auto &pair : combinedToAdd) {
778 insert(pair.first, pair.second);
788 for (
const auto &pair : mapping) {
790 assert(pair.first.size() != 0);
793 if (pair.first[0] != 0 && pair.first[0] != -1)
796 if (pair.first.size() == 1) {
799 dat.
insert(pair.first, pair.second);
806 if (pair.first[1] == -1) {
807 dat.
insert(pair.first, pair.second);
814 llvm::Type *
IsAllFloat(
const size_t size,
const llvm::DataLayout &dl)
const {
816 if (
auto FT = m1.isFloat())
821 if (
auto flt = m0.isFloat()) {
822 size_t chunk = dl.getTypeSizeInBits(flt) / 8;
823 for (
size_t i = chunk; i < size; i += chunk) {
825 if (
auto f2 = mx.isFloat()) {
841 const int maxSize,
size_t addOffset = 0)
const {
846 if (minIndices.size() == 0)
876 Result.minIndices.resize(minIndices.size(), INT_MAX);
878 for (
const auto &pair : mapping) {
879 if (pair.first.size() == 0) {
882 Result.mapping.emplace(pair.first, pair.second);
886 llvm::errs() <<
"could not unmerge " <<
str() <<
"\n";
887 assert(0 &&
"ShiftIndices called on a nonpointer/anything");
888 llvm_unreachable(
"ShiftIndices called on a nonpointer/anything");
891 int next0 = pair.first[0];
899 if (addOffset != 0) {
906 Result.minIndices[0] = addOffset;
907 for (
size_t i = 1, sz = pair.first.size(); i < sz; i++)
908 if (pair.first[i] < Result.minIndices[i])
909 Result.minIndices[i] = pair.first[i];
914 if (next0 < offset) {
920 if (next0 >= maxSize)
926 if (next0 < Result.minIndices[0])
927 Result.minIndices[0] = next0;
928 for (
size_t i = 1, sz = pair.first.size(); i < sz; i++)
929 if (pair.first[i] < Result.minIndices[i])
930 Result.minIndices[i] = pair.first[i];
934 size_t maxInsertedDepth = 0;
937 for (
const auto &pair : mapping) {
938 if (pair.first.size() == 0)
941 int next0 = pair.first[0];
949 if (addOffset != 0) {
960 if (next0 < offset) {
966 if (next0 >= maxSize)
976 bool minIndex = next0 == Result.minIndices[0];
978 for (
size_t i = 1; i < pair.first.size(); i++) {
979 if (pair.first[i] == Result.minIndices[i]) {
988 std::vector<int> next(pair.first);
990 Result.mapping.emplace(next, pair.second);
991 if (next.size() > maxInsertedDepth)
992 maxInsertedDepth = next.size();
997 for (
const auto &pair : mapping) {
998 if (pair.first.size() == 0)
1000 if (pair.first[0] != -1)
1004 std::vector<int> next(pair.first);
1006 if (
auto flt = op.isFloat()) {
1007 chunk = dl.getTypeSizeInBits(flt) / 8;
1009 chunk = dl.getPointerSizeInBits() / 8;
1011 auto offincr = (chunk - offset % chunk) % chunk;
1012 bool inserted =
false;
1013 for (
int i = offincr; i < maxSize; i += chunk) {
1014 next[0] = i + addOffset;
1019 auto found = Result.mapping.find(next);
1020 if (found != Result.mapping.end()) {
1023 if (prev.
orIn(found->second,
false))
1024 found->second = prev;
1026 Result.mapping.emplace(next, pair.second);
1030 if (inserted && next.size() > maxInsertedDepth)
1031 maxInsertedDepth = next.size();
1036 Result.minIndices.resize(maxInsertedDepth);
1043 Result.minIndices.reserve(minIndices.size());
1044 for (
const auto &pair : mapping) {
1047 Result.mapping.insert(pair);
1048 for (
size_t i = 0, Len = pair.first.size(); i < Len; ++i) {
1049 if (i == Result.minIndices.size())
1050 Result.minIndices.push_back(pair.first[i]);
1051 else if (pair.first[i] < Result.minIndices[i])
1052 Result.minIndices[i] = pair.first[i];
1061 for (
const auto &pair : mapping) {
1064 std::vector<int> nex = pair.first;
1068 dat.
insert(nex, pair.second);
1075 for (
auto &pair : mapping) {
1085 for (
const auto &pair : mapping) {
1088 dat.
insert(pair.first, pair.second);
1100 minIndices = RHS.minIndices;
1102 for (
const auto &elems : RHS.mapping) {
1103 mapping.emplace(elems);
1109 bool PointerIntSame,
bool &LegalOr) {
1113 bool subchanged = CT.
checkedOrIn(RHS, PointerIntSame, LegalOr);
1119 auto SeqSize = Seq.size();
1123 for (
size_t i = 0; i < SeqSize; ++i) {
1124 std::vector<int> tmp(Seq.begin(), Seq.end() - 1 - i);
1125 auto found = mapping.find(tmp);
1126 if (found != mapping.end()) {
1138 for (
const auto &pair : llvm::make_early_inc_range(mapping)) {
1139 if (pair.first.size() == SeqSize) {
1142 bool newMoreGeneralThanOld =
true;
1145 bool oldMoreGeneralThanNew =
true;
1146 for (
unsigned i = 0; i < SeqSize; i++) {
1147 if (pair.first[i] == Seq[i])
1150 oldMoreGeneralThanNew =
false;
1151 }
else if (pair.first[i] == -1) {
1152 newMoreGeneralThanOld =
false;
1154 oldMoreGeneralThanNew =
false;
1155 newMoreGeneralThanOld =
false;
1160 if (oldMoreGeneralThanNew) {
1162 if (CT == pair.second)
1182 if (newMoreGeneralThanOld)
1183 mapping.erase(pair.first);
1191 }
else if (newMoreGeneralThanOld) {
1198 mapping.erase(pair.first);
1209 mapping.erase(pair.first);
1233 bool PointerIntSame =
false) {
1234 bool LegalOr =
true;
1235 bool Result =
checkedOrIn(Seq, RHS, PointerIntSame, LegalOr);
1246 bool changed =
false;
1247 for (
auto &pair : RHS.mapping) {
1248 changed |=
checkedOrIn(pair.first, pair.second, PointerIntSame, LegalOr);
1258 bool Result =
checkedOrIn(RHS, PointerIntSame, Legal);
1260 llvm::errs() <<
"Illegal orIn: " <<
str() <<
" right: " << RHS.
str()
1261 <<
" PointerIntSame=" << PointerIntSame <<
"\n";
1262 assert(0 &&
"Performed illegal ConcreteType::orIn");
1263 llvm_unreachable(
"Performed illegal ConcreteType::orIn");
1273 bool Result =
checkedOrIn(Seq, CT, PointerIntSame, Legal);
1275 llvm::errs() <<
"Illegal orIn: " <<
str() <<
" right: " <<
to_string(Seq)
1276 <<
" CT: " << CT.
str()
1277 <<
" PointerIntSame=" << PointerIntSame <<
"\n";
1278 assert(0 &&
"Performed illegal ConcreteType::orIn");
1279 llvm_unreachable(
"Performed illegal ConcreteType::orIn");
1288 return orIn(RHS,
false);
1295 bool changed =
false;
1297 for (
auto &pair : llvm::make_early_inc_range(mapping)) {
1299 auto fd = RHS.mapping.find(pair.first);
1300 if (fd != RHS.mapping.end()) {
1303 changed = (pair.second &= other);
1305 mapping.erase(pair.first);
1321 llvm::BinaryOperator::BinaryOps Op) {
1322 bool changed =
false;
1324 for (
auto &pair : llvm::make_early_inc_range(mapping)) {
1329 if (pair.first.size() > 0) {
1330 mapping.erase(pair.first);
1338 auto found = RHS.mapping.find(pair.first);
1339 if (found != RHS.mapping.end()) {
1340 RightCT = found->second;
1342 bool SubLegal =
true;
1343 changed |= CT.
binopIn(SubLegal, RightCT, Op);
1349 mapping.erase(pair.first);
1356 for (
auto &pair : RHS.mapping) {
1361 if (pair.first.size() > 0) {
1365 if (mapping.find(pair.first) == RHS.mapping.end()) {
1367 bool SubLegal =
true;
1368 changed |= CT.
binopIn(SubLegal, pair.second, Op);
1374 mapping.insert(std::make_pair(pair.first, CT));
1384 std::string out =
"{";
1386 for (
auto &pair : mapping) {
1391 for (
unsigned i = 0; i < pair.first.size(); ++i) {
1394 out += std::to_string(pair.first[i]);
1396 out +=
"]:" + pair.second.str();
1403 llvm::MDNode *
toMD(llvm::LLVMContext &ctx) {
1404 llvm::SmallVector<llvm::Metadata *, 1> subMD;
1405 std::map<int, TypeTree> todo;
1407 for (
auto &pair : mapping) {
1408 if (pair.first.size() == 0) {
1412 auto next(pair.first);
1413 next.erase(next.begin());
1414 todo[pair.first[0]].mapping.insert(std::make_pair(next, pair.second));
1416 subMD.push_back(llvm::MDString::get(ctx, base.
str()));
1417 for (
auto pair : todo) {
1418 subMD.push_back(llvm::ConstantAsMetadata::get(
1419 llvm::ConstantInt::get(llvm::IntegerType::get(ctx, 32), pair.first)));
1420 subMD.push_back(pair.second.toMD(ctx));
1422 return llvm::MDNode::get(ctx, subMD);
1427 llvm::cast<llvm::MDString>(md->getOperand(0))->getString(),
1430 mapping.insert(std::make_pair(prev, base));
1431 for (
size_t i = 1; i < md->getNumOperands(); i += 2) {
1432 auto off = llvm::cast<llvm::ConstantInt>(
1433 llvm::cast<llvm::ConstantAsMetadata>(md->getOperand(i))
1437 next.push_back((
int)off);
1438 insertFromMD(llvm::cast<llvm::MDNode>(md->getOperand(i + 1)), next);
1444 std::vector<int> off;
std::map< const std::vector< int >, const TypeResult > TypeTreeMapType
llvm::cl::opt< unsigned > EnzymeMaxTypeDepth
static std::string to_string(const std::vector< int > x)
Helper function to print a vector of ints to a string.
std::map< const std::vector< int >, ConcreteType > ConcreteTypeMapType
llvm::cl::opt< bool > EnzymeTypeWarning
llvm::cl::opt< int > MaxTypeOffset
Maximum offset for type trees to keep.
std::shared_ptr< const TypeTree > TypeResult
LLVMValueRef(* CustomErrorHandler)(const char *, LLVMValueRef, ErrorType, const void *, LLVMValueRef, LLVMBuilderRef)
void EmitWarning(llvm::StringRef RemarkName, const llvm::DiagnosticLocation &Loc, const llvm::BasicBlock *BB, const Args &...args)
Concrete SubType of a given value.
bool binopIn(bool &Legal, const ConcreteType RHS, llvm::BinaryOperator::BinaryOps Op)
Set this to the logical binop of itself and RHS, using the Binop Op, returning true if this was chang...
std::string str() const
Convert the ConcreteType to a string.
bool checkedOrIn(const ConcreteType CT, bool PointerIntSame, bool &LegalOr)
Set this to the logical or of itself and CT, returning whether this value changed Setting PointerIntS...
bool orIn(const ConcreteType CT, bool PointerIntSame)
Set this to the logical or of itself and CT, returning whether this value changed Setting PointerIntS...
Class representing the underlying types of values as sequences of offsets to a ConcreteType.
bool orIn(const TypeTree &RHS, bool PointerIntSame)
Set this to the logical or of itself and RHS, returning whether this value changed Setting PointerInt...
TypeTree Only(int Off, llvm::Instruction *orig) const
Prepend an offset to all mappings.
bool operator&=(const TypeTree &RHS)
Set this to the logical and of itself and RHS, returning whether this value changed If this and RHS a...
TypeTree Data0() const
Peel off the outermost index at offset 0.
ConcreteType operator[](const std::vector< int > Seq) const
Lookup the underlying ConcreteType at a given offset sequence or Unknown if none exists.
bool andIn(const TypeTree &RHS)
Set this to the logical and of itself and RHS, returning whether this value changed If this and RHS a...
const ConcreteTypeMapType & getMapping() const
Utility helper to lookup the mapping.
static TypeTree parse(llvm::StringRef str, llvm::LLVMContext &ctx)
bool checkedOrIn(const TypeTree &RHS, bool PointerIntSame, bool &LegalOr)
Set this to the logical or of itself and RHS, returning whether this value changed Setting PointerInt...
TypeTree ShiftIndices(const llvm::DataLayout &dl, const int offset, const int maxSize, size_t addOffset=0) const
Replace mappings in the range in [offset, offset+maxSize] with those in.
TypeTree Lookup(size_t len, const llvm::DataLayout &dl) const
Select all submappings whose first index is in range [0, len) and remove the first index.
void ReplaceIntWithAnything()
Replace all integer subtypes with anything.
llvm::MDNode * toMD(llvm::LLVMContext &ctx)
ConcreteType Inner0() const
Optimized version of Data0()[{}].
bool operator|=(const TypeTree &RHS)
Set this to the logical or of itself and RHS, returning whether this value changed This assumes that ...
TypeTree ReplaceMinus() const
Replace -1 with 0.
bool operator==(const TypeTree &RHS) const
Chceck equality of two TypeTrees.
llvm::Type * IsAllFloat(const size_t size, const llvm::DataLayout &dl) const
static TypeTree fromMD(llvm::MDNode *md)
bool isKnownPastPointer() const
Whether this TypeTree knows any non-pointer information.
TypeTree Clear(size_t start, size_t end, size_t len) const
Remove any mappings in the range [start, end) or [len, inf) This function has special handling for -1...
TypeTree KeepMinusOne(bool &legal) const
Keep only pointers (or anything's) to a repeated value (represented by -1)
bool orIn(const std::vector< int > Seq, ConcreteType CT, bool PointerIntSame)
Set this to the logical or of itself and RHS, returning whether this value changed Setting PointerInt...
TypeTree JustInt() const
Select only the Integer ConcreteTypes.
TypeTree JustAnything() const
Keep only mappings where the type is an Anything
bool checkedOrIn(const std::vector< int > &Seq, ConcreteType RHS, bool PointerIntSame, bool &LegalOr)
void CanonicalizeInPlace(size_t len, const llvm::DataLayout &dl)
Given that this tree represents something of at most size len, canonicalize this, creating -1's where...
std::string str() const
Returns a string representation of this TypeTree.
bool isKnown() const
Whether this TypeTree contains any information.
bool orIn(const std::vector< int > &Seq, ConcreteType RHS, bool PointerIntSame=false)
bool insert(const std::vector< int > Seq, ConcreteType CT, bool PointerIntSame=false)
Return if changed.
void insertFromMD(llvm::MDNode *md, const std::vector< int > &prev={})
bool binopIn(bool &Legal, const TypeTree &RHS, llvm::BinaryOperator::BinaryOps Op)
Set this to the logical binop of itself and RHS, using the Binop Op, returning true if this was chang...
TypeTree(ConcreteType dat)
bool operator<(const TypeTree &vd) const
How this TypeTree compares with another.
TypeTree PurgeAnything() const
Keep only mappings where the type is not an Anything
bool operator=(const TypeTree &RHS)
Set this to another TypeTree, returning if this was changed.
bool IsFullyDetermined() const