163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke/* 263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Copyright © 2010 Intel Corporation 363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Permission is hereby granted, free of charge, to any person obtaining a 563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * copy of this software and associated documentation files (the "Software"), 663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * to deal in the Software without restriction, including without limitation 763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * the rights to use, copy, modify, merge, publish, distribute, sublicense, 863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * and/or sell copies of the Software, and to permit persons to whom the 963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Software is furnished to do so, subject to the following conditions: 1063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 1163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * The above copyright notice and this permission notice (including the next 1263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * paragraph) shall be included in all copies or substantial portions of the 1363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Software. 1463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 1563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * DEALINGS IN THE SOFTWARE. 2263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke */ 2363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 2463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke/** 2563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * \file lower_instructions.cpp 2663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 2763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Many GPUs lack native instructions for certain expression operations, and 2863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * must replace them with some other expression tree. This pass lowers some 2963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * of the most common cases, allowing the lowering code to be implemented once 3063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * rather than in each driver backend. 3163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 3263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Currently supported transformations: 3363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * - SUB_TO_ADD_NEG 3463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * - DIV_TO_MUL_RCP 35478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * - INT_DIV_TO_MUL_RCP 3663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * - EXP_TO_EXP2 37c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick * - POW_TO_EXP2 3863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * - LOG_TO_LOG2 3963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * - MOD_TO_FRACT 4063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 4163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * SUB_TO_ADD_NEG: 4263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * --------------- 4363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Breaks an ir_binop_sub expression down to add(op0, neg(op1)) 4463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 4563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * This simplifies expression reassociation, and for many backends 4663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * there is no subtract operation separate from adding the negation. 4763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * For backends with native subtract operations, they will probably 4863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * want to recognize add(op0, neg(op1)) or the other way around to 4963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * produce a subtract anyway. 5063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 51478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * DIV_TO_MUL_RCP and INT_DIV_TO_MUL_RCP: 52478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * -------------------------------------- 531853f467c6c0a6e7636b40fe99e1195c43b847aaBrian Paul * Breaks an ir_binop_div expression down to op0 * (rcp(op1)). 5463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 5563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Many GPUs don't have a divide instruction (945 and 965 included), 5663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * but they do have an RCP instruction to compute an approximate 5763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * reciprocal. By breaking the operation down, constant reciprocals 5863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * can get constant folded. 5963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 60478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * DIV_TO_MUL_RCP only lowers floating point division; INT_DIV_TO_MUL_RCP 61478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * handles the integer case, converting to and from floating point so that 62478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * RCP is possible. 63478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * 6463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * EXP_TO_EXP2 and LOG_TO_LOG2: 6563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * ---------------------------- 6663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Many GPUs don't have a base e log or exponent instruction, but they 6763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * do have base 2 versions, so this pass converts exp and log to exp2 6863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * and log2 operations. 6963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 70c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick * POW_TO_EXP2: 71c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick * ----------- 72c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick * Many older GPUs don't have an x**y instruction. For these GPUs, convert 73c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick * x**y to 2**(y * log2(x)). 74c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick * 7563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * MOD_TO_FRACT: 7663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * ------------- 771853f467c6c0a6e7636b40fe99e1195c43b847aaBrian Paul * Breaks an ir_binop_mod expression down to (op1 * fract(op0 / op1)) 7863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * 7963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Many GPUs don't have a MOD instruction (945 and 965 included), and 8063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * if we have to break it down like this anyway, it gives an 8163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * opportunity to do things like constant fold the (1.0 / op1) easily. 8263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke */ 8363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 84da61afa7388f1ce50ef612b89aba2302a052a3bbIan Romanick#include "main/core.h" /* for M_LOG2E */ 8563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke#include "glsl_types.h" 8663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke#include "ir.h" 8763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke#include "ir_optimization.h" 8863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 8963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkeclass lower_instructions_visitor : public ir_hierarchical_visitor { 9063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkepublic: 9163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke lower_instructions_visitor(unsigned lower) 9263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke : progress(false), lower(lower) { } 9363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 9463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir_visitor_status visit_leave(ir_expression *); 9563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 9663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke bool progress; 9763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 9863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkeprivate: 9963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke unsigned lower; /** Bitfield of which operations to lower */ 10063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 10163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke void sub_to_add_neg(ir_expression *); 10263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke void div_to_mul_rcp(ir_expression *); 103478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain void int_div_to_mul_rcp(ir_expression *); 10463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke void mod_to_fract(ir_expression *); 10563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke void exp_to_exp2(ir_expression *); 106c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick void pow_to_exp2(ir_expression *); 10763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke void log_to_log2(ir_expression *); 10863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke}; 10963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 11063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke/** 11163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * Determine if a particular type of lowering should occur 11263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke */ 11363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke#define lowering(x) (this->lower & x) 11463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 11563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkebool 11663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkelower_instructions(exec_list *instructions, unsigned what_to_lower) 11763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke{ 11863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke lower_instructions_visitor v(what_to_lower); 11963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 12063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke visit_list_elements(&v, instructions); 12163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke return v.progress; 12263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke} 12363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 12463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkevoid 12563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkelower_instructions_visitor::sub_to_add_neg(ir_expression *ir) 12663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke{ 12763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operation = ir_binop_add; 12863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[1] = new(ir) ir_expression(ir_unop_neg, ir->operands[1]->type, 12963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[1], NULL); 13063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke this->progress = true; 13163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke} 13263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 13363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkevoid 13463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkelower_instructions_visitor::div_to_mul_rcp(ir_expression *ir) 13563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke{ 136478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain assert(ir->operands[1]->type->is_float()); 137478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 138478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain /* New expression for the 1.0 / op1 */ 139478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir_rvalue *expr; 140478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain expr = new(ir) ir_expression(ir_unop_rcp, 141478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[1]->type, 142478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[1]); 143478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 144478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain /* op0 / op1 -> op0 * (1.0 / op1) */ 145478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operation = ir_binop_mul; 146478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[1] = expr; 147478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 148478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain this->progress = true; 149478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain} 150478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 151478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cainvoid 152478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cainlower_instructions_visitor::int_div_to_mul_rcp(ir_expression *ir) 153478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain{ 154478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain assert(ir->operands[1]->type->is_integer()); 155478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 156478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain /* Be careful with integer division -- we need to do it as a 157478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * float and re-truncate, since rcp(n > 1) of an integer would 158478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain * just be 0. 159478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain */ 160478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir_rvalue *op0, *op1; 161478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain const struct glsl_type *vec_type; 162478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 163478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 164478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[1]->type->vector_elements, 165478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[1]->type->matrix_columns); 166478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 167478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain if (ir->operands[1]->type->base_type == GLSL_TYPE_INT) 168478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain op1 = new(ir) ir_expression(ir_unop_i2f, vec_type, ir->operands[1], NULL); 169478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain else 170478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain op1 = new(ir) ir_expression(ir_unop_u2f, vec_type, ir->operands[1], NULL); 171478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 172478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain op1 = new(ir) ir_expression(ir_unop_rcp, op1->type, op1, NULL); 173478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 174478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 175478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[0]->type->vector_elements, 176478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[0]->type->matrix_columns); 177478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 178478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain if (ir->operands[0]->type->base_type == GLSL_TYPE_INT) 179478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain op0 = new(ir) ir_expression(ir_unop_i2f, vec_type, ir->operands[0], NULL); 180478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain else 181478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain op0 = new(ir) ir_expression(ir_unop_u2f, vec_type, ir->operands[0], NULL); 182478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 183478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain vec_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 184478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->type->vector_elements, 185478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->type->matrix_columns); 186478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 187478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain op0 = new(ir) ir_expression(ir_binop_mul, vec_type, op0, op1); 188478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain 189478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain if (ir->operands[1]->type->base_type == GLSL_TYPE_INT) { 190478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operation = ir_unop_f2i; 191478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[0] = op0; 19263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke } else { 193478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operation = ir_unop_i2u; 194478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[0] = new(ir) ir_expression(ir_unop_f2i, op0); 19563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke } 196478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain ir->operands[1] = NULL; 19763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 19863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke this->progress = true; 19963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke} 20063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 20163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkevoid 20263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkelower_instructions_visitor::exp_to_exp2(ir_expression *ir) 20363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke{ 204da61afa7388f1ce50ef612b89aba2302a052a3bbIan Romanick ir_constant *log2_e = new(ir) ir_constant(float(M_LOG2E)); 20563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 20663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operation = ir_unop_exp2; 20763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[0] = new(ir) ir_expression(ir_binop_mul, ir->operands[0]->type, 20863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[0], log2_e); 20963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke this->progress = true; 21063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke} 21163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 21263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkevoid 213c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanicklower_instructions_visitor::pow_to_exp2(ir_expression *ir) 214c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick{ 215c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick ir_expression *const log2_x = 216c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick new(ir) ir_expression(ir_unop_log2, ir->operands[0]->type, 217c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick ir->operands[0]); 218c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick 219c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick ir->operation = ir_unop_exp2; 220c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick ir->operands[0] = new(ir) ir_expression(ir_binop_mul, ir->operands[1]->type, 221c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick ir->operands[1], log2_x); 222c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick ir->operands[1] = NULL; 223c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick this->progress = true; 224c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick} 225c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick 226c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanickvoid 22763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkelower_instructions_visitor::log_to_log2(ir_expression *ir) 22863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke{ 22963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operation = ir_binop_mul; 23063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[0] = new(ir) ir_expression(ir_unop_log2, ir->operands[0]->type, 23163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[0], NULL); 232da61afa7388f1ce50ef612b89aba2302a052a3bbIan Romanick ir->operands[1] = new(ir) ir_constant(float(1.0 / M_LOG2E)); 23363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke this->progress = true; 23463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke} 23563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 23663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkevoid 23763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkelower_instructions_visitor::mod_to_fract(ir_expression *ir) 23863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke{ 23963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b", 24063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir_var_temporary); 24163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke this->base_ir->insert_before(temp); 24263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 24363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir_assignment *const assign = 24463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke new(ir) ir_assignment(new(ir) ir_dereference_variable(temp), 24563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[1], NULL); 24663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 24763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke this->base_ir->insert_before(assign); 24863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 24963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir_expression *const div_expr = 25063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke new(ir) ir_expression(ir_binop_div, ir->operands[0]->type, 25163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[0], 25263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke new(ir) ir_dereference_variable(temp)); 25363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 25463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke /* Don't generate new IR that would need to be lowered in an additional 25563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke * pass. 25663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke */ 25763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke if (lowering(DIV_TO_MUL_RCP)) 25863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke div_to_mul_rcp(div_expr); 25963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 26063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir_rvalue *expr = new(ir) ir_expression(ir_unop_fract, 26163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[0]->type, 26263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke div_expr, 26363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke NULL); 26463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 26563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operation = ir_binop_mul; 26663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[0] = new(ir) ir_dereference_variable(temp); 26763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke ir->operands[1] = expr; 26863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke this->progress = true; 26963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke} 27063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 27163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkeir_visitor_status 27263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunkelower_instructions_visitor::visit_leave(ir_expression *ir) 27363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke{ 27463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke switch (ir->operation) { 27563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke case ir_binop_sub: 27663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke if (lowering(SUB_TO_ADD_NEG)) 27763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke sub_to_add_neg(ir); 27863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke break; 27963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 28063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke case ir_binop_div: 281478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain if (ir->operands[1]->type->is_integer() && lowering(INT_DIV_TO_MUL_RCP)) 282478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain int_div_to_mul_rcp(ir); 283478034f34a59969103237eb78bc82f9e70fe81c2Bryan Cain else if (ir->operands[1]->type->is_float() && lowering(DIV_TO_MUL_RCP)) 28463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke div_to_mul_rcp(ir); 28563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke break; 28663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 28763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke case ir_unop_exp: 28863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke if (lowering(EXP_TO_EXP2)) 28963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke exp_to_exp2(ir); 29063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke break; 29163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 29263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke case ir_unop_log: 29363684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke if (lowering(LOG_TO_LOG2)) 29463684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke log_to_log2(ir); 29563684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke break; 29663684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 29763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke case ir_binop_mod: 298578f6a9534ec6ea1ffc6638b98f0b5570a85a19dKenneth Graunke if (lowering(MOD_TO_FRACT) && ir->type->is_float()) 29963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke mod_to_fract(ir); 30063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke break; 30163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 302c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick case ir_binop_pow: 303c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick if (lowering(POW_TO_EXP2)) 304c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick pow_to_exp2(ir); 305c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick break; 306c4285be9a5bd1adaa89050989374b95a9a601cdcIan Romanick 30763684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke default: 30863684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke return visit_continue; 30963684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke } 31063684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke 31163684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke return visit_continue; 31263684a9ae7a66f68df1f2c68cd9358e5622122a3Kenneth Graunke} 313