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

daisytuner / sdfglib / 15044057891

15 May 2025 11:42AM UTC coverage: 59.37% (+1.8%) from 57.525%
15044057891

push

github

web-flow
Merge pull request #14 from daisytuner/sanitizers

enables sanitizer on unit tests

63 of 67 new or added lines in 47 files covered. (94.03%)

570 existing lines in 62 files now uncovered.

7356 of 12390 relevant lines covered (59.37%)

505.93 hits per line

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

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

3
#include <cassert>
4

5
#include "sdfg/data_flow/access_node.h"
6
#include "sdfg/structured_control_flow/for.h"
7
#include "sdfg/symbolic/symbolic.h"
8
#include "sdfg/types/array.h"
9
#include "sdfg/types/type.h"
10
#include "sdfg/types/utils.h"
11
#include "symengine/symbol.h"
12

13
namespace sdfg {
14
namespace passes {
15

16
RedundantArrayElimination::RedundantArrayElimination()
4✔
17
    : Pass(){
4✔
18

19
      };
4✔
20

21
std::string RedundantArrayElimination::name() { return "RedundantArrayElimination"; };
×
22

23
bool RedundantArrayElimination::run_pass(builder::StructuredSDFGBuilder& builder,
4✔
24
                                         analysis::AnalysisManager& analysis_manager) {
25
    bool applied = false;
4✔
26

27
    auto& sdfg = builder.subject();
4✔
28
    auto& users = analysis_manager.get<analysis::Users>();
4✔
29
    for (auto& name : sdfg.containers()) {
31✔
30
        // Criterion: Only transients
31
        if (!sdfg.is_transient(name)) {
27✔
32
            continue;
4✔
33
        }
34
        if (!users.moves(name).empty() || !users.views(name).empty()) {
23✔
35
            continue;
×
36
        }
37
        if (users.writes(name).size() != 1) {
23✔
38
            continue;
19✔
39
        }
40
        std::unique_ptr<types::IType> type = sdfg.type(name).clone();
4✔
41
        if (auto atype = dynamic_cast<const types::Array*>(type.get())) {
4✔
42
        } else {
4✔
43
            continue;
×
44
        }
45

46
        // Criterion: Data must depend on externals
47
        auto write = users.writes(name)[0];
4✔
48
        auto write_node = dynamic_cast<data_flow::AccessNode*>(write->element());
4✔
49
        auto& graph = write_node->get_parent();
4✔
50
        if (graph.in_degree(*write_node) == 0) {
4✔
51
            continue;
×
52
        }
53
        auto& write_edge = *graph.in_edges(*write_node).begin();
4✔
54
        auto& write_subset = write_edge.subset();
4✔
55

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

76
        bool has_redundant_dimension = false;
4✔
77
        // Criterion: Data must be an Array
78
        uint depth = 0;
4✔
79
        while (auto atype = dynamic_cast<const types::Array*>(type.get())) {
12✔
80
            auto subset = write_subset[depth];
11✔
81
            auto atoms = symbolic::atoms(subset);
11✔
82
            bool dependency_exists = false;
11✔
83

84
            for (auto& atom : atoms) {
14✔
85
                if (SymEngine::is_a<SymEngine::Symbol>(*atom)) {
11✔
86
                    auto symbol = SymEngine::rcp_static_cast<const SymEngine::Symbol>(atom);
11✔
87
                    for (auto& input_symbol : input_symbols) {
43✔
88
                        if (symbolic::eq(symbol, input_symbol)) {
40✔
89
                            dependency_exists = true;
8✔
90
                            break;
8✔
91
                        }
92
                    }
93
                    if (dependency_exists) {
11✔
94
                        break;
8✔
95
                    }
96
                }
11✔
97
            }
98
            if (!dependency_exists) {
11✔
99
                has_redundant_dimension = true;
3✔
100
                break;
3✔
101
            }
102
            type = atype->element_type().clone();
8✔
103
            depth++;
8✔
104
        }
11✔
105

106
        if (!has_redundant_dimension) {
4✔
107
            continue;
1✔
108
        }
109

110
        // Construct new type
111
        auto atype = static_cast<const types::Array*>(type.get());
3✔
112
        std::unique_ptr<types::IType> inner_type = atype->element_type().clone();
3✔
113
        std::unique_ptr<types::IType> new_type =
114
            types::recombine_array_type(sdfg.type(name), depth, *inner_type.get());
3✔
115

116
        // Replace data type
117
        builder.change_type(name, *new_type.get());
3✔
118

119
        // Replace all reads
120
        for (auto& user : users.reads(name)) {
3✔
121
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
×
122
            assert(access_node != nullptr && "Expected AccessNode");
×
123

124
            auto& graph = access_node->get_parent();
×
125
            for (auto& oedge : graph.out_edges(*access_node)) {
×
126
                auto& subset = oedge.subset();
×
127
                subset.erase(subset.begin() + depth);
×
128
            }
129
        }
130
        // Replace all writes
131
        for (auto& user : users.writes(name)) {
6✔
132
            auto access_node = dynamic_cast<data_flow::AccessNode*>(user->element());
3✔
133
            assert(access_node != nullptr && "Expected AccessNode");
6✔
134

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

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

145
    analysis_manager.invalidate_all();
4✔
146

147
    return applied;
4✔
UNCOV
148
};
×
149

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