/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * \file opt_algebraic.cpp
 *
 * Takes advantage of association, commutivity, and other algebraic
 * properties to simplify expressions.
 */

#include "ir.h"
#include "ir_visitor.h"
#include "ir_rvalue_visitor.h"
#include "ir_optimization.h"
#include "glsl_types.h"

namespace {

/**
 * Visitor class for replacing expressions with ir_constant values.
 */

class ir_algebraic_visitor : public ir_rvalue_visitor {
public:
   ir_algebraic_visitor()
   {
      this->progress = false;
      this->mem_ctx = NULL;
   }

   virtual ~ir_algebraic_visitor()
   {
   }

   ir_rvalue *handle_expression(ir_expression *ir);
   void handle_rvalue(ir_rvalue **rvalue);
   bool reassociate_constant(ir_expression *ir1,
			     int const_index,
			     ir_constant *constant,
			     ir_expression *ir2);
   void reassociate_operands(ir_expression *ir1,
			     int op1,
			     ir_expression *ir2,
			     int op2);
   ir_rvalue *swizzle_if_required(ir_expression *expr,
				  ir_rvalue *operand);

   void *mem_ctx;

   bool progress;
};

} /* unnamed namespace */

static inline bool
is_vec_zero(ir_constant *ir)
{
   return (ir == NULL) ? false : ir->is_zero();
}

static inline bool
is_vec_one(ir_constant *ir)
{
   return (ir == NULL) ? false : ir->is_one();
}

static inline bool
is_vec_basis(ir_constant *ir)
{
   return (ir == NULL) ? false : ir->is_basis();
}

static void
update_type(ir_expression *ir)
{
   if (ir->operands[0]->type->is_vector())
      ir->type = ir->operands[0]->type;
   else
      ir->type = ir->operands[1]->type;
}

void
ir_algebraic_visitor::reassociate_operands(ir_expression *ir1,
					   int op1,
					   ir_expression *ir2,
					   int op2)
{
   ir_rvalue *temp = ir2->operands[op2];
   ir2->operands[op2] = ir1->operands[op1];
   ir1->operands[op1] = temp;

   /* Update the type of ir2.  The type of ir1 won't have changed --
    * base types matched, and at least one of the operands of the 2
    * binops is still a vector if any of them were.
    */
   update_type(ir2);

   this->progress = true;
}

/**
 * Reassociates a constant down a tree of adds or multiplies.
 *
 * Consider (2 * (a * (b * 0.5))).  We want to send up with a * b.
 */
bool
ir_algebraic_visitor::reassociate_constant(ir_expression *ir1, int const_index,
					   ir_constant *constant,
					   ir_expression *ir2)
{
   if (!ir2 || ir1->operation != ir2->operation)
      return false;

   /* Don't want to even think about matrices. */
   if (ir1->operands[0]->type->is_matrix() ||
       ir1->operands[1]->type->is_matrix() ||
       ir2->operands[0]->type->is_matrix() ||
       ir2->operands[1]->type->is_matrix())
      return false;

   ir_constant *ir2_const[2];
   ir2_const[0] = ir2->operands[0]->constant_expression_value();
   ir2_const[1] = ir2->operands[1]->constant_expression_value();

   if (ir2_const[0] && ir2_const[1])
      return false;

   if (ir2_const[0]) {
      reassociate_operands(ir1, const_index, ir2, 1);
      return true;
   } else if (ir2_const[1]) {
      reassociate_operands(ir1, const_index, ir2, 0);
      return true;
   }

   if (reassociate_constant(ir1, const_index, constant,
			    ir2->operands[0]->as_expression())) {
      update_type(ir2);
      return true;
   }

   if (reassociate_constant(ir1, const_index, constant,
			    ir2->operands[1]->as_expression())) {
      update_type(ir2);
      return true;
   }

   return false;
}

/* When eliminating an expression and just returning one of its operands,
 * we may need to swizzle that operand out to a vector if the expression was
 * vector type.
 */
ir_rvalue *
ir_algebraic_visitor::swizzle_if_required(ir_expression *expr,
					  ir_rvalue *operand)
{
   if (expr->type->is_vector() && operand->type->is_scalar()) {
      return new(mem_ctx) ir_swizzle(operand, 0, 0, 0, 0,
				     expr->type->vector_elements);
   } else
      return operand;
}

