blob: 90973b567078befebef30a9e3ebcb3a4b25c47e0 [file] [log] [blame]
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +01001/*
Hans-Kristian Arntzen47044822021-01-14 16:07:49 +01002 * Copyright 2016-2021 Arm Limited
Jon Leechf2a65542021-05-08 01:47:48 -07003 * SPDX-License-Identifier: Apache-2.0 OR MIT
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +01004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
Hans-Kristian Arntzencf1e9e02020-11-25 15:22:08 +010018/*
19 * At your option, you may choose to accept this material under either:
20 * 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
21 * 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
Hans-Kristian Arntzencf1e9e02020-11-25 15:22:08 +010022 */
23
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010024#ifndef SPIRV_CROSS_CFG_HPP
25#define SPIRV_CROSS_CFG_HPP
26
Hans-Kristian Arntzenb2c2e642017-03-25 16:25:30 +010027#include "spirv_common.hpp"
Hans-Kristian Arntzenbf5c0752017-03-25 16:28:44 +010028#include <assert.h>
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010029
Hans-Kristian Arntzen9b92e682019-03-29 10:29:44 +010030namespace SPIRV_CROSS_NAMESPACE
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010031{
Hans-Kristian Arntzenb2c2e642017-03-25 16:25:30 +010032class Compiler;
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010033class CFG
34{
35public:
36 CFG(Compiler &compiler, const SPIRFunction &function);
37
38 Compiler &get_compiler()
39 {
40 return compiler;
41 }
42
Hans-Kristian Arntzen5ff11cc2016-11-18 16:45:11 +010043 const Compiler &get_compiler() const
44 {
45 return compiler;
46 }
47
48 const SPIRFunction &get_function() const
49 {
50 return func;
51 }
52
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010053 uint32_t get_immediate_dominator(uint32_t block) const
54 {
Hans-Kristian Arntzen57be9032019-01-10 14:35:34 +010055 auto itr = immediate_dominators.find(block);
56 if (itr != std::end(immediate_dominators))
57 return itr->second;
58 else
59 return 0;
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010060 }
61
Hans-Kristian Arntzen5ff11cc2016-11-18 16:45:11 +010062 uint32_t get_visit_order(uint32_t block) const
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010063 {
Hans-Kristian Arntzen57be9032019-01-10 14:35:34 +010064 auto itr = visit_order.find(block);
65 assert(itr != std::end(visit_order));
66 int v = itr->second.get();
Hans-Kristian Arntzen5ff11cc2016-11-18 16:45:11 +010067 assert(v > 0);
68 return uint32_t(v);
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +010069 }
70
71 uint32_t find_common_dominator(uint32_t a, uint32_t b) const;
72
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +020073 const SmallVector<uint32_t> &get_preceding_edges(uint32_t block) const
Hans-Kristian Arntzen4f07a322016-12-15 17:14:47 +010074 {
Hans-Kristian Arntzen57be9032019-01-10 14:35:34 +010075 auto itr = preceding_edges.find(block);
76 if (itr != std::end(preceding_edges))
77 return itr->second;
78 else
79 return empty_vector;
Hans-Kristian Arntzen4f07a322016-12-15 17:14:47 +010080 }
81
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +020082 const SmallVector<uint32_t> &get_succeeding_edges(uint32_t block) const
Hans-Kristian Arntzen4f07a322016-12-15 17:14:47 +010083 {
Hans-Kristian Arntzen57be9032019-01-10 14:35:34 +010084 auto itr = succeeding_edges.find(block);
85 if (itr != std::end(succeeding_edges))
86 return itr->second;
87 else
88 return empty_vector;
Hans-Kristian Arntzen4f07a322016-12-15 17:14:47 +010089 }
90
91 template <typename Op>
Hans-Kristian Arntzenf0c50a62017-07-25 18:22:15 +020092 void walk_from(std::unordered_set<uint32_t> &seen_blocks, uint32_t block, const Op &op) const
Hans-Kristian Arntzen4f07a322016-12-15 17:14:47 +010093 {
Hans-Kristian Arntzenf0c50a62017-07-25 18:22:15 +020094 if (seen_blocks.count(block))
95 return;
96 seen_blocks.insert(block);
97
Hans-Kristian Arntzen5d97dae2019-08-26 15:36:23 +020098 if (op(block))
99 {
100 for (auto b : get_succeeding_edges(block))
101 walk_from(seen_blocks, b, op);
102 }
Hans-Kristian Arntzen4f07a322016-12-15 17:14:47 +0100103 }
104
Hans-Kristian Arntzen03d93ab2019-06-06 11:10:39 +0200105 uint32_t find_loop_dominator(uint32_t block) const;
106
Hans-Kristian Arntzen333980a2019-09-05 12:43:40 +0200107 bool node_terminates_control_flow_in_sub_graph(BlockID from, BlockID to) const;
Hans-Kristian Arntzen5d97dae2019-08-26 15:36:23 +0200108
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +0100109private:
Hans-Kristian Arntzen57be9032019-01-10 14:35:34 +0100110 struct VisitOrder
111 {
112 int &get()
113 {
114 return v;
115 }
116
117 const int &get() const
118 {
119 return v;
120 }
121
122 int v = -1;
123 };
124
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +0100125 Compiler &compiler;
126 const SPIRFunction &func;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200127 std::unordered_map<uint32_t, SmallVector<uint32_t>> preceding_edges;
128 std::unordered_map<uint32_t, SmallVector<uint32_t>> succeeding_edges;
Hans-Kristian Arntzen57be9032019-01-10 14:35:34 +0100129 std::unordered_map<uint32_t, uint32_t> immediate_dominators;
130 std::unordered_map<uint32_t, VisitOrder> visit_order;
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200131 SmallVector<uint32_t> post_order;
132 SmallVector<uint32_t> empty_vector;
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +0100133
134 void add_branch(uint32_t from, uint32_t to);
135 void build_post_order_visit_order();
136 void build_immediate_dominators();
Hans-Kristian Arntzenedbe8672016-11-17 22:15:07 +0100137 bool post_order_visit(uint32_t block);
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +0100138 uint32_t visit_count = 0;
139
Hans-Kristian Arntzen0c9683c2016-11-18 09:59:54 +0100140 bool is_back_edge(uint32_t to) const;
Hans-Kristian Arntzenfc9fe4e2019-07-03 11:18:50 +0200141 bool has_visited_forward_edge(uint32_t to) const;
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +0100142};
143
144class DominatorBuilder
145{
146public:
147 DominatorBuilder(const CFG &cfg);
148
149 void add_block(uint32_t block);
150 uint32_t get_dominator() const
151 {
152 return dominator;
153 }
154
Hans-Kristian Arntzen5ff11cc2016-11-18 16:45:11 +0100155 void lift_continue_block_dominator();
156
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +0100157private:
158 const CFG &cfg;
159 uint32_t dominator = 0;
160};
Hans-Kristian Arntzena489ba72019-04-02 11:19:03 +0200161} // namespace SPIRV_CROSS_NAMESPACE
Hans-Kristian Arntzendad4a342016-11-11 18:04:14 +0100162
163#endif