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

daisytuner / sdfglib / 16779684622

06 Aug 2025 02:21PM UTC coverage: 64.3% (-1.0%) from 65.266%
16779684622

push

github

web-flow
Merge pull request #172 from daisytuner/opaque-pointers

Opaque pointers, typed memlets, untyped tasklet connectors

330 of 462 new or added lines in 38 files covered. (71.43%)

382 existing lines in 30 files now uncovered.

8865 of 13787 relevant lines covered (64.3%)

116.73 hits per line

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

82.11
/src/passes/dataflow/redundant_array_elimination.cpp
1
#include "sdfg/passes/dataflow/redundant_array_elimination.h"
2

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

6
namespace sdfg {
7
namespace passes {
8

9
RedundantArrayElimination::RedundantArrayElimination()
4✔
10
    : Pass() {
4✔
11

12
      };
4✔
13

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

16
bool RedundantArrayElimination::
17
    run_pass(builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager) {
4✔
18
    bool applied = false;
4✔
19

20
    auto& sdfg = builder.subject();
4✔
21
    auto& users = analysis_manager.get<analysis::Users>();
4✔
22
    for (auto& name : sdfg.containers()) {
31✔
23
        // Criterion: Only transients
24
        if (!sdfg.is_transient(name)) {
27✔
25
            continue;
4✔
26
        }
27
        if (!users.moves(name).empty() || !users.views(name).empty()) {
23✔
28
            continue;
×
29
        }
30
        if (users.writes(name).size() != 1) {
23✔
31
            continue;
19✔
32
        }
33
        std::unique_ptr<types::IType> type = sdfg.type(name).clone();
4✔
34
        if (dynamic_cast<const types::Array*>(type.get()) == nullptr) {
4✔
35
            continue;
×
36
        }
37

38
        // Criterion: Data must depend on externals
39
        auto write = users.writes(name)[0];
4✔
40
        auto write_node = dynamic_cast<data_flow::AccessNode*>(write->element());
4✔
41
        auto& graph = write_node->get_parent();
4✔
42
        if (graph.in_degree(*write_node) == 0) {
4✔
43
            continue;
×
44
        }
45
        auto& write_edge = *graph.in_edges(*write_node).begin();
4✔
46
        auto& write_subset = write_edge.subset();
4✔
47

48
        // Access nodes for write
49
        std::vector<symbolic::Symbol> input_symbols;
4✔
50
        for (auto& e : graph.in_edges(write_edge.src())) {
8✔
51
            auto& src = e.src();
4✔
52
            if (graph.in_degree(src) != 0) {
4✔
53
                continue;
×
54
            }
55
            auto access_node = dynamic_cast<data_flow::AccessNode*>(&src);
4✔
56
            input_symbols.push_back(symbolic::symbol(access_node->data()));
4✔
57
            for (auto& subset : e.subset()) {
20✔
58
                auto atoms = symbolic::atoms(subset);
16✔
59
                for (auto& atom : atoms) {
32✔
60
                    if (SymEngine::is_a<SymEngine::Symbol>(*atom)) {
16✔
61
                        auto symbol = SymEngine::rcp_static_cast<const SymEngine::Symbol>(atom);
16✔
62
                        input_symbols.push_back(symbol);
16✔
63
                    }
16✔
64
                }
65
            }
16✔
66
        }
67

68
        bool has_redundant_dimension = false;
4✔
69
        // Criterion: Data must be an Array
70
        uint depth = 0;
4✔
71
        while (auto atype = dynamic_cast<const types::Array*>(type.get())) {
12✔
72
            auto subset = write_subset[depth];
11✔
73
            auto atoms = symbolic::atoms(subset);
11✔
74
            bool dependency_exists = false;
11✔
75

76
            for (auto& atom : atoms) {
14✔
77
                if (SymEngine::is_a<SymEngine::Symbol>(*atom)) {
11✔
78
                    auto symbol = SymEngine::rcp_static_cast<const SymEngine::Symbol>(atom);
11✔
79
                    for (auto& input_symbol : input_symbols) {
43✔
80
                        if (symbolic::eq(symbol, input_symbol)) {
40✔
81
                            dependency_exists = true;
8✔
82
                            break;
8✔
83
                        }
84
                    }
85
                    if (dependency_exists) {
11✔
86
                        break;
8✔
87
                    }
88
                }
11✔
89
            }
90
            if (!dependency_exists) {
11✔
91
                has_redundant_dimension = true;
3✔
92
                break;
3✔
93
            }
94
            type = atype->element_type().clone();
8✔
95
            depth++;
8✔
96
        }
11✔
97

98
        if (!has_redundant_dimension) {
4✔
99
            continue;
1✔
100
        }
101

102
        // Construct new type
103
        auto atype = static_cast<const types::Array*>(type.get());
3✔
104
        std::unique_ptr<types::IType> inner_type = atype->element_type().clone();
3✔
105
        std::unique_ptr<types::IType> new_type = types::recombine_array_type(sdfg.type(name), depth, *inner_type.get());
3✔
106

107
        // Replace data type
108
        builder.change_type(name, *new_type.get());
3✔
109

110
        // Replace all reads
111
        for (auto& user : users.reads(name)) {
3✔
112
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
×
113
            if (access_node == nullptr) {
×
114
                throw InvalidSDFGException("RedundantArrayElimination: Expected AccessNode");
×
115
            }
116

117
            auto& graph = access_node->get_parent();
×
118
            for (auto& oedge : graph.out_edges(*access_node)) {
×
119
                auto subset = oedge.subset();
×
120
                subset.erase(subset.begin() + depth);
×
121
                oedge.set_subset(subset);
×
NEW
122
                oedge.set_base_type(*new_type);
×
UNCOV
123
            }
×
124
        }
125
        // Replace all writes
126
        for (auto& user : users.writes(name)) {
6✔
127
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
3✔
128
            if (access_node == nullptr) {
3✔
129
                throw InvalidSDFGException("RedundantArrayElimination: Expected AccessNode");
×
130
            }
131

132
            auto& graph = access_node->get_parent();
3✔
133
            for (auto& iedge : graph.in_edges(*access_node)) {
6✔
134
                auto subset = iedge.subset();
3✔
135
                subset.erase(subset.begin() + depth);
3✔
136
                iedge.set_subset(subset);
3✔
137
                iedge.set_base_type(*new_type);
3✔
138
            }
3✔
139
        }
140

141
        applied = true;
3✔
142
    }
4✔
143

144
    analysis_manager.invalidate_all();
4✔
145

146
    return applied;
4✔
147
};
×
148

149
} // namespace passes
150
} // 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