Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | 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_algebraic.cpp
  26.  *
  27.  * Takes advantage of association, commutivity, and other algebraic
  28.  * properties to simplify expressions.
  29.  */
  30.  
  31. #include "ir.h"
  32. #include "ir_visitor.h"
  33. #include "ir_rvalue_visitor.h"
  34. #include "ir_optimization.h"
  35. #include "glsl_types.h"
  36.  
  37. /**
  38.  * Visitor class for replacing expressions with ir_constant values.
  39.  */
  40.  
  41. class ir_algebraic_visitor : public ir_rvalue_visitor {
  42. public:
  43.    ir_algebraic_visitor()
  44.    {
  45.       this->progress = false;
  46.       this->mem_ctx = NULL;
  47.    }
  48.  
  49.    virtual ~ir_algebraic_visitor()
  50.    {
  51.    }
  52.  
  53.    ir_rvalue *handle_expression(ir_expression *ir);
  54.    void handle_rvalue(ir_rvalue **rvalue);
  55.    bool reassociate_constant(ir_expression *ir1,
  56.                              int const_index,
  57.                              ir_constant *constant,
  58.                              ir_expression *ir2);
  59.    void reassociate_operands(ir_expression *ir1,
  60.                              int op1,
  61.                              ir_expression *ir2,
  62.                              int op2);
  63.    ir_rvalue *swizzle_if_required(ir_expression *expr,
  64.                                   ir_rvalue *operand);
  65.  
  66.    void *mem_ctx;
  67.  
  68.    bool progress;
  69. };
  70.  
  71. static inline bool
  72. is_vec_zero(ir_constant *ir)
  73. {
  74.    return (ir == NULL) ? false : ir->is_zero();
  75. }
  76.  
  77. static inline bool
  78. is_vec_one(ir_constant *ir)
  79. {
  80.    return (ir == NULL) ? false : ir->is_one();
  81. }
  82.  
  83. static void
  84. update_type(ir_expression *ir)
  85. {
  86.    if (ir->operands[0]->type->is_vector())
  87.       ir->type = ir->operands[0]->type;
  88.    else
  89.       ir->type = ir->operands[1]->type;
  90. }
  91.  
  92. void
  93. ir_algebraic_visitor::reassociate_operands(ir_expression *ir1,
  94.                                            int op1,
  95.                                            ir_expression *ir2,
  96.                                            int op2)
  97. {
  98.    ir_rvalue *temp = ir2->operands[op2];
  99.    ir2->operands[op2] = ir1->operands[op1];
  100.    ir1->operands[op1] = temp;
  101.  
  102.    /* Update the type of ir2.  The type of ir1 won't have changed --
  103.     * base types matched, and at least one of the operands of the 2
  104.     * binops is still a vector if any of them were.
  105.     */
  106.    update_type(ir2);
  107.  
  108.    this->progress = true;
  109. }
  110.  
  111. /**
  112.  * Reassociates a constant down a tree of adds or multiplies.
  113.  *
  114.  * Consider (2 * (a * (b * 0.5))).  We want to send up with a * b.
  115.  */
  116. bool
  117. ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
  118.                                            ir_constant *constant,
  119.                                            ir_expression *ir2)
  120. {
  121.    if (!ir2 || ir1->operation != ir2->operation)
  122.       return false;
  123.  
  124.    /* Don't want to even think about matrices. */
  125.    if (ir1->operands[0]->type->is_matrix() ||
  126.        ir1->operands[1]->type->is_matrix() ||
  127.        ir2->operands[0]->type->is_matrix() ||
  128.        ir2->operands[1]->type->is_matrix())
  129.       return false;
  130.  
  131.    ir_constant *ir2_const[2];
  132.    ir2_const[0] = ir2->operands[0]->constant_expression_value();
  133.    ir2_const[1] = ir2->operands[1]->constant_expression_value();
  134.  
  135.    if (ir2_const[0] && ir2_const[1])
  136.       return false;
  137.  
  138.    if (ir2_const[0]) {
  139.       reassociate_operands(ir1, const_index, ir2, 1);
  140.       return true;
  141.    } else if (ir2_const[1]) {
  142.       reassociate_operands(ir1, const_index, ir2, 0);
  143.       return true;
  144.    }
  145.  
  146.    if (reassociate_constant(ir1, const_index, constant,
  147.                             ir2->operands[0]->as_expression())) {
  148.       update_type(ir2);
  149.       return true;
  150.    }
  151.  
  152.    if (reassociate_constant(ir1, const_index, constant,
  153.                             ir2->operands[1]->as_expression())) {
  154.       update_type(ir2);
  155.       return true;
  156.    }
  157.  
  158.    return false;
  159. }
  160.  
  161. /* When eliminating an expression and just returning one of its operands,
  162.  * we may need to swizzle that operand out to a vector if the expression was
  163.  * vector type.
  164.  */
  165. ir_rvalue *
  166. ir_algebraic_visitor::swizzle_if_required(ir_expression *expr,
  167.                                           ir_rvalue *operand)
  168. {
  169.    if (expr->type->is_vector() && operand->type->is_scalar()) {
  170.       return new(mem_ctx) ir_swizzle(operand, 0, 0, 0, 0,
  171.                                      expr->type->vector_elements);
  172.    } else
  173.       return operand;
  174. }
  175.  
  176. ir_rvalue *
  177. ir_algebraic_visitor::handle_expression(ir_expression *ir)
  178. {
  179.    ir_constant *op_const[2] = {NULL, NULL};
  180.    ir_expression *op_expr[2] = {NULL, NULL};
  181.    ir_expression *temp;
  182.    unsigned int i;
  183.  
  184.    assert(ir->get_num_operands() <= 2);
  185.    for (i = 0; i < ir->get_num_operands(); i++) {
  186.       if (ir->operands[i]->type->is_matrix())
  187.          return ir;
  188.  
  189.       op_const[i] = ir->operands[i]->constant_expression_value();
  190.       op_expr[i] = ir->operands[i]->as_expression();
  191.    }
  192.  
  193.    if (this->mem_ctx == NULL)
  194.       this->mem_ctx = ralloc_parent(ir);
  195.  
  196.    switch (ir->operation) {
  197.    case ir_unop_logic_not: {
  198.       enum ir_expression_operation new_op = ir_unop_logic_not;
  199.  
  200.       if (op_expr[0] == NULL)
  201.          break;
  202.  
  203.       switch (op_expr[0]->operation) {
  204.       case ir_binop_less:    new_op = ir_binop_gequal;  break;
  205.       case ir_binop_greater: new_op = ir_binop_lequal;  break;
  206.       case ir_binop_lequal:  new_op = ir_binop_greater; break;
  207.       case ir_binop_gequal:  new_op = ir_binop_less;    break;
  208.       case ir_binop_equal:   new_op = ir_binop_nequal;  break;
  209.       case ir_binop_nequal:  new_op = ir_binop_equal;   break;
  210.       case ir_binop_all_equal:   new_op = ir_binop_any_nequal;  break;
  211.       case ir_binop_any_nequal:  new_op = ir_binop_all_equal;   break;
  212.  
  213.       default:
  214.          /* The default case handler is here to silence a warning from GCC.
  215.           */
  216.          break;
  217.       }
  218.  
  219.       if (new_op != ir_unop_logic_not) {
  220.          this->progress = true;
  221.          return new(mem_ctx) ir_expression(new_op,
  222.                                            ir->type,
  223.                                            op_expr[0]->operands[0],
  224.                                            op_expr[0]->operands[1]);
  225.       }
  226.  
  227.       break;
  228.    }
  229.  
  230.    case ir_binop_add:
  231.       if (is_vec_zero(op_const[0])) {
  232.          this->progress = true;
  233.          return swizzle_if_required(ir, ir->operands[1]);
  234.       }
  235.       if (is_vec_zero(op_const[1])) {
  236.          this->progress = true;
  237.          return swizzle_if_required(ir, ir->operands[0]);
  238.       }
  239.  
  240.       /* Reassociate addition of constants so that we can do constant
  241.        * folding.
  242.        */
  243.       if (op_const[0] && !op_const[1])
  244.          reassociate_constant(ir, 0, op_const[0],
  245.                               ir->operands[1]->as_expression());
  246.       if (op_const[1] && !op_const[0])
  247.          reassociate_constant(ir, 1, op_const[1],
  248.                               ir->operands[0]->as_expression());
  249.       break;
  250.  
  251.    case ir_binop_sub:
  252.       if (is_vec_zero(op_const[0])) {
  253.          this->progress = true;
  254.          temp = new(mem_ctx) ir_expression(ir_unop_neg,
  255.                                            ir->operands[1]->type,
  256.                                            ir->operands[1],
  257.                                            NULL);
  258.          return swizzle_if_required(ir, temp);
  259.       }
  260.       if (is_vec_zero(op_const[1])) {
  261.          this->progress = true;
  262.          return swizzle_if_required(ir, ir->operands[0]);
  263.       }
  264.       break;
  265.  
  266.    case ir_binop_mul:
  267.       if (is_vec_one(op_const[0])) {
  268.          this->progress = true;
  269.          return swizzle_if_required(ir, ir->operands[1]);
  270.       }
  271.       if (is_vec_one(op_const[1])) {
  272.          this->progress = true;
  273.          return swizzle_if_required(ir, ir->operands[0]);
  274.       }
  275.  
  276.       if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
  277.          this->progress = true;
  278.          return ir_constant::zero(ir, ir->type);
  279.       }
  280.  
  281.       /* Reassociate multiplication of constants so that we can do
  282.        * constant folding.
  283.        */
  284.       if (op_const[0] && !op_const[1])
  285.          reassociate_constant(ir, 0, op_const[0],
  286.                               ir->operands[1]->as_expression());
  287.       if (op_const[1] && !op_const[0])
  288.          reassociate_constant(ir, 1, op_const[1],
  289.                               ir->operands[0]->as_expression());
  290.  
  291.       break;
  292.  
  293.    case ir_binop_div:
  294.       if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
  295.          this->progress = true;
  296.          temp = new(mem_ctx) ir_expression(ir_unop_rcp,
  297.                                            ir->operands[1]->type,
  298.                                            ir->operands[1],
  299.                                            NULL);
  300.          return swizzle_if_required(ir, temp);
  301.       }
  302.       if (is_vec_one(op_const[1])) {
  303.          this->progress = true;
  304.          return swizzle_if_required(ir, ir->operands[0]);
  305.       }
  306.       break;
  307.  
  308.    case ir_binop_logic_and:
  309.       /* FINISHME: Also simplify (a && a) to (a). */
  310.       if (is_vec_one(op_const[0])) {
  311.          this->progress = true;
  312.          return ir->operands[1];
  313.       } else if (is_vec_one(op_const[1])) {
  314.          this->progress = true;
  315.          return ir->operands[0];
  316.       } else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
  317.          this->progress = true;
  318.          return ir_constant::zero(mem_ctx, ir->type);
  319.       }
  320.       break;
  321.  
  322.    case ir_binop_logic_xor:
  323.       /* FINISHME: Also simplify (a ^^ a) to (false). */
  324.       if (is_vec_zero(op_const[0])) {
  325.          this->progress = true;
  326.          return ir->operands[1];
  327.       } else if (is_vec_zero(op_const[1])) {
  328.          this->progress = true;
  329.          return ir->operands[0];
  330.       } else if (is_vec_one(op_const[0])) {
  331.          this->progress = true;
  332.          return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
  333.                                            ir->operands[1], NULL);
  334.       } else if (is_vec_one(op_const[1])) {
  335.          this->progress = true;
  336.          return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
  337.                                            ir->operands[0], NULL);
  338.       }
  339.       break;
  340.  
  341.    case ir_binop_logic_or:
  342.       /* FINISHME: Also simplify (a || a) to (a). */
  343.       if (is_vec_zero(op_const[0])) {
  344.          this->progress = true;
  345.          return ir->operands[1];
  346.       } else if (is_vec_zero(op_const[1])) {
  347.          this->progress = true;
  348.          return ir->operands[0];
  349.       } else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) {
  350.          ir_constant_data data;
  351.  
  352.          for (unsigned i = 0; i < 16; i++)
  353.             data.b[i] = true;
  354.  
  355.          this->progress = true;
  356.          return new(mem_ctx) ir_constant(ir->type, &data);
  357.       }
  358.       break;
  359.  
  360.    case ir_unop_rcp:
  361.       if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) {
  362.          this->progress = true;
  363.          return op_expr[0]->operands[0];
  364.       }
  365.  
  366.       /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some
  367.        * backends, except that some backends will have done sqrt ->
  368.        * rcp(rsq(x)) and we don't want to undo it for them.
  369.        */
  370.  
  371.       /* As far as we know, all backends are OK with rsq. */
  372.       if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
  373.          this->progress = true;
  374.          temp = new(mem_ctx) ir_expression(ir_unop_rsq,
  375.                                            op_expr[0]->operands[0]->type,
  376.                                            op_expr[0]->operands[0],
  377.                                            NULL);
  378.          return swizzle_if_required(ir, temp);
  379.       }
  380.  
  381.       break;
  382.  
  383.    default:
  384.       break;
  385.    }
  386.  
  387.    return ir;
  388. }
  389.  
  390. void
  391. ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue)
  392. {
  393.    if (!*rvalue)
  394.       return;
  395.  
  396.    ir_expression *expr = (*rvalue)->as_expression();
  397.    if (!expr || expr->operation == ir_quadop_vector)
  398.       return;
  399.  
  400.    *rvalue = handle_expression(expr);
  401. }
  402.  
  403. bool
  404. do_algebraic(exec_list *instructions)
  405. {
  406.    ir_algebraic_visitor v;
  407.  
  408.    visit_list_elements(&v, instructions);
  409.  
  410.    return v.progress;
  411. }
  412.