68 std::unordered_map<const rvsdg::Output *, std::optional<int64_t>>
TopOrigins;
78 if (&p1Norm == &p2Norm)
86 JLM_ASSERT(p1Traced.Offset.has_value() && p2Traced.Offset.has_value());
88 if (p1Traced.BasePointer == p2Traced.BasePointer)
94 return QueryOffsets(p1Traced.Offset, s1, p2Traced.Offset, s2);
116 const auto & [p1Base, p1Offset] = *p1TraceCollection.
TopOrigins.begin();
117 const auto & [p2Base, p2Offset] = *p2TraceCollection.
TopOrigins.begin();
118 if (p1Base == p2Base)
131 if (*p1Traced.Offset > 0)
132 minimumP1OffsetFromStart =
133 std::max(minimumP1OffsetFromStart,
static_cast<size_t>(*p1Traced.Offset));
134 if (*p2Traced.Offset > 0)
135 minimumP2OffsetFromStart =
136 std::max(minimumP2OffsetFromStart,
static_cast<size_t>(*p2Traced.Offset));
165 if (p1AllTopsOriginal && p2AllTopsOriginal)
174 if (p1OnlyTraceable || p2OnlyTraceable)
189 static std::optional<int64_t>
196 if (inputIndex >= gepNode.
ninputs())
204 auto & gepInput = *gepNode.
input(inputIndex)->
origin();
208 if (!indexingValue.has_value())
213 const auto & elementType = array->GetElementType();
218 if (subOffset.has_value())
219 return offset + *subOffset;
225 if (*indexingValue < 0 ||
static_cast<size_t>(*indexingValue) >= strct->numElements())
226 throw std::logic_error(
"Struct type has fewer fields than requested by GEP");
228 const auto & fieldType = strct->getElementType(*indexingValue);
229 int64_t offset = strct->GetFieldOffset(*indexingValue);
232 if (subOffset.has_value())
233 return offset + *subOffset;
241 std::optional<int64_t>
244 const auto gep = util::assertedCast<const GetElementPtrOperation>(&gepNode.
GetOperation());
247 const auto & pointeeType = gep->GetPointeeType();
249 const auto & wholeTypeIndexingOrigin = *gepNode.
input(1)->
origin();
252 if (!wholeTypeIndexing.has_value())
259 if (!subOffset.has_value())
262 return offset + *subOffset;
277 if (
const auto [node, gep] =
278 rvsdg::TryGetSimpleNodeAndOptionalOp<GetElementPtrOperation>(*base);
284 if (!calculatedOffset.has_value())
287 base = node->input(0)->origin();
288 offset += *calculatedOffset;
300 std::optional<int64_t> offset1,
302 std::optional<int64_t> offset2,
306 if (!offset1.has_value() || !offset2.has_value())
309 auto difference = *offset2 - *offset1;
314 if (difference >= 0 &&
static_cast<size_t>(difference) >= s1)
318 if (difference <= 0 &&
static_cast<size_t>(-difference) >= s2)
338 if (!it->second.has_value())
342 const auto prevOffset = *it->second;
355 if (
const auto [node, gep] =
356 rvsdg::TryGetSimpleNodeAndOptionalOp<GetElementPtrOperation>(*p.
BasePointer);
366 if (gepOffset.has_value())
376 if (
const auto [node, select] =
377 rvsdg::TryGetSimpleNodeAndOptionalOp<SelectOperation>(*p.
BasePointer);
390 if (rvsdg::IsOwnerNodeOperation<UndefValueOperation>(*p.
BasePointer))
396 if (
auto gamma = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(*p.
BasePointer))
398 auto exitVar = gamma->MapOutputExitVar(*p.
BasePointer);
399 for (
auto result : exitVar.branchResult)
412 if (
auto theta = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(*p.
BasePointer))
414 auto loopVar = theta->MapOutputLoopVar(*p.
BasePointer);
435 if (rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(pointer))
438 if (rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(pointer))
442 if (
const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(pointer))
444 if (is<AllocaOperation>(node->GetOperation()))
447 if (is<MallocOperation>(node->GetOperation()))
457 for (
auto [output, offset] : traces.
TopOrigins)
465 std::optional<size_t>
468 if (
auto delta = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(pointer))
479 if (
const auto [node, allocaOp] = rvsdg::TryGetSimpleNodeAndOptionalOp<AllocaOperation>(pointer);
483 if (elementCount.has_value())
486 if (
const auto [node, mallocOp] = rvsdg::TryGetSimpleNodeAndOptionalOp<MallocOperation>(pointer);
489 const auto mallocSize =
491 if (mallocSize.has_value())
498 std::optional<size_t>
502 if (!totalSize.has_value())
505 if (!trace.
Offset.has_value())
509 if (*trace.
Offset > 0 &&
static_cast<size_t>(*trace.
Offset) > *totalSize)
512 return *totalSize - *trace.
Offset;
522 if (remainingSize.has_value())
525 if (*remainingSize < s)
532 if (*remainingSize == s && !it->second.has_value())
542 std::optional<size_t> minimumOffset;
543 for (
auto [output, offset] : traces.
TopOrigins)
546 if (!offset.has_value())
552 if (minimumOffset.has_value())
553 minimumOffset = std::min(*minimumOffset,
static_cast<size_t>(*offset));
555 minimumOffset = offset;
558 if (minimumOffset.has_value())
559 return *minimumOffset;
573 if (originSize.has_value() && *originSize < s)
589 const auto offset = it->second;
607 for (
auto [p1Origin, p1Offset] : tc1.
TopOrigins)
613 auto p2Offset = p2Find->second;
625 if (!rvsdg::IsOwnerNodeOperation<AllocaOperation>(pointer))
634 std::queue<const rvsdg::Output *> qu;
635 std::unordered_set<const rvsdg::Output *> added;
640 auto [_, inserted] = added.insert(&p);
648 auto & p = *qu.front();
652 for (
auto & user : p.Users())
654 if (
auto gamma = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(user))
656 auto input = gamma->MapInput(user);
659 auto entry = std::get_if<rvsdg::GammaNode::EntryVar>(&input);
662 for (
auto output : entry->branchArgument)
667 if (
auto gamma = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(user))
670 auto exitVar = gamma->MapBranchResultExitVar(user);
671 Enqueue(*exitVar.output);
676 if (
auto theta = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(user))
678 auto loopVar = theta->MapInputLoopVar(user);
681 Enqueue(*loopVar.pre);
685 if (
auto theta = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(user))
688 auto loopVar = theta->MapPostLoopVar(user);
689 Enqueue(*loopVar.pre);
690 Enqueue(*loopVar.output);
695 if (
auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(user))
698 node->GetOperation(),
702 JLM_ASSERT(user.index() == 0);
703 Enqueue(*node->output(0));
709 JLM_ASSERT(user.index() == 0);
710 Enqueue(*node->output(0));
716 Enqueue(*node->output(0));
727 if (&user == &StoreOperation::AddressInput(*node))
static rvsdg::Input & sizeInput(const rvsdg::Node &node)
static void RemoveTopOriginsWithinTheFirstNBytes(TraceCollection &traces, size_t s, size_t N)
static bool IsOriginalOrigin(const rvsdg::Output &pointer)
~LocalAliasAnalysis() noexcept override
bool HasOnlyFullyTraceableTopOrigins(TraceCollection &traces)
AliasQueryResponse Query(const rvsdg::Output &p1, size_t s1, const rvsdg::Output &p2, size_t s2) override
std::unordered_map< const rvsdg::Output *, bool > IsFullyTraceable_
static TracedPointerOrigin TracePointerOriginPrecise(const rvsdg::Output &p)
static bool DoTraceCollectionsOverlap(TraceCollection &tc1, size_t s1, TraceCollection &tc2, size_t s2)
static void RemoveTopOriginsSmallerThanSize(TraceCollection &traces, size_t s)
static std::optional< int64_t > CalculateGepOffset(const rvsdg::SimpleNode &gepNode)
static bool HasOnlyOriginalTopOrigins(TraceCollection &traces)
static size_t GetMinimumOffsetFromStart(TraceCollection &traces)
static constexpr size_t MaxTraceCollectionSize
bool IsOriginalOriginFullyTraceable(const rvsdg::Output &pointer)
static void RemoveTopOriginsWithRemainingSizeBelow(TraceCollection &traces, size_t s)
static AliasQueryResponse QueryOffsets(std::optional< int64_t > offset1, size_t s1, std::optional< int64_t > offset2, size_t s2)
static bool TraceAllPointerOrigins(TracedPointerOrigin p, TraceCollection &traceCollection)
static std::optional< size_t > GetOriginalOriginSize(const rvsdg::Output &pointer)
static std::optional< size_t > GetRemainingSize(TracedPointerOrigin trace)
size_t ninputs() const noexcept
const SimpleOperation & GetOperation() const noexcept override
NodeInput * input(size_t index) const noexcept
#define JLM_UNREACHABLE(msg)
static std::optional< int64_t > CalculateIntraTypeGepOffset(const rvsdg::SimpleNode &gepNode, size_t inputIndex, const rvsdg::Type &type)
size_t GetTypeAllocSize(const rvsdg::Type &type)
rvsdg::Output & traceOutput(rvsdg::Output &output)
static std::string ToString(const std::vector< MemoryNodeId > &memoryNodeIds)
std::optional< int64_t > tryGetConstantSignedInteger(const rvsdg::Output &output)
void MatchTypeWithDefault(T &obj, const Fns &... fns)
Pattern match over subclass type of given object with default handler.
static bool ThetaLoopVarIsInvariant(const ThetaNode::LoopVar &loopVar) noexcept
static std::string type(const Node *n)
std::unordered_map< const rvsdg::Output *, std::optional< int64_t > > TopOrigins
std::unordered_map< const rvsdg::Output *, std::optional< int64_t > > AllTracedOutputs
const rvsdg::Output * BasePointer
std::optional< int64_t > Offset