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; }