82 std::unordered_map<const rvsdg::Output *, std::optional<int64_t>>
TopOrigins;
92 if (&p1Norm == &p2Norm)
100 JLM_ASSERT(p1Traced.Offset.has_value() && p2Traced.Offset.has_value());
102 if (p1Traced.BasePointer == p2Traced.BasePointer)
108 return QueryOffsets(p1Traced.Offset, s1, p2Traced.Offset, s2);
141 const auto & [p1Base, p1Offset] = *p1TraceCollection.
TopOrigins.begin();
142 const auto & [p2Base, p2Offset] = *p2TraceCollection.
TopOrigins.begin();
143 if (p1Base == p2Base)
156 if (*p1Traced.Offset > 0)
157 minimumP1OffsetFromStart =
158 std::max(minimumP1OffsetFromStart,
static_cast<size_t>(*p1Traced.Offset));
159 if (*p2Traced.Offset > 0)
160 minimumP2OffsetFromStart =
161 std::max(minimumP2OffsetFromStart,
static_cast<size_t>(*p2Traced.Offset));
190 if (p1AllTopsOriginal && p2AllTopsOriginal)
199 if (p1OnlyTraceable || p2OnlyTraceable)
214 static std::optional<int64_t>
221 if (inputIndex >= gepNode.
ninputs())
229 auto & gepInput = *gepNode.
input(inputIndex)->
origin();
233 if (!indexingValue.has_value())
236 if (
auto array =
dynamic_cast<const ArrayType *
>(&type))
238 const auto & elementType = array->GetElementType();
243 if (subOffset.has_value())
244 return offset + *subOffset;
248 if (
auto strct =
dynamic_cast<const StructType *
>(&type))
250 if (*indexingValue < 0 ||
static_cast<size_t>(*indexingValue) >= strct->numElements())
251 throw std::logic_error(
"Struct type has fewer fields than requested by GEP");
253 const auto & fieldType = strct->getElementType(*indexingValue);
254 int64_t offset = strct->GetFieldOffset(*indexingValue);
257 if (subOffset.has_value())
258 return offset + *subOffset;
266 std::optional<int64_t>
269 const auto gep = util::assertedCast<const GetElementPtrOperation>(&gepNode.
GetOperation());
272 const auto & pointeeType = gep->getPointeeType();
274 const auto & wholeTypeIndexingOrigin = *gepNode.
input(1)->
origin();
277 if (!wholeTypeIndexing.has_value())
284 if (!subOffset.has_value())
287 return offset + *subOffset;
302 if (
const auto [node, gep] =
303 rvsdg::TryGetSimpleNodeAndOptionalOp<GetElementPtrOperation>(*base);
309 if (!calculatedOffset.has_value())
312 base = node->input(0)->origin();
313 offset += *calculatedOffset;
327 std::optional<int64_t> offset1,
329 std::optional<int64_t> offset2,
333 if (!offset1.has_value() || !offset2.has_value())
336 auto difference = *offset2 - *offset1;
341 if (difference >= 0 &&
static_cast<size_t>(difference) >= s1)
345 if (difference <= 0 &&
static_cast<size_t>(-difference) >= s2)
365 if (!it->second.has_value())
369 const auto prevOffset = *it->second;
382 if (
const auto [node, gep] =
383 rvsdg::TryGetSimpleNodeAndOptionalOp<GetElementPtrOperation>(*p.
BasePointer);
393 if (gepOffset.has_value())
403 if (
const auto [node, select] =
404 rvsdg::TryGetSimpleNodeAndOptionalOp<SelectOperation>(*p.
BasePointer);
417 if (rvsdg::IsOwnerNodeOperation<UndefValueOperation>(*p.
BasePointer))
423 if (
auto gamma = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(*p.
BasePointer))
425 auto exitVar = gamma->MapOutputExitVar(*p.
BasePointer);
426 for (
auto result : exitVar.branchResult)
439 if (
auto theta = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(*p.
BasePointer))
441 auto loopVar = theta->MapOutputLoopVar(*p.
BasePointer);
462 if (rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(pointer))
465 if (rvsdg::TryGetOwnerNode<rvsdg::LambdaNode>(pointer))
469 if (
const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(pointer))
471 if (is<AllocaOperation>(node->GetOperation()))
474 if (is<MallocOperation>(node->GetOperation()))
484 for (
auto [output, offset] : traces.
TopOrigins)
492 std::optional<size_t>
495 if (
auto delta = rvsdg::TryGetOwnerNode<rvsdg::DeltaNode>(pointer))
506 if (
const auto [node, allocaOp] = rvsdg::TryGetSimpleNodeAndOptionalOp<AllocaOperation>(pointer);
510 if (elementCount.has_value())
513 if (
const auto [node, mallocOp] = rvsdg::TryGetSimpleNodeAndOptionalOp<MallocOperation>(pointer);
516 const auto mallocSize =
518 if (mallocSize.has_value())
525 std::optional<size_t>
529 if (!totalSize.has_value())
532 if (!trace.
Offset.has_value())
536 if (*trace.
Offset > 0 &&
static_cast<size_t>(*trace.
Offset) > *totalSize)
539 return *totalSize - *trace.
Offset;
549 if (remainingSize.has_value())
552 if (*remainingSize < s)
559 if (*remainingSize == s && !it->second.has_value())
569 std::optional<size_t> minimumOffset;
570 for (
auto [output, offset] : traces.
TopOrigins)
573 if (!offset.has_value())
579 if (minimumOffset.has_value())
580 minimumOffset = std::min(*minimumOffset,
static_cast<size_t>(*offset));
582 minimumOffset = offset;
585 if (minimumOffset.has_value())
586 return *minimumOffset;
600 if (originSize.has_value() && *originSize < s)
616 const auto offset = it->second;
634 for (
auto [p1Origin, p1Offset] : tc1.
TopOrigins)
640 auto p2Offset = p2Find->second;
652 if (!rvsdg::IsOwnerNodeOperation<AllocaOperation>(pointer))
661 std::queue<const rvsdg::Output *> qu;
662 std::unordered_set<const rvsdg::Output *> added;
667 auto [_, inserted] = added.insert(&p);
675 auto & p = *qu.front();
679 for (
auto & user : p.Users())
681 if (
auto gamma = rvsdg::TryGetOwnerNode<rvsdg::GammaNode>(user))
683 auto input = gamma->MapInput(user);
686 auto entry = std::get_if<rvsdg::GammaNode::EntryVar>(&input);
689 for (
auto output : entry->branchArgument)
694 if (
auto gamma = rvsdg::TryGetRegionParentNode<rvsdg::GammaNode>(user))
697 auto exitVar = gamma->MapBranchResultExitVar(user);
698 Enqueue(*exitVar.output);
703 if (
auto theta = rvsdg::TryGetOwnerNode<rvsdg::ThetaNode>(user))
705 auto loopVar = theta->MapInputLoopVar(user);
708 Enqueue(*loopVar.pre);
712 if (
auto theta = rvsdg::TryGetRegionParentNode<rvsdg::ThetaNode>(user))
715 auto loopVar = theta->MapPostLoopVar(user);
716 Enqueue(*loopVar.pre);
717 Enqueue(*loopVar.output);
722 if (
auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(user))
725 node->GetOperation(),
729 JLM_ASSERT(user.index() == 0);
730 Enqueue(*node->output(0));
736 JLM_ASSERT(user.index() == 0);
737 Enqueue(*node->output(0));
743 Enqueue(*node->output(0));
754 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)
void setMaxTraceCollectionSize(size_t maxTraceCollectionSize)
static std::optional< int64_t > CalculateGepOffset(const rvsdg::SimpleNode &gepNode)
static bool HasOnlyOriginalTopOrigins(TraceCollection &traces)
static size_t GetMinimumOffsetFromStart(TraceCollection &traces)
size_t getMaxTraceCollectionSize()
bool IsOriginalOriginFullyTraceable(const rvsdg::Output &pointer)
size_t maxTraceCollectionSize_
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)
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, const rvsdg::Region *withinRegion)
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
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