ir_rvalue *
ir_algebraic_visitor::handle_expression(ir_expression *ir)
{
   ir_constant *op_const[2] = {NULL, NULL};
   ir_expression *op_expr[2] = {NULL, NULL};
   ir_expression *temp;
   unsigned int i;

   assert(ir->get_num_operands() <= 2);
   for (i = 0; i < ir->get_num_operands(); i++) {
      if (ir->operands[i]->type->is_matrix())
	 return ir;

      op_const[i] = ir->operands[i]->constant_expression_value();
      op_expr[i] = ir->operands[i]->as_expression();
   }

   if (this->mem_ctx == NULL)
      this->mem_ctx = ralloc_parent(ir);

   switch (ir->operation) {
   case ir_unop_logic_not: {
      enum ir_expression_operation new_op = ir_unop_logic_not;

      if (op_expr[0] == NULL)
	 break;

      switch (op_expr[0]->operation) {
      case ir_binop_less:    new_op = ir_binop_gequal;  break;
      case ir_binop_greater: new_op = ir_binop_lequal;  break;
      case ir_binop_lequal:  new_op = ir_binop_greater; break;
      case ir_binop_gequal:  new_op = ir_binop_less;    break;
      case ir_binop_equal:   new_op = ir_binop_nequal;  break;
      case ir_binop_nequal:  new_op = ir_binop_equal;   break;
      case ir_binop_all_equal:   new_op = ir_binop_any_nequal;  break;
      case ir_binop_any_nequal:  new_op = ir_binop_all_equal;   break;

      default:
	 /* The default case handler is here to silence a warning from GCC.
	  */
	 break;
      }

      if (new_op != ir_unop_logic_not) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(new_op,
					   ir->type,
					   op_expr[0]->operands[0],
					   op_expr[0]->operands[1]);
      }

      break;
   }

   case ir_binop_add:
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[1]);
      }
      if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }

      /* Reassociate addition of constants so that we can do constant
       * folding.
       */
      if (op_const[0] && !op_const[1])
	 reassociate_constant(ir, 0, op_const[0],
			      ir->operands[1]->as_expression());
      if (op_const[1] && !op_const[0])
	 reassociate_constant(ir, 1, op_const[1],
			      ir->operands[0]->as_expression());
      break;

   case ir_binop_sub:
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_neg,
					   ir->operands[1]->type,
					   ir->operands[1],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }
      if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }
      break;

   case ir_binop_mul:
      if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[1]);
      }
      if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }

      if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir_constant::zero(ir, ir->type);
      }

      /* Reassociate multiplication of constants so that we can do
       * constant folding.
       */
      if (op_const[0] && !op_const[1])
	 reassociate_constant(ir, 0, op_const[0],
			      ir->operands[1]->as_expression());
      if (op_const[1] && !op_const[0])
	 reassociate_constant(ir, 1, op_const[1],
			      ir->operands[0]->as_expression());

      break;

   case ir_binop_div:
      if (is_vec_one(op_const[0]) && ir->type->base_type == GLSL_TYPE_FLOAT) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_rcp,
					   ir->operands[1]->type,
					   ir->operands[1],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }
      if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return swizzle_if_required(ir, ir->operands[0]);
      }
      break;

   case ir_binop_dot:
      if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir_constant::zero(mem_ctx, ir->type);
      }
      if (is_vec_basis(op_const[0])) {
	 this->progress = true;
	 unsigned component = 0;
	 for (unsigned c = 0; c < op_const[0]->type->vector_elements; c++) {
	    if (op_const[0]->value.f[c] == 1.0)
	       component = c;
	 }
	 return new(mem_ctx) ir_swizzle(ir->operands[1], component, 0, 0, 0, 1);
      }
      if (is_vec_basis(op_const[1])) {
	 this->progress = true;
	 unsigned component = 0;
	 for (unsigned c = 0; c < op_const[1]->type->vector_elements; c++) {
	    if (op_const[1]->value.f[c] == 1.0)
	       component = c;
	 }
	 return new(mem_ctx) ir_swizzle(ir->operands[0], component, 0, 0, 0, 1);
      }
      break;

   case ir_binop_logic_and:
      /* FINISHME: Also simplify (a && a) to (a). */
      if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_zero(op_const[0]) || is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir_constant::zero(mem_ctx, ir->type);
      }
      break;

   case ir_binop_logic_xor:
      /* FINISHME: Also simplify (a ^^ a) to (false). */
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_one(op_const[0])) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
					   ir->operands[1], NULL);
      } else if (is_vec_one(op_const[1])) {
	 this->progress = true;
	 return new(mem_ctx) ir_expression(ir_unop_logic_not, ir->type,
					   ir->operands[0], NULL);
      }
      break;

   case ir_binop_logic_or:
      /* FINISHME: Also simplify (a || a) to (a). */
      if (is_vec_zero(op_const[0])) {
	 this->progress = true;
	 return ir->operands[1];
      } else if (is_vec_zero(op_const[1])) {
	 this->progress = true;
	 return ir->operands[0];
      } else if (is_vec_one(op_const[0]) || is_vec_one(op_const[1])) {
	 ir_constant_data data;

	 for (unsigned i = 0; i < 16; i++)
	    data.b[i] = true;

	 this->progress = true;
	 return new(mem_ctx) ir_constant(ir->type, &data);
      }
      break;

   case ir_unop_rcp:
      if (op_expr[0] && op_expr[0]->operation == ir_unop_rcp) {
	 this->progress = true;
	 return op_expr[0]->operands[0];
      }

      /* FINISHME: We should do rcp(rsq(x)) -> sqrt(x) for some
       * backends, except that some backends will have done sqrt ->
       * rcp(rsq(x)) and we don't want to undo it for them.
       */

      /* As far as we know, all backends are OK with rsq. */
      if (op_expr[0] && op_expr[0]->operation == ir_unop_sqrt) {
	 this->progress = true;
	 temp = new(mem_ctx) ir_expression(ir_unop_rsq,
					   op_expr[0]->operands[0]->type,
					   op_expr[0]->operands[0],
					   NULL);
	 return swizzle_if_required(ir, temp);
      }

      break;

   default:
      break;
   }

   return ir;
}

void
ir_algebraic_visitor::handle_rvalue(ir_rvalue **rvalue)
{
   if (!*rvalue)
      return;

   ir_expression *expr = (*rvalue)->as_expression();
   if (!expr || expr->operation == ir_quadop_vector)
      return;

   *rvalue = handle_expression(expr);
}

bool
do_algebraic(exec_list *instructions)
{
   ir_algebraic_visitor v;

   visit_list_elements(&v, instructions);

   return v.progress;
}
