blob: 80f92171590966aacbe38aaa18a41fc9b4ee4680 [file] [log] [blame]
Ian Romanickde7c3fe2010-08-27 13:59:49 -07001/*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "glsl_types.h"
25#include "loop_analysis.h"
26#include "ir_hierarchical_visitor.h"
27
28class loop_unroll_visitor : public ir_hierarchical_visitor {
29public:
Luca Barbierie591c462010-09-05 22:29:58 +020030 loop_unroll_visitor(loop_state *state, unsigned max_iterations)
Ian Romanickde7c3fe2010-08-27 13:59:49 -070031 {
32 this->state = state;
33 this->progress = false;
Luca Barbierie591c462010-09-05 22:29:58 +020034 this->max_iterations = max_iterations;
Ian Romanickde7c3fe2010-08-27 13:59:49 -070035 }
36
37 virtual ir_visitor_status visit_leave(ir_loop *ir);
38
39 loop_state *state;
40
41 bool progress;
Luca Barbierie591c462010-09-05 22:29:58 +020042 unsigned max_iterations;
Ian Romanickde7c3fe2010-08-27 13:59:49 -070043};
44
45
46ir_visitor_status
47loop_unroll_visitor::visit_leave(ir_loop *ir)
48{
49 loop_variable_state *const ls = this->state->get(ir);
50
51 /* If we've entered a loop that hasn't been analyzed, something really,
52 * really bad has happened.
53 */
54 if (ls == NULL) {
55 assert(ls != NULL);
56 return visit_continue;
57 }
58
59 /* Don't try to unroll loops where the number of iterations is not known
60 * at compile-time.
61 */
62 if (ls->max_iterations < 0)
63 return visit_continue;
64
65 /* Don't try to unroll loops that have zillions of iterations either.
66 */
Luca Barbierie591c462010-09-05 22:29:58 +020067 if (ls->max_iterations > max_iterations)
Ian Romanickde7c3fe2010-08-27 13:59:49 -070068 return visit_continue;
69
70 if (ls->num_loop_jumps > 0)
71 return visit_continue;
72
73 void *const mem_ctx = talloc_parent(ir);
74
75 for (int i = 0; i < ls->max_iterations; i++) {
76 exec_list copy_list;
77
78 copy_list.make_empty();
79 clone_ir_list(mem_ctx, &copy_list, &ir->body_instructions);
80
81 ir->insert_before(&copy_list);
82 }
83
84 /* The loop has been replaced by the unrolled copies. Remove the original
85 * loop from the IR sequence.
86 */
87 ir->remove();
88
89 this->progress = true;
90 return visit_continue;
91}
92
93
94bool
Luca Barbierie591c462010-09-05 22:29:58 +020095unroll_loops(exec_list *instructions, loop_state *ls, unsigned max_iterations)
Ian Romanickde7c3fe2010-08-27 13:59:49 -070096{
Luca Barbierie591c462010-09-05 22:29:58 +020097 loop_unroll_visitor v(ls, max_iterations);
Ian Romanickde7c3fe2010-08-27 13:59:49 -070098
99 v.run(instructions);
100
101 return v.progress;
102}