• 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

89.47
/src/passes/normalization/conditional_tasklet_propagation.cpp
1
#include "sdfg/passes/normalization/conditional_tasklet_propagation.h"
2

3
#include "sdfg/symbolic/symbolic.h"
4

5
namespace sdfg {
6
namespace passes {
7

8
ConditionalTaskletPropagation::ConditionalTaskletPropagation(
3✔
9
    builder::StructuredSDFGBuilder& builder, analysis::AnalysisManager& analysis_manager)
10
    : visitor::StructuredSDFGVisitor(builder, analysis_manager) {}
3✔
11

12
bool ConditionalTaskletPropagation::can_be_applied(structured_control_flow::Sequence& parent,
3✔
13
                                                   structured_control_flow::IfElse& if_else,
14
                                                   size_t index) {
15
    auto& sdfg = builder_.subject();
3✔
16
    auto branch = if_else.at(index);
3✔
17
    auto& root = branch.first;
3✔
18
    auto& condition = branch.second;
3✔
19

20
    if (root.size() == 0) {
3✔
21
        return false;
×
22
    }
23

24
    // Criterion: Pure data-flow
25
    for (size_t i = 0; i < root.size(); i++) {
6✔
26
        auto child = root.at(i);
4✔
27
        if (!dynamic_cast<structured_control_flow::Block*>(&child.first)) {
4✔
UNCOV
28
            return false;
×
29
        }
30
        if (!child.second.assignments().empty()) {
4✔
31
            return false;
1✔
32
        }
33
    }
3✔
34

35
    // Criterion: Symbols used in condition are read-only
36
    auto& all_users = analysis_manager_.get<analysis::Users>();
2✔
37
    analysis::UsersView users(all_users, root);
2✔
38
    if (!users.moves().empty() || !users.views().empty()) {
2✔
39
        return false;
×
40
    }
41

42
    std::unordered_set<std::string> unsafe_symbols;
2✔
43
    for (auto& atom : symbolic::atoms(condition)) {
4✔
44
        auto sym = SymEngine::rcp_static_cast<const SymEngine::Symbol>(atom);
2✔
45
        if (symbolic::is_pointer(sym)) {
2✔
46
            return false;
×
47
        }
48
        if (!symbolic::is_nvptx(sym)) {
2✔
49
            if (!dynamic_cast<const types::Scalar*>(&sdfg.type(sym->get_name()))) {
2✔
50
                return false;
×
51
            }
52
        }
2✔
53
        if (users.writes(sym->get_name()).size() > 0) {
2✔
54
            return false;
×
55
        }
56
        unsafe_symbols.insert(sym->get_name());
2✔
57
    }
2✔
58

59
    // Unsafe memory accesses: e.g., if (n > 0) A[n - 1]
60
    for (auto write : users.writes()) {
4✔
61
        auto& container = write->container();
2✔
62
        auto& type = sdfg.type(container);
2✔
63
        if (!dynamic_cast<const types::Scalar*>(&type) ||
3✔
64
            !types::is_integer(type.primitive_type())) {
1✔
65
            continue;
1✔
66
        }
67
        unsafe_symbols.insert(container);
1✔
68
    }
69

70
    for (auto read : users.reads()) {
3✔
71
        auto& container = read->container();
1✔
72
        if (symbolic::is_nvptx(symbolic::symbol(container))) {
1✔
73
            continue;
×
74
        }
75
        auto& type = sdfg.type(container);
1✔
76
        if (!dynamic_cast<const types::Scalar*>(&type) ||
2✔
77
            !types::is_integer(type.primitive_type())) {
1✔
78
            continue;
×
79
        }
80
        if (!dynamic_cast<data_flow::Memlet*>(read->element())) {
1✔
81
            continue;
×
82
        }
83
        if (unsafe_symbols.find(container) != unsafe_symbols.end()) {
1✔
84
            return false;
1✔
85
        }
86
    }
87

88
    return true;
1✔
89
};
3✔
90

91
void ConditionalTaskletPropagation::apply(structured_control_flow::Sequence& parent,
1✔
92
                                          structured_control_flow::IfElse& if_else, size_t index,
93
                                          const symbolic::Condition& condition) {
94
    auto& sdfg = builder_.subject();
1✔
95

96
    auto branch = if_else.at(index);
1✔
97
    auto& root = branch.first;
1✔
98

99
    auto& users = analysis_manager_.get<analysis::Users>();
1✔
100
    analysis::UsersView users_branch(users, root);
1✔
101

102
    // Determine all writes to externals
103
    auto locals_vars = users.locals(sdfg, root);
1✔
104
    std::unordered_set<std::string> candidates;
1✔
105
    for (auto write : users_branch.writes()) {
2✔
106
        auto& container = write->container();
1✔
107
        if (locals_vars.find(container) != locals_vars.end()) {
1✔
108
            continue;
×
109
        }
110

111
        candidates.insert(container);
1✔
112
    }
113

114
    // Make writes conditional
115
    for (auto& write : candidates) {
2✔
116
        auto uses = users_branch.writes(write);
1✔
117
        for (auto& use : uses) {
2✔
118
            auto access_node = static_cast<data_flow::AccessNode*>(use->element());
1✔
119
            auto& graph = access_node->get_parent();
1✔
120
            auto& edge = *graph.in_edges(*access_node).begin();
1✔
121
            auto& tasklet = static_cast<data_flow::Tasklet&>(edge.src());
1✔
122
            tasklet.condition() = symbolic::And(tasklet.condition(), condition);
1✔
123
        }
124
    }
1✔
125

126
    // Remove branch
127
    auto& new_sequence = builder_.add_sequence_before(parent, if_else).first;
1✔
128
    deepcopy::StructuredSDFGDeepCopy copier(builder_, new_sequence, root);
1✔
129
    copier.copy();
1✔
130

131
    builder_.remove_case(if_else, index);
1✔
132
};
1✔
133

134
bool ConditionalTaskletPropagation::accept(structured_control_flow::Sequence& parent,
3✔
135
                                           structured_control_flow::IfElse& if_else) {
136
    for (size_t i = 0; i < if_else.size(); i++) {
4✔
137
        if (!this->can_be_applied(parent, if_else, i)) {
3✔
138
            return false;
2✔
139
        }
140
    }
1✔
141

142
    auto condition = symbolic::__true__();
1✔
143
    for (size_t j = 0; j < if_else.size();) {
2✔
144
        auto branch_condition = if_else.at(j).second;
1✔
145
        auto apply_condition = symbolic::And(condition, if_else.at(j).second);
1✔
146
        this->apply(parent, if_else, j, apply_condition);
1✔
147
        condition = symbolic::And(condition, symbolic::Not(branch_condition));
1✔
148
    }
1✔
149

150
    return true;
1✔
151
};
3✔
152

153
}  // namespace passes
154
}  // 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