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

daisytuner / sdfglib / 15656007340

14 Jun 2025 08:51PM UTC coverage: 13.234% (-49.9%) from 63.144%
15656007340

Pull #76

github

web-flow
Merge 9586c8161 into 413c53212
Pull Request #76: New Loop Dependency Analysis

361 of 465 new or added lines in 7 files covered. (77.63%)

6215 existing lines in 110 files now uncovered.

1612 of 12181 relevant lines covered (13.23%)

13.64 hits per line

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

0.0
/src/passes/dataflow/view_propagation.cpp
1
#include "sdfg/passes/dataflow/view_propagation.h"
2

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

6
namespace sdfg {
7
namespace passes {
8

UNCOV
9
ViewPropagation::ViewPropagation()
×
UNCOV
10
    : Pass() {
×
11

UNCOV
12
      };
×
13

14
std::string ViewPropagation::name() { return "ViewPropagation"; };
×
15

UNCOV
16
bool ViewPropagation::run_pass(builder::StructuredSDFGBuilder& builder,
×
17
                               analysis::AnalysisManager& analysis_manager) {
UNCOV
18
    bool applied = false;
×
19

UNCOV
20
    auto& sdfg = builder.subject();
×
21

22
    // Replaces all views by their original pointers
UNCOV
23
    auto& users = analysis_manager.get<analysis::Users>();
×
UNCOV
24
    std::unordered_set<std::string> reduced;
×
UNCOV
25
    for (auto& container : sdfg.containers()) {
×
UNCOV
26
        if (reduced.find(container) != reduced.end()) {
×
UNCOV
27
            continue;
×
28
        }
UNCOV
29
        auto& type = sdfg.type(container);
×
UNCOV
30
        if (!dynamic_cast<const types::Pointer*>(&type)) {
×
31
            continue;
×
32
        }
UNCOV
33
        if (sdfg.is_external(container)) {
×
34
            continue;
×
35
        }
36

37
        // Collect all moves of the pointer
UNCOV
38
        auto moves = users.moves(container);
×
UNCOV
39
        if (moves.empty() || !users.views(container).empty()) {
×
40
            continue;
×
41
        }
UNCOV
42
        auto uses = users.uses(container);
×
UNCOV
43
        for (auto& move : moves) {
×
44
            // Location of where the view is created
UNCOV
45
            auto& access_node = dynamic_cast<data_flow::AccessNode&>(*move->element());
×
UNCOV
46
            auto& graph = *move->parent();
×
UNCOV
47
            auto& edge = *graph.in_edges(access_node).begin();
×
48

49
            // The original pointer
UNCOV
50
            auto& viewed_node = dynamic_cast<const data_flow::AccessNode&>(edge.src());
×
UNCOV
51
            auto& viewed_container = viewed_node.data();
×
UNCOV
52
            auto& viewed_subset = edge.subset();
×
UNCOV
53
            if (viewed_subset.empty()) {
×
54
                continue;
×
55
            }
UNCOV
56
            if (edge.src_conn() != "void") {
×
57
                continue;
×
58
            }
UNCOV
59
            if (symbolic::is_pointer(symbolic::symbol(viewed_container))) {
×
60
                continue;
×
61
            }
UNCOV
62
            types::Pointer viewed_type(
×
UNCOV
63
                types::infer_type(sdfg, sdfg.type(viewed_container), viewed_subset));
×
UNCOV
64
            if (viewed_type != type) {
×
65
                continue;
×
66
            }
67

68
            // Iterate over all uses of the viewing container
69
            // Replace the view by the original pointer if possible
UNCOV
70
            for (auto& user : uses) {
×
UNCOV
71
                if (user->use() == analysis::Use::MOVE || user->use() == analysis::Use::VIEW) {
×
UNCOV
72
                    continue;
×
73
                }
74
                // Criterion: The assignment of the view must dominate the use of the view
UNCOV
75
                if (!users.dominates(*move, *user)) {
×
76
                    continue;
×
77
                }
78
                // Criterion: No pointer operations between the assignment and the use
UNCOV
79
                auto uses_between = users.all_uses_between(*move, *user);
×
UNCOV
80
                bool moving_pointers = false;
×
UNCOV
81
                for (auto& use : uses_between) {
×
82
                    if (use->use() != analysis::Use::MOVE) {
×
83
                        continue;
×
84
                    }
85
                    // Viewed container is not constant
86
                    if (use->container() == viewed_container) {
×
87
                        moving_pointers = true;
×
88
                        break;
×
89
                    }
90
                    // Moved container is not constant
91
                    if (use->container() == container) {
×
92
                        moving_pointers = true;
×
93
                        break;
×
94
                    }
95

96
                    // Unsafe pointer operations
97
                    auto& move_node = dynamic_cast<data_flow::AccessNode&>(*use->element());
×
98
                    auto& move_graph = *use->parent();
×
99
                    auto& move_edge = *move_graph.in_edges(move_node).begin();
×
100
                    auto& view_node = dynamic_cast<data_flow::AccessNode&>(move_edge.src());
×
101
                    if (move_edge.dst_conn() == "void" ||
×
102
                        symbolic::is_pointer(symbolic::symbol(view_node.data()))) {
×
103
                        moving_pointers = true;
×
104
                        break;
×
105
                    }
106
                }
UNCOV
107
                if (moving_pointers) {
×
108
                    continue;
×
109
                }
110

111
                // Replace the view by the original pointer
UNCOV
112
                if (auto use_node = dynamic_cast<data_flow::AccessNode*>(user->element())) {
×
UNCOV
113
                    auto use_graph = user->parent();
×
UNCOV
114
                    use_node->data() = viewed_container;
×
115

116
                    // Update subsets
UNCOV
117
                    for (auto& oedge : use_graph->out_edges(*use_node)) {
×
118
                        auto& old_subset = oedge.subset();
×
119

120
                        // Add leading dimensions
121
                        data_flow::Subset new_subset(viewed_subset.begin(),
×
122
                                                     viewed_subset.end() - 1);
×
123

124
                        // Accumulate overlapping dimension
125
                        auto& dim = old_subset[0];
×
126
                        auto& alias_dim = viewed_subset.back();
×
127
                        auto new_dim = symbolic::add(alias_dim, dim);
×
128
                        new_subset.push_back(new_dim);
×
129

130
                        // Add trailing dimensions
131
                        for (size_t i = 1; i < old_subset.size(); i++) {
×
132
                            auto& old_dim = old_subset[i];
×
133
                            new_subset.push_back(old_dim);
×
134
                        }
×
135

136
                        oedge.subset() = new_subset;
×
137
                    }
×
UNCOV
138
                    for (auto& iedge : use_graph->in_edges(*use_node)) {
×
UNCOV
139
                        auto& old_subset = iedge.subset();
×
140

141
                        // Add leading dimensions
UNCOV
142
                        data_flow::Subset new_subset(viewed_subset.begin(),
×
UNCOV
143
                                                     viewed_subset.end() - 1);
×
144

145
                        // Accumulate overlapping dimension
UNCOV
146
                        auto& dim = old_subset[0];
×
UNCOV
147
                        auto& alias_dim = viewed_subset.back();
×
UNCOV
148
                        auto new_dim = symbolic::add(alias_dim, dim);
×
UNCOV
149
                        new_subset.push_back(new_dim);
×
150

151
                        // Add trailing dimensions
UNCOV
152
                        for (size_t i = 1; i < old_subset.size(); i++) {
×
153
                            auto& old_dim = old_subset[i];
×
154
                            new_subset.push_back(old_dim);
×
155
                        }
×
156

UNCOV
157
                        iedge.subset() = new_subset;
×
UNCOV
158
                    }
×
159

UNCOV
160
                    applied = true;
×
UNCOV
161
                    reduced.insert(viewed_container);
×
UNCOV
162
                }
×
UNCOV
163
            }
×
UNCOV
164
        }
×
UNCOV
165
    }
×
166

UNCOV
167
    return applied;
×
UNCOV
168
};
×
169

170
}  // namespace passes
171
}  // 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

© 2026 Coveralls, Inc