1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2020 Collabora, Ltd. 3bf215546Sopenharmony_ci * Copyright (C) 2014 Intel Corporation 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22bf215546Sopenharmony_ci * IN THE SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci * Authors: 25bf215546Sopenharmony_ci * Alyssa Rosenzweig <alyssa@collabora.com> 26bf215546Sopenharmony_ci * Jason Ekstrand (jason@jlekstrand.net) 27bf215546Sopenharmony_ci * 28bf215546Sopenharmony_ci */ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "nir.h" 31bf215546Sopenharmony_ci#include "pan_ir.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci/* Check if a given ALU source is the result of a particular componentwise 1-op 34bf215546Sopenharmony_ci * ALU source (principally fneg or fabs). If so, return true and rewrite the 35bf215546Sopenharmony_ci * source to be the argument, respecting swizzles as needed. If not (or it 36bf215546Sopenharmony_ci * cannot be proven), return false and leave the source untouched. 37bf215546Sopenharmony_ci*/ 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_cibool 40bf215546Sopenharmony_cipan_has_source_mod(nir_alu_src *src, nir_op op) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci if (!src->src.is_ssa || src->src.ssa->parent_instr->type != nir_instr_type_alu) 43bf215546Sopenharmony_ci return false; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci nir_alu_instr *alu = nir_instr_as_alu(src->src.ssa->parent_instr); 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci if (alu->op != op) 48bf215546Sopenharmony_ci return false; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci /* This only works for unary ops */ 51bf215546Sopenharmony_ci assert(nir_op_infos[op].num_inputs == 1); 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci /* If the copied source is not SSA, moving it might not be valid */ 54bf215546Sopenharmony_ci if (!alu->src[0].src.is_ssa) 55bf215546Sopenharmony_ci return false; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci /* Okay - we've found the modifier we wanted. Let's construct the new ALU 58bf215546Sopenharmony_ci * src. In a scalar world, this is just psrc, but for vector archs we need 59bf215546Sopenharmony_ci * to respect the swizzle, so we compose. 60bf215546Sopenharmony_ci */ 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci nir_alu_src nsrc = { 63bf215546Sopenharmony_ci .src = alu->src[0].src, 64bf215546Sopenharmony_ci }; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; ++i) { 67bf215546Sopenharmony_ci /* (a o b)(i) = a(b(i)) ... swizzle composition is intense. */ 68bf215546Sopenharmony_ci nsrc.swizzle[i] = alu->src[0].swizzle[src->swizzle[i]]; 69bf215546Sopenharmony_ci } 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci *src = nsrc; 72bf215546Sopenharmony_ci return true; 73bf215546Sopenharmony_ci} 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci/* Check if a given instruction's result will be fed into a 76bf215546Sopenharmony_ci * componentwise 1-op ALU instruction (principally fsat without 77bf215546Sopenharmony_ci * swizzles). If so, return true and rewrite the destination. The 78bf215546Sopenharmony_ci * backend will need to track the new destinations to avoid 79bf215546Sopenharmony_ci * incorrect double-emits. */ 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cibool 82bf215546Sopenharmony_cipan_has_dest_mod(nir_dest **odest, nir_op op) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci /* This only works for unary ops */ 85bf215546Sopenharmony_ci assert(nir_op_infos[op].num_inputs == 1); 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci /* If not SSA, this might not be legal */ 88bf215546Sopenharmony_ci nir_dest *dest = *odest; 89bf215546Sopenharmony_ci if (!dest->is_ssa) 90bf215546Sopenharmony_ci return false; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci /* Check the uses. We want a single use, with the op `op` */ 93bf215546Sopenharmony_ci if (!list_is_empty(&dest->ssa.if_uses)) 94bf215546Sopenharmony_ci return false; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci if (!list_is_singular(&dest->ssa.uses)) 97bf215546Sopenharmony_ci return false; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci nir_src *use = list_first_entry(&dest->ssa.uses, nir_src, use_link); 100bf215546Sopenharmony_ci nir_instr *parent = use->parent_instr; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci /* Check if the op is `op` */ 103bf215546Sopenharmony_ci if (parent->type != nir_instr_type_alu) 104bf215546Sopenharmony_ci return false; 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci nir_alu_instr *alu = nir_instr_as_alu(parent); 107bf215546Sopenharmony_ci if (alu->op != op) 108bf215546Sopenharmony_ci return false; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci /* We can't do expansions without a move in the middle */ 111bf215546Sopenharmony_ci unsigned nr_components = nir_dest_num_components(alu->dest.dest); 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (nir_dest_num_components(*dest) != nr_components) 114bf215546Sopenharmony_ci return false; 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci /* We don't handle swizzles here, so check for the identity */ 117bf215546Sopenharmony_ci for (unsigned i = 0; i < nr_components; ++i) { 118bf215546Sopenharmony_ci if (alu->src[0].swizzle[i] != i) 119bf215546Sopenharmony_ci return false; 120bf215546Sopenharmony_ci } 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci if (!alu->dest.dest.is_ssa) 123bf215546Sopenharmony_ci return false; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci /* Otherwise, we're good */ 126bf215546Sopenharmony_ci *odest = &alu->dest.dest; 127bf215546Sopenharmony_ci return true; 128bf215546Sopenharmony_ci} 129