• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daisytuner / sdfglib / 19231491789

10 Nov 2025 12:23PM UTC coverage: 61.533% (+0.3%) from 61.206%
19231491789

push

github

web-flow
Merge pull request #336 from daisytuner/bytes-reference-tests

adds tests for byte reference elimination

50 of 56 new or added lines in 4 files covered. (89.29%)

6 existing lines in 1 file now uncovered.

10393 of 16890 relevant lines covered (61.53%)

101.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.35
/src/passes/dataflow/byte_reference_elimination.cpp
1
#include "sdfg/passes/dataflow/byte_reference_elimination.h"
2

3
#include "sdfg/analysis/dominance_analysis.h"
4
#include "sdfg/analysis/users.h"
5
#include "sdfg/types/utils.h"
6

7
namespace sdfg {
8
namespace passes {
9

10
ByteReferenceElimination::ByteReferenceElimination()
3✔
11
    : Pass() {
3✔
12

13
      };
3✔
14

15
std::string ByteReferenceElimination::name() { return "ByteReferenceElimination"; };
×
16

17
bool ByteReferenceElimination::
18
    run_pass(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
2✔
19
    bool applied = false;
2✔
20

21
    auto& sdfg = builder.subject();
2✔
22
    auto& users_analysis = analysis_manager.get<analysis::Users>();
2✔
23
    auto& dominance_analysis = analysis_manager.get<analysis::DominanceAnalysis>();
2✔
24

25
    for (auto& name : sdfg.containers()) {
7✔
26
        if (!sdfg.is_transient(name)) {
5✔
27
            continue;
2✔
28
        }
29
        if (sdfg.type(name).type_id() != types::TypeID::Pointer) {
3✔
30
            continue;
×
31
        }
32
        auto moves = users_analysis.moves(name);
3✔
33
        if (moves.size() != 1) {
3✔
34
            continue;
×
35
        }
36

37
        // Find Move
38
        auto move = *moves.begin();
3✔
39
        auto move_node = dynamic_cast<data_flow::AccessNode*>(move->element());
3✔
40
        auto& move_graph = move_node->get_parent();
3✔
41
        auto& move_edge = *move_graph.in_edges(*move_node).begin();
3✔
42
        auto& move_src = static_cast<data_flow::AccessNode&>(move_edge.src());
3✔
43

44
        // Criterion: Move must be a constant offset in bytes
45
        auto& move_type = move_edge.base_type();
3✔
46
        if (move_type.type_id() != types::TypeID::Pointer) {
3✔
47
            continue;
×
48
        }
49
        auto& move_pointer_type = static_cast<const types::Pointer&>(move_type);
3✔
50
        if (!move_pointer_type.has_pointee_type()) {
3✔
51
            continue;
×
52
        }
53
        auto& move_pointee_type = move_pointer_type.pointee_type();
3✔
54
        if (move_pointee_type.type_id() != types::TypeID::Scalar) {
3✔
NEW
55
            continue;
×
56
        }
57
        auto& move_pointee_type_bytes = static_cast<const types::Scalar&>(move_pointee_type);
3✔
58
        if (move_pointee_type_bytes.primitive_type() != types::PrimitiveType::Int8 &&
4✔
59
            move_pointee_type_bytes.primitive_type() != types::PrimitiveType::UInt8) {
1✔
60
            continue;
1✔
61
        }
62

63
        auto& move_subset = move_edge.subset();
2✔
64
        if (move_subset.size() != 1) {
2✔
NEW
65
            continue;
×
66
        }
67
        auto move_offset = move_subset.at(0);
2✔
68
        if (!SymEngine::is_a<SymEngine::Integer>(*move_offset)) {
2✔
UNCOV
69
            continue;
×
70
        }
71
        auto move_offset_int = SymEngine::rcp_static_cast<const SymEngine::Integer>(move_offset);
2✔
72
        int move_offset_bytes = move_offset_int->as_int();
2✔
73

74
        // Replace uses of byte-offseted pointer
75
        auto uses = users_analysis.uses(name);
2✔
76
        for (auto& use : uses) {
7✔
77
            if (use->use() != analysis::Use::VIEW && use->use() != analysis::Use::READ &&
8✔
78
                use->use() != analysis::Use::WRITE) {
3✔
79
                continue;
2✔
80
            }
81

82
            auto access_node = dynamic_cast<data_flow::AccessNode*>(use->element());
3✔
83
            if (!access_node) {
3✔
NEW
84
                continue;
×
85
            }
86
            auto& use_graph = access_node->get_parent();
3✔
87
            if (use_graph.out_degree(*access_node) + use_graph.in_degree(*access_node) != 1) {
3✔
NEW
88
                continue;
×
89
            }
90
            data_flow::Memlet* use_edge = nullptr;
3✔
91
            if (use_graph.in_degree(*access_node) == 1) {
3✔
92
                use_edge = &*use_graph.in_edges(*access_node).begin();
1✔
93
            } else {
1✔
94
                use_edge = &*use_graph.out_edges(*access_node).begin();
2✔
95
            }
96
            if (use_edge->type() == data_flow::MemletType::Dereference_Dst ||
6✔
97
                use_edge->type() == data_flow::MemletType::Dereference_Src) {
3✔
NEW
98
                continue;
×
99
            }
100
            if (use_edge->subset().empty()) {
3✔
UNCOV
101
                continue;
×
102
            }
103

104
            if (!dominance_analysis.dominates(*move, *use)) {
3✔
105
                continue;
×
106
            }
107

108
            // Criterion: View must be a pointer
109
            auto& base_type = use_edge->base_type();
3✔
110
            if (base_type.type_id() != types::TypeID::Pointer) {
3✔
UNCOV
111
                continue;
×
112
            }
113
            auto& base_pointer_type = static_cast<const types::Pointer&>(base_type);
3✔
114
            if (!base_pointer_type.has_pointee_type()) {
3✔
UNCOV
115
                continue;
×
116
            }
117
            auto& pointee_type = base_pointer_type.pointee_type();
3✔
118
            auto pointee_type_size = types::get_type_size(pointee_type, false);
3✔
119
            if (pointee_type_size.is_null()) {
3✔
UNCOV
120
                continue;
×
121
            }
122
            if (!SymEngine::is_a<SymEngine::Integer>(*pointee_type_size)) {
3✔
123
                continue;
×
124
            }
125
            int pointee_type_int = SymEngine::rcp_static_cast<const SymEngine::Integer>(pointee_type_size)->as_int();
3✔
126
            if (move_offset_bytes % pointee_type_int != 0) {
3✔
UNCOV
127
                continue;
×
128
            }
129
            int elements = move_offset_bytes / pointee_type_int;
3✔
130

131
            data_flow::Subset new_subset = use_edge->subset();
3✔
132
            auto offset = use_edge->subset().at(0);
3✔
133
            new_subset[0] = symbolic::add(offset, symbolic::integer(elements));
3✔
134
            use_edge->set_subset(new_subset);
3✔
135
            access_node->data(move_src.data());
3✔
136

137
            applied = true;
3✔
138
        }
3✔
139
    }
3✔
140

141
    return applied;
2✔
142
};
×
143

144
} // namespace passes
145
} // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc