Jlm
Loading...
Searching...
No Matches
Trace.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2025 HÃ¥vard Krogstie <krogstie.havard@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#ifndef JLM_RVSDG_TRACE_HPP
7#define JLM_RVSDG_TRACE_HPP
8
9#include <jlm/rvsdg/node.hpp>
11
12namespace jlm::rvsdg
13{
14class GammaNode;
15class ThetaNode;
16
27{
28public:
37 {
38 // Perform a quick check to see if the structural output is trivially invariant,
39 // i.e., gets its value directly from a single subregion argument in all subregions.
40 // If so, tracing continues from the corresponding input to the structural node.
42
43 // Performs the same check as above, but tries harder to determine invariance.
44 // Tracing continues inside the subregion, to check if it can reach a subregion argument.
45 // If all subregions reach the same argument, the structural node is invariant,
46 // and tracing continue from the input of the structural node.
48
49 // Performs the same checks as above, but can also trace outputs that are not invariant.
50 // Tracing can continue inside subregions, such as inside a theta subregion,
51 // or inside a gamma subregion when the other subregions are unreachable or
52 // provide undefined values.
53 // Unlike the previous policies, this means the final return value of the tracer can be
54 // inside a region that is not an ancestor of the region where tracing started.
56 };
57
58 virtual ~OutputTracer();
59
64
75
82 [[nodiscard]] bool
87
95 [[nodiscard]] bool
100
105 void
110
117 [[nodiscard]] bool
122
128 void
129 setInterprocedural(bool value) noexcept
130 {
131 isInterprocedural_ = value;
132 }
133
141 [[nodiscard]] bool
146
152 void
153 setEnterPhiNodes(bool value) noexcept
154 {
155 enterPhiNodes_ = value;
156 }
157
158 [[nodiscard]] bool
163
164 void
166 {
168 }
169
181 [[nodiscard]] bool
186
193 void
194 setInvarianceCaching(bool value) noexcept
195 {
197 }
198
211 void
213 {
214 invariantOutputCache_.clear();
215 }
216
221 [[nodiscard]] Output &
222 trace(Output & output);
223
232 [[nodiscard]] Output &
233 trace(Output & output, const Region * withinRegion);
234
235protected:
236 // Enum representing information about the path the tracer took from the starting output
237 // to reach the current output being considered
238 enum class BackEdgeState
239 {
240 // Tracing has gone from the starting output to the current output without
241 // following any back-edges around the current output.
242 // Theta nodes between the current output and the starting output do not matter.
244
245 // While tracing from the starting output to the current output,
246 // the tracer may have followed a back-edge going around the current output.
247 // This prevents the use of the region predication checker.
249 };
250
255 {
256 public:
263 [[nodiscard]] Output &
265 {
267 return *output_;
268 }
269
276 [[nodiscard]] bool
281
287 [[nodiscard]] bool
292
300 [[nodiscard]] bool
305
310 [[nodiscard]] static TraceStepResult
312 {
314 }
315
320 [[nodiscard]] static TraceStepResult
325
330 [[nodiscard]] static TraceStepResult
335
336 private:
338 {
339 // Represents an output found after one or more steps of tracing progress,
340 // but not necessarily the final stopping point for tracing.
342
343 // Represents an output from which no more tracing is possible
345
346 // When tracing, the region of the starting output is the target region.
347 // During tracing, tracing may enter the subregions of structural nodes.
348 // Within such a subregion S, it may be discovered that all possible value origins
349 // inside S are in regions from which control flow can never enter the target region.
350 // This effectively means tracing never needed to enter S in the first place.
351 // This is signalled by returning DeadEnd from the tracing inside S.
352 DeadEnd,
353 };
354
356 : output_(output),
357 kind_(kind)
358 {}
359
362 };
363
376
395
412
424 traceThetaArgument(ThetaNode & thetaNode, Output & output);
425
434 [[nodiscard]] virtual TraceStepResult
436
450 Output &
452
459 Input *
461
462 // The policy determining how tracing handles outputs of gamma and theta nodes
465
466 // When true, tracing is allowed to continue outside of lambda nodes.
467 // When false, tracing will stop at the lambda's context arguments.
469
470 // When true, tracing can go from the output of a \ref PhiNode into its subregion.
471 // When false, tracing will stop at the output of the phi node.
472 bool enterPhiNodes_ = true;
473
474 // When true, gamma subregions are ignored when it is impossible for control flow to go
475 // from the gamma subregion to the region containing the output tracing started from
477 // The region predicate checker used to disqualify regions
479 // The output from which the current tracing operation started.
480 // Used for region predication checks.
481 // This is the starting output referenced by the enum \ref BackEdgeState.
482 const Output * startingOutput_ = nullptr;
483
484 // When true, the tracer can cache the fact that outputs of structural nodes are invariant.
485 // Enabling caching means the user of the tracer is responsible for cache invalidation.
486 // @see clearInvarianceCache() for details
488 // Maps from a structural output to an input of the same structural node
489 // that the output always gets its value from.
490 std::unordered_map<const Output *, Input *> invariantOutputCache_{};
491};
492
511Output &
513
514inline const Output &
516{
517 return traceOutputIntraProcedurally(const_cast<Output &>(output), mayEnterSubregions);
518}
519
538Output &
539traceOutput(Output & output, bool mayEnterSubregions, const Region * withinRegion = nullptr);
540
541inline const Output &
542traceOutput(const Output & output, bool mayEnterSubregions, const Region * withinRegion = nullptr)
543{
544 return traceOutput(const_cast<Output &>(output), mayEnterSubregions, withinRegion);
545}
546
547}
548
549#endif // JLM_RVSDG_TRACE_HPP
class providing guarantees about unreachability of regions from other regions.
Conditional operator / pattern matching.
Definition gamma.hpp:99
static TraceStepResult createFinalOutput(Output &output)
Definition Trace.hpp:321
static TraceStepResult createDeadEndResult()
Definition Trace.hpp:331
bool isFinalOutput() const noexcept
Definition Trace.hpp:288
Output & getOutput() const noexcept
Definition Trace.hpp:264
static TraceStepResult createStepOutput(Output &output)
Definition Trace.hpp:311
TraceStepResult(Output *output, TraceStepResultKind kind)
Definition Trace.hpp:355
TraceStepResult traceInternal(Output &output, BackEdgeState backEdgeState, const Region *withinRegion)
Definition Trace.cpp:55
void setRegionPredicateCheckingEnabled(bool value) noexcept
Definition Trace.hpp:165
Output & insertInInvarianceCache(const Output &structuralOutput, Input &structuralInput)
Definition Trace.cpp:416
bool isInvarianceCachingEnabled() const noexcept
Definition Trace.hpp:182
void setEnterPhiNodes(bool value) noexcept
Definition Trace.hpp:153
AlternativeRegionPredicateTracer regionPredicateTracer_
Definition Trace.hpp:478
void setInvarianceCaching(bool value) noexcept
Definition Trace.hpp:194
TraceStepResult traceThetaOutput(ThetaNode &thetaNode, Output &output, BackEdgeState backEdgeState)
Definition Trace.cpp:223
virtual TraceStepResult traceStep(Output &output, BackEdgeState backEdgeState, const Region *withinRegion)
Definition Trace.cpp:330
bool isDeepInvarianceCheckingEnabled() const noexcept
Definition Trace.hpp:83
void setInterprocedural(bool value) noexcept
Definition Trace.hpp:129
bool isInterprocedural() const noexcept
Definition Trace.hpp:118
StructuralNodePolicy getStructuralNodePolicy() const noexcept
Definition Trace.hpp:71
TraceStepResult traceGammaOutput(GammaNode &gammaNode, Output &output, BackEdgeState backEdgeState)
Definition Trace.cpp:94
const Output * startingOutput_
Definition Trace.hpp:482
Output & trace(Output &output)
Definition Trace.cpp:21
bool isEnteringPhiNodes() const noexcept
Definition Trace.hpp:142
bool isRegionPredicateCheckingEnabled() const noexcept
Definition Trace.hpp:159
void setStructuralNodePolicy(StructuralNodePolicy value) noexcept
Definition Trace.hpp:106
bool enableRegionPredicateChecking_
Definition Trace.hpp:476
Input * lookupInInvarianceCache(const Output &structuralOutput)
Definition Trace.cpp:428
StructuralNodePolicy structuralNodePolicy_
Definition Trace.hpp:463
OutputTracer() noexcept
Definition Trace.cpp:17
std::unordered_map< const Output *, Input * > invariantOutputCache_
Definition Trace.hpp:490
TraceStepResult traceThetaArgument(ThetaNode &thetaNode, Output &output)
Definition Trace.cpp:309
bool isTracingIntoSubregionsEnabled() const noexcept
Definition Trace.hpp:96
Represent acyclic RVSDG subgraphs.
Definition region.hpp:213
#define JLM_ASSERT(x)
Definition common.hpp:16
Output & traceOutput(Output &output, bool mayEnterSubregions, const Region *withinRegion)
Definition Trace.cpp:454
Output & traceOutputIntraProcedurally(Output &output, bool mayEnterSubregions)
Definition Trace.cpp:442
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872