2
2
3
3
#include " ./Address.hpp"
4
4
#include " ./Predicate.hpp"
5
+ #include " Containers/BumpMapSet.hpp"
6
+ #include " Math/BumpVector.hpp"
7
+ #include " Utilities/Allocators.hpp"
5
8
#include < algorithm>
6
9
#include < concepts>
7
10
#include < cstddef>
32
35
#include < utility>
33
36
#include < variant>
34
37
35
- auto containsCycle (const llvm::Instruction *,
36
- llvm::SmallPtrSet<llvm::Instruction const *, 8 > &,
38
+ auto containsCycle (const llvm::Instruction *, aset<llvm::Instruction const *> &,
37
39
const llvm::Value *) -> bool;
38
- inline auto
39
- containsCycleCore (const llvm::Instruction *J,
40
- llvm::SmallPtrSet<llvm::Instruction const *, 8 > &visited,
41
- const llvm::Instruction *K) -> bool {
40
+ inline auto containsCycleCore (const llvm::Instruction *J,
41
+ aset<llvm::Instruction const *> &visited,
42
+ const llvm::Instruction *K) -> bool {
42
43
for (const llvm::Use &op : K->operands ())
43
44
if (containsCycle (J, visited, op.get ())) return true ;
44
45
return false ;
45
46
}
46
- inline auto
47
- containsCycle (const llvm::Instruction *J,
48
- llvm::SmallPtrSet<llvm::Instruction const *, 8 > &visited,
49
- const llvm::Value *V) -> bool {
47
+ inline auto containsCycle (const llvm::Instruction *J,
48
+ aset<llvm::Instruction const *> &visited,
49
+ const llvm::Value *V) -> bool {
50
50
const auto *S = llvm::dyn_cast<llvm::Instruction>(V);
51
51
if (S == J) return true ;
52
52
if ((!S) || (visited.count (S))) return false ;
53
53
visited.insert (S);
54
54
return containsCycleCore (J, visited, S);
55
55
}
56
56
57
- inline auto containsCycle (llvm::Instruction const *S) -> bool {
57
+ inline auto containsCycle (BumpAlloc<> &alloc, llvm::Instruction const *S)
58
+ -> bool {
58
59
// don't get trapped in a different cycle
59
- llvm::SmallPtrSet<llvm::Instruction const *, 8 > visited;
60
+ auto p = alloc.scope ();
61
+ aset<llvm::Instruction const *> visited{alloc};
60
62
return containsCycleCore (S, visited, S);
61
63
}
62
64
@@ -156,9 +158,9 @@ struct Instruction {
156
158
[[no_unique_address]] Predicate::Set predicates;
157
159
[[no_unique_address]] llvm::MutableArrayRef<Instruction *> operands;
158
160
// [[no_unique_address]] llvm::SmallVector<Instruction *> users;
159
- [[no_unique_address]] llvm::SmallPtrSet <Instruction *, 8 > users;
161
+ [[no_unique_address]] aset <Instruction *> users;
160
162
// / costs[i] == cost for vector-width 2^i
161
- [[no_unique_address]] llvm::SmallVector <RecipThroughputLatency> costs;
163
+ [[no_unique_address]] LinAlg::BumpPtrVector <RecipThroughputLatency> costs;
162
164
163
165
void setOperands (llvm::MutableArrayRef<Instruction *> ops) {
164
166
operands = ops;
@@ -229,9 +231,7 @@ struct Instruction {
229
231
[[nodiscard]] auto getOperand (size_t i) const -> Instruction * {
230
232
return operands[i];
231
233
}
232
- [[nodiscard]] auto getUsers () -> llvm::SmallPtrSetImpl<Instruction *> & {
233
- return users;
234
- }
234
+ [[nodiscard]] auto getUsers () -> aset<Instruction *> & { return users; }
235
235
[[nodiscard]] auto getNumOperands () const -> size_t {
236
236
return operands.size ();
237
237
}
@@ -283,11 +283,13 @@ struct Instruction {
283
283
// type(type) {
284
284
// // this->TTI = TTI;
285
285
// }
286
- Instruction (Intrinsic idt, llvm::Type *typ) : idtf(idt), type(typ) {}
286
+ Instruction (BumpAlloc<> &alloc, Intrinsic idt, llvm::Type *typ)
287
+ : idtf(idt), type(typ), predicates(alloc), users(alloc), costs(alloc) {}
287
288
// Instruction(UniqueIdentifier uid)
288
289
// : id(std::get<0>(uid)), operands(std::get<1>(uid)) {}
289
- Instruction (UniqueIdentifier uid, llvm::Type *typ)
290
- : idtf(std::get<0 >(uid)), type(typ), operands(std::get<1 >(uid)) {}
290
+ Instruction (BumpAlloc<> &alloc, UniqueIdentifier uid, llvm::Type *typ)
291
+ : idtf(std::get<0 >(uid)), type(typ), predicates(alloc),
292
+ operands (std::get<1 >(uid)), users(alloc), costs(alloc) {}
291
293
struct Cache {
292
294
[[no_unique_address]] llvm::DenseMap<llvm::Value *, Instruction *>
293
295
llvmToInternalMap;
@@ -346,7 +348,7 @@ struct Instruction {
346
348
}
347
349
auto createInstruction (BumpAlloc<> &alloc, UniqueIdentifier uid,
348
350
llvm::Type *typ) -> Instruction * {
349
- auto *i = new (alloc) Instruction (uid, typ);
351
+ auto *i = new (alloc) Instruction (alloc, uid, typ);
350
352
for (auto *op : i->operands ) op->users .insert (i);
351
353
argMap.insert ({uid, i});
352
354
return i;
@@ -427,7 +429,7 @@ struct Instruction {
427
429
UniqueIdentifier uid{Identifier (c), {}};
428
430
auto argMatch = argMap.find (uid);
429
431
if (argMatch != argMap.end ()) return argMatch->second ;
430
- return new (alloc) Instruction (uid, typ);
432
+ return new (alloc) Instruction (alloc, uid, typ);
431
433
}
432
434
auto getConstant (BumpAlloc<> &alloc, llvm::Type *typ, int64_t c)
433
435
-> Instruction * {
@@ -589,7 +591,7 @@ struct Instruction {
589
591
static auto createIsolated (BumpAlloc<> &alloc, llvm::Instruction *instr)
590
592
-> Instruction * {
591
593
Intrinsic id{instr};
592
- auto *i = new (alloc) Instruction (id, instr->getType ());
594
+ auto *i = new (alloc) Instruction (alloc, id, instr->getType ());
593
595
return i;
594
596
}
595
597
@@ -1260,14 +1262,14 @@ struct Map {
1260
1262
cache.predicates .emplace_back (I);
1261
1263
return i;
1262
1264
}
1263
- void reach (llvm::BasicBlock *BB, Intersection predicate) {
1265
+ void reach (BumpAlloc<> &alloc, llvm::BasicBlock *BB, Intersection predicate) {
1264
1266
// because we may have inserted into predMap, we need to look up
1265
1267
// again rather than being able to reuse anything from the
1266
1268
// `visit`.
1267
1269
if (auto f = find (BB); f != rend ()) {
1268
1270
f->second |= predicate;
1269
1271
} else {
1270
- map.insert ({BB, predicate});
1272
+ map.insert ({BB, Set{alloc, predicate} });
1271
1273
// map.insert(std::make_pair(BB, Set(predicate)));
1272
1274
}
1273
1275
}
@@ -1282,13 +1284,13 @@ struct Map {
1282
1284
// correctly
1283
1285
[[nodiscard]] static auto
1284
1286
descendBlock (BumpAlloc<> &alloc, Instruction::Cache &cache,
1285
- llvm::SmallPtrSet <llvm::BasicBlock *, 16 > &visited,
1286
- Predicate::Map &predMap , llvm::BasicBlock *BBsrc ,
1287
- llvm::BasicBlock *BBdst, Predicate::Intersection predicate ,
1288
- llvm::BasicBlock *BBhead, llvm:: Loop *L) -> Destination {
1287
+ aset <llvm::BasicBlock *> &visited, Predicate::Map &predMap ,
1288
+ llvm::BasicBlock *BBsrc , llvm::BasicBlock *BBdst ,
1289
+ Predicate::Intersection predicate, llvm::BasicBlock *BBhead ,
1290
+ llvm::Loop *L) -> Destination {
1289
1291
if (BBsrc == BBdst) {
1290
1292
assert (!predMap.contains (BBsrc));
1291
- predMap.insert ({BBsrc, predicate});
1293
+ predMap.insert ({BBsrc, Set{alloc, predicate} });
1292
1294
return Destination::Reached;
1293
1295
} else if (L && (!(L->contains (BBsrc)))) {
1294
1296
// oops, we seem to have skipped the preheader and escaped the
@@ -1320,7 +1322,7 @@ struct Map {
1320
1322
if (BI->isUnconditional ()) {
1321
1323
auto rc = descendBlock (alloc, cache, visited, predMap,
1322
1324
BI->getSuccessor (0 ), BBdst, predicate, BBhead, L);
1323
- if (rc == Destination::Reached) predMap.reach (BBsrc, predicate);
1325
+ if (rc == Destination::Reached) predMap.reach (alloc, BBsrc, predicate);
1324
1326
return rc;
1325
1327
}
1326
1328
// We have a conditional branch.
@@ -1340,7 +1342,7 @@ struct Map {
1340
1342
// we're now assuming that !cond
1341
1343
predMap.assume (
1342
1344
Predicate::Intersection (predInd, Predicate::Relation::False));
1343
- predMap.reach (BBsrc, predicate);
1345
+ predMap.reach (alloc, BBsrc, predicate);
1344
1346
}
1345
1347
return rc1;
1346
1348
} else if ((rc1 == Destination::Returned) ||
@@ -1349,11 +1351,11 @@ struct Map {
1349
1351
// we're now assuming that cond
1350
1352
predMap.assume (
1351
1353
Predicate::Intersection (predInd, Predicate::Relation::True));
1352
- predMap.reach (BBsrc, predicate);
1354
+ predMap.reach (alloc, BBsrc, predicate);
1353
1355
}
1354
1356
return rc0;
1355
1357
} else if (rc0 == rc1) {
1356
- if (rc0 == Destination::Reached) predMap.reach (BBsrc, predicate);
1358
+ if (rc0 == Destination::Reached) predMap.reach (alloc, BBsrc, predicate);
1357
1359
return rc0;
1358
1360
} else return Destination::Unknown;
1359
1361
}
@@ -1364,7 +1366,7 @@ struct Map {
1364
1366
llvm::BasicBlock *start, llvm::BasicBlock *stop, llvm::Loop *L)
1365
1367
-> std::optional<Map> {
1366
1368
Predicate::Map pm;
1367
- llvm::SmallPtrSet <llvm::BasicBlock *, 16 > visited;
1369
+ aset <llvm::BasicBlock *> visited (alloc) ;
1368
1370
if (descendBlock (alloc, cache, visited, pm, start, stop, {}, start, L) ==
1369
1371
Destination::Reached)
1370
1372
return pm;
@@ -1379,9 +1381,9 @@ inline auto Instruction::Cache::getInstruction(BumpAlloc<> &alloc,
1379
1381
llvm::Instruction *instr)
1380
1382
-> Instruction * {
1381
1383
if (Instruction *i = completeInstruction (alloc, predMap, instr)) return i;
1382
- if (containsCycle (instr)) {
1383
- auto *i =
1384
- new (alloc) Instruction ( Instruction::Intrinsic (instr), instr->getType ());
1384
+ if (containsCycle (alloc, instr)) {
1385
+ auto *i = new (alloc)
1386
+ Instruction (alloc, Instruction::Intrinsic (instr), instr->getType ());
1385
1387
llvmToInternalMap[instr] = i;
1386
1388
return i;
1387
1389
}
@@ -1417,12 +1419,19 @@ inline auto Instruction::Cache::getInstruction(BumpAlloc<> &alloc,
1417
1419
-> Instruction * {
1418
1420
1419
1421
if (auto *instr = llvm::dyn_cast<llvm::Instruction>(v)) {
1420
- if (containsCycle (instr)) {
1422
+ if (containsCycle (alloc, instr)) {
1421
1423
}
1422
1424
return getInstruction (alloc, predMap, instr);
1423
1425
}
1424
1426
return getInstruction (alloc, v);
1425
1427
}
1428
+ static_assert (
1429
+ std::is_trivially_destructible_v<
1430
+ std::variant<std::monostate, llvm::Instruction *, llvm::ConstantInt *,
1431
+ llvm::ConstantFP *, Address *>>);
1432
+ static_assert (std::is_trivially_destructible_v<Predicate::Set>);
1433
+ static_assert (
1434
+ std::is_trivially_destructible_v<LinAlg::BumpPtrVector<Instruction *>>);
1426
1435
/*
1427
1436
struct InstructionBlock {
1428
1437
// we tend to heap allocate InstructionBlocks with a bump allocator,
0 commit comments