Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  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. /**
  25.  * \file opt_if_simplification.cpp
  26.  *
  27.  * Moves constant branches of if statements out to the surrounding
  28.  * instruction stream, and inverts if conditionals to avoid empty
  29.  * "then" blocks.
  30.  */
  31.  
  32. #include "ir.h"
  33.  
  34. namespace {
  35.  
  36. class ir_if_simplification_visitor : public ir_hierarchical_visitor {
  37. public:
  38.    ir_if_simplification_visitor()
  39.    {
  40.       this->made_progress = false;
  41.    }
  42.  
  43.    ir_visitor_status visit_leave(ir_if *);
  44.    ir_visitor_status visit_enter(ir_assignment *);
  45.  
  46.    bool made_progress;
  47. };
  48.  
  49. } /* unnamed namespace */
  50.  
  51. /* We only care about the top level "if" instructions, so don't
  52.  * descend into expressions.
  53.  */
  54. ir_visitor_status
  55. ir_if_simplification_visitor::visit_enter(ir_assignment *ir)
  56. {
  57.    (void) ir;
  58.    return visit_continue_with_parent;
  59. }
  60.  
  61. bool
  62. do_if_simplification(exec_list *instructions)
  63. {
  64.    ir_if_simplification_visitor v;
  65.  
  66.    v.run(instructions);
  67.    return v.made_progress;
  68. }
  69.  
  70.  
  71. ir_visitor_status
  72. ir_if_simplification_visitor::visit_leave(ir_if *ir)
  73. {
  74.    /* If the if statement has nothing on either side, remove it. */
  75.    if (ir->then_instructions.is_empty() &&
  76.        ir->else_instructions.is_empty()) {
  77.       ir->remove();
  78.       this->made_progress = true;
  79.       return visit_continue;
  80.    }
  81.  
  82.    /* FINISHME: Ideally there would be a way to note that the condition results
  83.     * FINISHME: in a constant before processing both of the other subtrees.
  84.     * FINISHME: This can probably be done with some flags, but it would take
  85.     * FINISHME: some work to get right.
  86.     */
  87.    ir_constant *condition_constant = ir->condition->constant_expression_value();
  88.    if (condition_constant) {
  89.       /* Move the contents of the one branch of the conditional
  90.        * that matters out.
  91.        */
  92.       if (condition_constant->value.b[0]) {
  93.          ir->insert_before(&ir->then_instructions);
  94.       } else {
  95.          ir->insert_before(&ir->else_instructions);
  96.       }
  97.       ir->remove();
  98.       this->made_progress = true;
  99.       return visit_continue;
  100.    }
  101.  
  102.    /* Turn:
  103.     *
  104.     *     if (cond) {
  105.     *     } else {
  106.     *         do_work();
  107.     *     }
  108.     *
  109.     * into :
  110.     *
  111.     *     if (!cond)
  112.     *         do_work();
  113.     *
  114.     * which avoids control flow for "else" (which is usually more
  115.     * expensive than normal operations), and the "not" can usually be
  116.     * folded into the generation of "cond" anyway.
  117.     */
  118.    if (ir->then_instructions.is_empty()) {
  119.       ir->condition = new(ralloc_parent(ir->condition))
  120.          ir_expression(ir_unop_logic_not, ir->condition);
  121.       ir->else_instructions.move_nodes_to(&ir->then_instructions);
  122.       this->made_progress = true;
  123.    }
  124.  
  125.    return visit_continue;
  126. }
  127.