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);
233 void remove(
const std::vector<int> Seq) { mapping.erase(Seq); }
237 bool PointerIntSame =
false) {
238 size_t SeqSize = Seq.size();
247 <<
" pointer lookups deep dt:" <<
str()
254 mapping.insert(std::pair<
const std::vector<int>,
ConcreteType>(Seq, CT));
261 std::vector<int> tmp(Seq);
262 while (tmp.size() > 0) {
263 tmp.erase(tmp.end() - 1);
264 auto found = mapping.find(tmp);
265 if (found != mapping.end()) {
269 llvm::errs() <<
"FAILED CT: " <<
str()
270 <<
" adding Seq: " <<
to_string(Seq) <<
": "
278 bool changed =
false;
282 for (
const auto &pair : llvm::make_early_inc_range(mapping)) {
283 if (pair.first.size() == SeqSize) {
286 bool newMoreGeneralThanOld =
true;
289 bool oldMoreGeneralThanNew =
true;
290 for (
unsigned i = 0; i < SeqSize; i++) {
291 if (pair.first[i] == Seq[i])
294 oldMoreGeneralThanNew =
false;
295 }
else if (pair.first[i] == -1) {
296 newMoreGeneralThanOld =
false;
298 oldMoreGeneralThanNew =
false;
299 newMoreGeneralThanOld =
false;
304 if (oldMoreGeneralThanNew) {
306 if (CT == pair.second)
328 llvm::errs() <<
"inserting into : " <<
str() <<
" with "
330 llvm_unreachable(
"illegal insertion");
331 }
else if (newMoreGeneralThanOld) {
339 mapping.erase(pair.first);
351 mapping.erase(pair.first);
363 llvm::errs() <<
"inserting into : " <<
str() <<
" with "
365 llvm_unreachable(
"illegal insertion");
371 bool possibleDeletion =
false;
373 (minIndices.size() <= SeqSize) ? minIndices.size() : SeqSize;
374 for (
size_t i = 0; i < minLen; i++) {
375 if (minIndices[i] > Seq[i]) {
377 possibleDeletion =
true;
378 minIndices[i] = Seq[i];
382 if (minIndices.size() < SeqSize) {
383 for (
size_t i = minIndices.size(), end = SeqSize; i < end; ++i) {
384 minIndices.push_back(Seq[i]);
388 if (possibleDeletion) {
389 for (
const auto &pair : llvm::make_early_inc_range(mapping)) {
391 bool mustKeep =
false;
392 bool considerErase =
false;
393 for (
int val : pair.first) {
395 if (val == minIndices[i]) {
399 considerErase =
true;
403 if (!mustKeep && considerErase) {
404 mapping.erase(pair.first);
412 bool considerErase =
false;
413 for (
auto val : Seq) {
415 if (val == minIndices[i]) {
419 considerErase =
true;
423 if (considerErase && !keep)
425 mapping.insert(std::pair<
const std::vector<int>,
ConcreteType>(Seq, CT));
435 for (
const auto &pair : mapping) {
438 assert(pair.second.isKnown());
441 return mapping.size() != 0;
446 for (
auto &pair : mapping) {
449 assert(pair.second.isKnown());
450 if (pair.first.size() == 0) {
463 for (
auto &pair : mapping) {
465 vd.
insert(pair.first, pair.second);
475 Result.minIndices.reserve(1 + minIndices.size());
476 Result.minIndices.push_back(Off);
477 for (
auto midx : minIndices)
478 Result.minIndices.push_back(midx);
481 Result.minIndices.pop_back();
488 EmitWarning(
"TypeAnalysisDepthLimit", *orig, *orig,
490 " pointer lookups deep dt: ",
str(),
" only(", Off,
")");
493 <<
" pointer lookups deep dt:" <<
str() <<
" only("
500 for (
const auto &pair : mapping) {
503 std::vector<int> Vec;
504 Vec.reserve(pair.first.size() + 1);
506 for (
auto Val : pair.first)
508 Result.mapping.insert(
509 std::pair<
const std::vector<int>,
ConcreteType>(Vec, pair.second));
518 for (
const auto &pair : mapping) {
519 if (pair.first.size() == 0) {
520 llvm::errs() <<
str() <<
"\n";
522 assert(pair.first.size() != 0);
524 if (pair.first[0] == -1) {
525 std::vector<int> next(pair.first.begin() + 1, pair.first.end());
526 Result.mapping.insert(
527 std::pair<
const std::vector<int>,
ConcreteType>(next, pair.second));
528 for (
size_t i = 0, Len = next.size(); i < Len; ++i) {
529 if (i == Result.minIndices.size())
530 Result.minIndices.push_back(next[i]);
531 else if (next[i] < Result.minIndices[i])
532 Result.minIndices[i] = next[i];
536 for (
const auto &pair : mapping) {
537 if (pair.first[0] == 0) {
538 std::vector<int> next(pair.first.begin() + 1, pair.first.end());
542 Result.
orIn(next, pair.second);
565 for (
const auto &pair : mapping) {
566 assert(pair.first.size() != 0);
568 if (pair.first[0] == -1) {
571 auto next = pair.first;
572 for (
size_t i = 0; i < start; ++i) {
574 Result.
orIn(next, pair.second);
576 for (
size_t i = end; i < len; ++i) {
578 Result.
orIn(next, pair.second);
580 }
else if ((
size_t)pair.first[0] < start ||
581 ((
size_t)pair.first[0] >= end &&
582 (
size_t)pair.first[0] < len)) {
585 Result.
insert(pair.first, pair.second);
598 std::map<std::vector<int>, std::map<ConcreteType, std::set<int>>> staging;
600 for (
const auto &pair : mapping) {
601 assert(pair.first.size() != 0);
604 if (pair.first[0] != 0 && pair.first[0] != -1)
607 if (pair.first.size() == 1) {
613 if (pair.first[1] == -1) {
615 if ((
size_t)pair.first[1] >= len)
619 std::vector<int> next(pair.first.begin() + 2, pair.first.end());
621 staging[next][pair.second].insert(pair.first[1]);
625 for (
auto &pair : staging) {
626 auto &pnext = pair.first;
627 for (
auto &pair2 : pair.second) {
628 auto dt = pair2.first;
629 const auto &set = pair2.second;
631 bool legalCombine = set.count(-1);
637 if (pnext.size() > 0) {
638 chunk = dl.getPointerSizeInBits() / 8;
640 if (
auto flt = dt.isFloat()) {
641 chunk = dl.getTypeSizeInBits(flt) / 8;
643 chunk = dl.getPointerSizeInBits() / 8;
648 for (
size_t i = 0; i < len; i += chunk) {
650 legalCombine =
false;
656 std::vector<int> next;
657 next.reserve(pnext.size() + 1);
663 Result.
insert(next, dt,
true);
679 bool canonicalized =
true;
680 for (
const auto &pair : mapping) {
681 assert(pair.first.size() != 0);
682 if (pair.first[0] != -1) {
683 canonicalized =
false;
691 std::map<const std::vector<int>, std::map<ConcreteType, std::set<int>>>
694 for (
const auto &pair : mapping) {
696 std::vector<int> next(pair.first.begin() + 1, pair.first.end());
697 if (pair.first[0] != -1) {
698 if ((
size_t)pair.first[0] >= len) {
699 llvm::errs() <<
str() <<
"\n";
700 llvm::errs() <<
" canonicalizing " << len <<
"\n";
701 llvm::report_fatal_error(
"Canonicalization failed");
704 staging[next][pair.second].insert(pair.first[0]);
708 std::map<const std::vector<int>,
ConcreteType> unCombinedToAdd;
711 std::map<const std::vector<int>,
ConcreteType> combinedToAdd;
713 for (
const auto &pair : staging) {
714 auto &pnext = pair.first;
715 for (
const auto &pair2 : pair.second) {
716 auto dt = pair2.first;
717 const auto &set = pair2.second;
719 bool legalCombine =
false;
722 if (!set.count(-1)) {
724 if (pnext.size() > 0) {
725 chunk = dl.getPointerSizeInBits() / 8;
727 if (
auto flt = dt.isFloat()) {
728 chunk = dl.getTypeSizeInBits(flt) / 8;
730 chunk = dl.getPointerSizeInBits() / 8;
735 for (
size_t i = 0; i < len; i += chunk) {
737 legalCombine =
false;
743 std::vector<int> next;
744 next.reserve(pnext.size() + 1);
750 combinedToAdd.emplace(next, dt);
754 unCombinedToAdd.emplace(next, dt);
762 if (combinedToAdd.size() == 0) {
768 mapping = std::move(unCombinedToAdd);
769 if (minIndices.size() > 0) {
779 for (
const auto &pair : combinedToAdd) {
780 insert(pair.first, pair.second);
790 for (
const auto &pair : mapping) {
792 assert(pair.first.size() != 0);
795 if (pair.first[0] != 0 && pair.first[0] != -1)
798 if (pair.first.size() == 1) {
801 dat.
insert(pair.first, pair.second);
808 if (pair.first[1] == -1) {
809 dat.
insert(pair.first, pair.second);
816 llvm::Type *
allFloat(llvm::Value *val,
const llvm::DataLayout &dl,
817 bool anythingIsFloat =
false)
const {
822 return (llvm::Type *)0x123;
824 if (val->getType()->isTokenTy() || val->getType()->isVoidTy())
827 size_t size = (dl.getTypeSizeInBits(val->getType()) + 7) / 8;
831 llvm::Type *flt = m0.
isFloat();
839 size_t chunk = flt ? dl.getTypeSizeInBits(flt) / 8 : 1;
840 for (
size_t i = chunk; i < size; i += chunk) {
842 if (
auto f2 = mx.isFloat()) {
844 if (anythingIsFloat && !flt) {
846 chunk = dl.getTypeSizeInBits(flt) / 8;
857 if (!flt && anythingIsFloat) {
858 return (llvm::Type *)0x123;
862 bool anyFloat(llvm::Value *val,
const llvm::DataLayout &dl)
const {
867 if (val->getType()->isTokenTy() || val->getType()->isVoidTy())
870 size_t ObjSize = (dl.getTypeSizeInBits(val->getType()) + 7) / 8;
871 for (
size_t i = 0; i < ObjSize;) {
878 i += dl.getPointerSize(0);
885 bool anyPointer(llvm::Value *val,
const llvm::DataLayout &dl)
const {
890 if (val->getType()->isTokenTy() || val->getType()->isVoidTy())
893 size_t ObjSize = (dl.getTypeSizeInBits(val->getType()) + 7) / 8;
894 for (
size_t i = 0; i < ObjSize;) {
900 if (
auto FT = dt.isFloat()) {
901 i += (dl.getTypeSizeInBits(FT) + 7) / 8;
913 const int maxSize,
size_t addOffset = 0)
const {
918 if (minIndices.size() == 0)
948 Result.minIndices.resize(minIndices.size(), INT_MAX);
950 for (
const auto &pair : mapping) {
951 if (pair.first.size() == 0) {
954 Result.mapping.emplace(pair.first, pair.second);
958 llvm::errs() <<
"could not unmerge " <<
str() <<
"\n";
959 assert(0 &&
"ShiftIndices called on a nonpointer/anything");
960 llvm_unreachable(
"ShiftIndices called on a nonpointer/anything");
963 int next0 = pair.first[0];
971 if (addOffset != 0) {
978 Result.minIndices[0] = addOffset;
979 for (
size_t i = 1, sz = pair.first.size(); i < sz; i++)
980 if (pair.first[i] < Result.minIndices[i])
981 Result.minIndices[i] = pair.first[i];
986 if (next0 < offset) {
992 if (next0 >= maxSize)
998 if (next0 < Result.minIndices[0])
999 Result.minIndices[0] = next0;
1000 for (
size_t i = 1, sz = pair.first.size(); i < sz; i++)
1001 if (pair.first[i] < Result.minIndices[i])
1002 Result.minIndices[i] = pair.first[i];
1006 size_t maxInsertedDepth = 0;
1009 for (
const auto &pair : mapping) {
1010 if (pair.first.size() == 0)
1013 int next0 = pair.first[0];
1016 if (maxSize == -1) {
1021 if (addOffset != 0) {
1032 if (next0 < offset) {
1037 if (maxSize != -1) {
1038 if (next0 >= maxSize)
1048 bool minIndex = next0 == Result.minIndices[0];
1050 for (
size_t i = 1; i < pair.first.size(); i++) {
1051 if (pair.first[i] == Result.minIndices[i]) {
1060 std::vector<int> next(pair.first);
1062 Result.mapping.emplace(next, pair.second);
1063 if (next.size() > maxInsertedDepth)
1064 maxInsertedDepth = next.size();
1069 for (
const auto &pair : mapping) {
1070 if (pair.first.size() == 0)
1072 if (pair.first[0] != -1)
1076 std::vector<int> next(pair.first);
1078 if (
auto flt = op.isFloat()) {
1079 chunk = dl.getTypeSizeInBits(flt) / 8;
1081 chunk = dl.getPointerSizeInBits() / 8;
1083 auto offincr = (chunk - offset % chunk) % chunk;
1084 bool inserted =
false;
1085 for (
int i = offincr; i < maxSize; i += chunk) {
1086 next[0] = i + addOffset;
1091 auto found = Result.mapping.find(next);
1092 if (found != Result.mapping.end()) {
1095 if (prev.
orIn(found->second,
false))
1096 found->second = prev;
1098 Result.mapping.emplace(next, pair.second);
1102 if (inserted && next.size() > maxInsertedDepth)
1103 maxInsertedDepth = next.size();
1108 Result.minIndices.resize(maxInsertedDepth);
1115 Result.minIndices.reserve(minIndices.size());
1116 for (
const auto &pair : mapping) {
1119 Result.mapping.insert(pair);
1120 for (
size_t i = 0, Len = pair.first.size(); i < Len; ++i) {
1121 if (i == Result.minIndices.size())
1122 Result.minIndices.push_back(pair.first[i]);
1123 else if (pair.first[i] < Result.minIndices[i])
1124 Result.minIndices[i] = pair.first[i];
1133 for (
const auto &pair : mapping) {
1136 std::vector<int> nex = pair.first;
1140 dat.
insert(nex, pair.second);
1147 for (
auto &pair : mapping) {
1157 for (
const auto &pair : mapping) {
1160 dat.
insert(pair.first, pair.second);
1172 minIndices = RHS.minIndices;
1174 for (
const auto &elems : RHS.mapping) {
1175 mapping.emplace(elems);
1181 bool PointerIntSame,
bool &LegalOr) {
1185 bool subchanged = CT.
checkedOrIn(RHS, PointerIntSame, LegalOr);
1191 auto SeqSize = Seq.size();
1195 for (
size_t i = 0; i < SeqSize; ++i) {
1196 std::vector<int> tmp(Seq.begin(), Seq.end() - 1 - i);
1197 auto found = mapping.find(tmp);
1198 if (found != mapping.end()) {
1210 for (
const auto &pair : llvm::make_early_inc_range(mapping)) {
1211 if (pair.first.size() == SeqSize) {
1214 bool newMoreGeneralThanOld =
true;
1217 bool oldMoreGeneralThanNew =
true;
1218 for (
unsigned i = 0; i < SeqSize; i++) {
1219 if (pair.first[i] == Seq[i])
1222 oldMoreGeneralThanNew =
false;
1223 }
else if (pair.first[i] == -1) {
1224 newMoreGeneralThanOld =
false;
1226 oldMoreGeneralThanNew =
false;
1227 newMoreGeneralThanOld =
false;
1232 if (oldMoreGeneralThanNew) {
1234 if (CT == pair.second)
1254 if (newMoreGeneralThanOld)
1255 mapping.erase(pair.first);
1263 }
else if (newMoreGeneralThanOld) {
1270 mapping.erase(pair.first);
1281 mapping.erase(pair.first);
1305 bool PointerIntSame =
false) {
1306 bool LegalOr =
true;
1307 bool Result =
checkedOrIn(Seq, RHS, PointerIntSame, LegalOr);
1318 bool changed =
false;
1319 for (
auto &pair : RHS.mapping) {
1320 changed |=
checkedOrIn(pair.first, pair.second, PointerIntSame, LegalOr);
1330 bool Result =
checkedOrIn(RHS, PointerIntSame, Legal);
1332 llvm::errs() <<
"Illegal orIn: " <<
str() <<
" right: " << RHS.
str()
1333 <<
" PointerIntSame=" << PointerIntSame <<
"\n";
1334 assert(0 &&
"Performed illegal ConcreteType::orIn");
1335 llvm_unreachable(
"Performed illegal ConcreteType::orIn");
1345 bool Result =
checkedOrIn(Seq, CT, PointerIntSame, Legal);
1347 llvm::errs() <<
"Illegal orIn: " <<
str() <<
" right: " <<
to_string(Seq)
1348 <<
" CT: " << CT.
str()
1349 <<
" PointerIntSame=" << PointerIntSame <<
"\n";
1350 assert(0 &&
"Performed illegal ConcreteType::orIn");
1351 llvm_unreachable(
"Performed illegal ConcreteType::orIn");
1360 return orIn(RHS,
false);
1367 bool changed =
false;
1369 for (
auto &pair : llvm::make_early_inc_range(mapping)) {
1371 auto fd = RHS.mapping.find(pair.first);
1372 if (fd != RHS.mapping.end()) {
1375 changed = (pair.second &= other);
1377 mapping.erase(pair.first);
1393 llvm::BinaryOperator::BinaryOps Op) {
1394 bool changed =
false;
1396 for (
auto &pair : llvm::make_early_inc_range(mapping)) {
1401 if (pair.first.size() > 0) {
1402 mapping.erase(pair.first);
1410 auto found = RHS.mapping.find(pair.first);
1411 if (found != RHS.mapping.end()) {
1412 RightCT = found->second;
1414 bool SubLegal =
true;
1415 changed |= CT.
binopIn(SubLegal, RightCT, Op);
1421 mapping.erase(pair.first);
1428 for (
auto &pair : RHS.mapping) {
1433 if (pair.first.size() > 0) {
1437 if (mapping.find(pair.first) == RHS.mapping.end()) {
1439 bool SubLegal =
true;
1440 changed |= CT.
binopIn(SubLegal, pair.second, Op);
1446 mapping.insert(std::make_pair(pair.first, CT));
1456 std::string out =
"{";
1458 for (
auto &pair : mapping) {
1463 for (
unsigned i = 0; i < pair.first.size(); ++i) {
1466 out += std::to_string(pair.first[i]);
1468 out +=
"]:" + pair.second.str();
1475 llvm::MDNode *
toMD(llvm::LLVMContext &ctx) {
1476 llvm::SmallVector<llvm::Metadata *, 1> subMD;
1477 std::map<int, TypeTree> todo;
1479 for (
auto &pair : mapping) {
1480 if (pair.first.size() == 0) {
1484 auto next(pair.first);
1485 next.erase(next.begin());
1486 todo[pair.first[0]].mapping.insert(std::make_pair(next, pair.second));
1488 subMD.push_back(llvm::MDString::get(ctx, base.
str()));
1489 for (
auto pair : todo) {
1492 subMD.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
1493 llvm::IntegerType::get(ctx, 32), pair.first,
true)));
1494 subMD.push_back(pair.second.toMD(ctx));
1496 return llvm::MDNode::get(ctx, subMD);
1501 llvm::cast<llvm::MDString>(md->getOperand(0))->getString(),
1504 mapping.insert(std::make_pair(prev, base));
1505 for (
size_t i = 1; i < md->getNumOperands(); i += 2) {
1506 auto off = llvm::cast<llvm::ConstantInt>(
1507 llvm::cast<llvm::ConstantAsMetadata>(md->getOperand(i))
1511 next.push_back((
int)off);
1512 insertFromMD(llvm::cast<llvm::MDNode>(md->getOperand(i + 1)), next);
1518 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...
llvm::Type * isFloat() const
Return the floating point type, if this is a float.
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 ...
void remove(const std::vector< int > Seq)
TypeTree ReplaceMinus() const
Replace -1 with 0.
bool operator==(const TypeTree &RHS) const
Chceck equality of two TypeTrees.
bool anyPointer(llvm::Value *val, 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...
bool anyFloat(llvm::Value *val, const llvm::DataLayout &dl) const
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
llvm::Type * allFloat(llvm::Value *val, const llvm::DataLayout &dl, bool anythingIsFloat=false) const
bool operator=(const TypeTree &RHS)
Set this to another TypeTree, returning if this was changed.
bool IsFullyDetermined() const