• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2014 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 /**
25  * \file opt_conditional_discard.cpp
26  *
27  * Replace
28  *
29  *    if (cond) discard;
30  *
31  * with
32  *
33  *    (discard <condition>)
34  */
35 
36 #include "compiler/glsl_types.h"
37 #include "ir.h"
38 
39 namespace {
40 
41 class opt_conditional_discard_visitor : public ir_hierarchical_visitor {
42 public:
opt_conditional_discard_visitor()43    opt_conditional_discard_visitor()
44    {
45       progress = false;
46    }
47 
48    ir_visitor_status visit_leave(ir_if *);
49 
50    bool progress;
51 };
52 
53 } /* anonymous namespace */
54 
55 bool
opt_conditional_discard(exec_list * instructions)56 opt_conditional_discard(exec_list *instructions)
57 {
58    opt_conditional_discard_visitor v;
59    v.run(instructions);
60    return v.progress;
61 }
62 
63 ir_visitor_status
visit_leave(ir_if * ir)64 opt_conditional_discard_visitor::visit_leave(ir_if *ir)
65 {
66    /* Look for "if (...) discard" with no else clause or extra statements. */
67    if (ir->then_instructions.is_empty() ||
68        !ir->then_instructions.get_head_raw()->next->is_tail_sentinel() ||
69        !((ir_instruction *) ir->then_instructions.get_head_raw())->as_discard() ||
70        !ir->else_instructions.is_empty())
71       return visit_continue;
72 
73    /* Move the condition and replace the ir_if with the ir_discard. */
74    ir_discard *discard = (ir_discard *) ir->then_instructions.get_head_raw();
75    if (!discard->condition)
76       discard->condition = ir->condition;
77    else {
78       void *ctx = ralloc_parent(ir);
79       discard->condition = new(ctx) ir_expression(ir_binop_logic_and,
80                                                   ir->condition,
81                                                   discard->condition);
82    }
83    ir->replace_with(discard);
84 
85    progress = true;
86 
87    return visit_continue;
88 }
89