Esempio n. 1
0
void
lower_instructions_visitor::mod_to_fract(ir_expression *ir)
{
   ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b",
					   ir_var_temporary, precision_from_ir(ir->operands[1]));
   this->base_ir->insert_before(temp);

   ir_assignment *const assign =
      new(ir) ir_assignment(new(ir) ir_dereference_variable(temp),
			    ir->operands[1], NULL);

   this->base_ir->insert_before(assign);

   ir_expression *const div_expr =
      new(ir) ir_expression(ir_binop_div, ir->operands[0]->type,
			    ir->operands[0],
			    new(ir) ir_dereference_variable(temp));

   /* Don't generate new IR that would need to be lowered in an additional
    * pass.
    */
   if (lowering(DIV_TO_MUL_RCP))
      div_to_mul_rcp(div_expr);

   ir_rvalue *expr = new(ir) ir_expression(ir_unop_fract,
					   ir->operands[0]->type,
					   div_expr,
					   NULL);

   ir->operation = ir_binop_mul;
   ir->operands[0] = new(ir) ir_dereference_variable(temp);
   ir->operands[1] = expr;
   this->progress = true;
}
ir_visitor_status
lower_instructions_visitor::visit_leave(ir_expression *ir)
{
   switch (ir->operation) {
   case ir_binop_sub:
      if (lowering(SUB_TO_ADD_NEG))
	 sub_to_add_neg(ir);
      break;

   case ir_binop_div:
      if (ir->operands[1]->type->is_integer() && lowering(INT_DIV_TO_MUL_RCP))
	 int_div_to_mul_rcp(ir);
      else if (ir->operands[1]->type->is_float() && lowering(DIV_TO_MUL_RCP))
	 div_to_mul_rcp(ir);
      break;

   case ir_unop_exp:
      if (lowering(EXP_TO_EXP2))
	 exp_to_exp2(ir);
      break;

   case ir_unop_log:
      if (lowering(LOG_TO_LOG2))
	 log_to_log2(ir);
      break;

   case ir_binop_mod:
      if (lowering(MOD_TO_FRACT) && ir->type->is_float())
	 mod_to_fract(ir);
      break;

   case ir_binop_pow:
      if (lowering(POW_TO_EXP2))
	 pow_to_exp2(ir);
      break;

   default:
      return visit_continue;
   }

   return visit_continue;
}