Jlm
TraceTests.cpp
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 #include <gtest/gtest.h>
7 
11 #include <jlm/llvm/ir/Trace.hpp>
12 #include <jlm/llvm/ir/types.hpp>
14 #include <jlm/rvsdg/control.hpp>
15 #include <jlm/rvsdg/gamma.hpp>
16 #include <jlm/rvsdg/lambda.hpp>
17 
18 #include <cassert>
19 
20 TEST(TraceTests, testTracingIOBarrier)
21 {
22  using namespace jlm;
23  using namespace jlm::llvm;
24 
25  // Creates a graph that looks like
26  // GraphImport("x") GraphImport("io")
27  // | /---------/
28  // v v |
29  // IOBarrier |
30  // | /---------/
31  // v v
32  // IOBarrier
33  //
34  // And checks that both the IOBarrier outputs are traced back up to the "x" graph import
35 
36  // Arrange
37  rvsdg::Graph graph;
38 
39  const auto int32Type = rvsdg::BitType::Create(32);
40  const auto ioStateType = IOStateType::Create();
41 
42  const auto myInt = &rvsdg::GraphImport::Create(graph, int32Type, "x");
43  const auto myIo = &rvsdg::GraphImport::Create(graph, ioStateType, "io");
44 
45  const auto ioBarrier1 = &rvsdg::CreateOpNode<IOBarrierOperation>({ myInt, myIo }, int32Type);
46  const auto ioBarrier1Output = ioBarrier1->output(0);
47 
48  const auto ioBarrier2 =
49  &rvsdg::CreateOpNode<IOBarrierOperation>({ ioBarrier1Output, myIo }, int32Type);
50  const auto ioBarrier2Output = ioBarrier2->output(0);
51 
52  // Assert
53  EXPECT_EQ(&jlm::llvm::traceOutput(*ioBarrier1Output), myInt);
54  EXPECT_EQ(&jlm::llvm::traceOutput(*ioBarrier2Output), myInt);
55 }
56 
57 TEST(TraceTests, testGetConstantSignedInteger)
58 {
59  using namespace jlm;
60  using namespace jlm::llvm;
61 
62  // Creates a graph that looks like
63  //
64  // BITS64(-37)
65  // |
66  // v
67  // +-------------------------------------------+
68  // | LAMBDA f() |
69  // +-------------------------------------------+
70  // | | |
71  // | | |
72  // | | |
73  // | | IntegerConstantOperation(20) |
74  // | v | |
75  // | MATCH | |
76  // | v v |
77  // | +-----------------------+ |
78  // | | gamma | |
79  // | | +-------+ +-------+ | |
80  // | | | | | | | | | |
81  // | | | v | | v | | |
82  // | | +-------+ +-------+ | |
83  // | +-----------------------+ |
84  // | | |
85  // | v |
86  // +-------------------------------------------+
87  // And checks that outputs with constant integer values lead to the correct value.
88  //
89 
90  // Arrange
91  rvsdg::Graph graph;
92 
93  const auto int64Type = rvsdg::BitType::Create(64);
94  const auto int32Type = rvsdg::BitType::Create(32);
95 
96  const auto bits64Output = &rvsdg::BitConstantOperation::create(
97  graph.GetRootRegion(),
99 
100  const auto functionType = rvsdg::FunctionType::Create({}, { int32Type });
101  const auto lambdaNode = jlm::rvsdg::LambdaNode::Create(
102  graph.GetRootRegion(),
104  functionType,
105  "f",
107 
108  const auto bits64CtxVar = lambdaNode->AddContextVar(*bits64Output).inner;
109  const auto matchOutput = rvsdg::MatchOperation::Create(*bits64CtxVar, { { 0, 0 } }, 1, 2);
110  const auto & integerConstantNode =
111  IntegerConstantOperation::Create(*lambdaNode->subregion(), 32, 20);
112 
113  auto & gammaNode = *rvsdg::GammaNode::create(matchOutput, 2);
114  const auto entryVar = gammaNode.AddEntryVar(integerConstantNode.output(0));
115 
116  const auto exitVarOutput =
117  gammaNode.AddExitVar({ entryVar.branchArgument[0], entryVar.branchArgument[1] }).output;
118  const auto lambdaOutput = lambdaNode->finalize({ exitVarOutput });
119 
120  // Assert
121 
122  // The -37 can be found both inside and outside the lambda
123  EXPECT_EQ(tryGetConstantSignedInteger(*bits64Output), -37);
124  EXPECT_EQ(tryGetConstantSignedInteger(*bits64CtxVar), -37);
125 
126  // The 20 can be found both before, inside and after the gamma
127  EXPECT_EQ(tryGetConstantSignedInteger(*integerConstantNode.output(0)), 20);
128  EXPECT_EQ(tryGetConstantSignedInteger(*entryVar.branchArgument[0]), 20);
129  EXPECT_EQ(tryGetConstantSignedInteger(*entryVar.branchArgument[1]), 20);
130  EXPECT_EQ(tryGetConstantSignedInteger(*exitVarOutput), 20);
131 
132  // A match output is not a constant integer, neither is the lambda output
133  EXPECT_EQ(tryGetConstantSignedInteger(*matchOutput), std::nullopt);
134  EXPECT_EQ(tryGetConstantSignedInteger(*lambdaOutput), std::nullopt);
135 }
static std::shared_ptr< const IOStateType > Create()
Definition: types.cpp:343
static std::unique_ptr< LlvmLambdaOperation > Create(std::shared_ptr< const jlm::rvsdg::FunctionType > type, std::string name, const jlm::llvm::Linkage &linkage, jlm::llvm::CallingConvention callingConvention, jlm::llvm::AttributeSet attributes)
Definition: lambda.hpp:84
static Output & create(Region &region, BitValueRepresentation value)
Definition: constant.hpp:44
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
static std::shared_ptr< const FunctionType > Create(std::vector< std::shared_ptr< const jlm::rvsdg::Type >> argumentTypes, std::vector< std::shared_ptr< const jlm::rvsdg::Type >> resultTypes)
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
Definition: gamma.hpp:161
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
Definition: graph.cpp:36
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
static LambdaNode * Create(rvsdg::Region &parent, std::unique_ptr< LambdaOperation > operation)
Definition: lambda.cpp:140
static Output * Create(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
Definition: control.hpp:242
TEST(TraceTests, testTracingIOBarrier)
Definition: TraceTests.cpp:20
Global memory state passed between functions.
rvsdg::Output & traceOutput(rvsdg::Output &output, const rvsdg::Region *withinRegion)
Definition: Trace.cpp:54
std::optional< int64_t > tryGetConstantSignedInteger(const rvsdg::Output &output)
Definition: Trace.cpp:62